]> Sergey Matveev's repositories - vim-lsp.git/commitdiff
Add support selection ranges and folding
authorYegappan Lakshmanan <yegappan@yahoo.com>
Thu, 31 Dec 2020 21:23:39 +0000 (13:23 -0800)
committerYegappan Lakshmanan <yegappan@yahoo.com>
Thu, 31 Dec 2020 21:23:39 +0000 (13:23 -0800)
autoload/handlers.vim
autoload/lsp.vim
autoload/lspserver.vim
plugin/lsp.vim

index 89bca568281941072fa51b1f98697470811e5950..2b2a31e61b93a12013039ed65a16ebc362b044aa 100644 (file)
@@ -713,6 +713,36 @@ def s:processCodeActionReply(lspserver: dict<any>, req: dict<any>, reply: dict<a
   endif
 enddef
 
+# process the 'textDocument/selectionRange' reply from the LSP server
+def s:processSelectionRangeReply(lspserver: dict<any>, req: dict<any>, reply: dict<any>)
+  if reply.result->empty()
+    return
+  endif
+
+  var r: dict<dict<number>> = reply.result[0].range
+
+  setpos("'<", [0, r.start.line + 1, r.start.character + 1, 0])
+  setpos("'>", [0, r.end.line + 1, r.end.character, 0])
+  :normal gv
+enddef
+
+# process the 'textDocument/foldingRange' reply from the LSP server
+def s:processFoldingRangeReply(lspserver: dict<any>, req: dict<any>, reply: dict<any>)
+  if reply.result->empty()
+    return
+  endif
+
+  # result: FoldingRange[]
+  for foldRange in reply.result
+    exe ':' .. (foldRange.startLine + 1) .. ',' .. (foldRange.endLine + 2) .. 'fold'
+    :foldopen!
+  endfor
+
+  if &foldcolumn == 0
+    :setlocal foldcolumn=2
+  endif
+enddef
+
 # process the 'workspace/executeCommand' reply from the LSP server
 def s:processWorkspaceExecuteReply(lspserver: dict<any>, req: dict<any>, reply: dict<any>)
   if reply.result->empty()
@@ -751,6 +781,8 @@ export def ProcessReply(lspserver: dict<any>, req: dict<any>, reply: dict<any>):
       'textDocument/rangeFormatting': function('s:processFormatReply'),
       'textDocument/rename': function('s:processRenameReply'),
       'textDocument/codeAction': function('s:processCodeActionReply'),
+      'textDocument/selectionRange': function('s:processSelectionRangeReply'),
+      'textDocument/foldingRange': function('s:processFoldingRangeReply'),
       'workspace/executeCommand': function('s:processWorkspaceExecuteReply'),
       'workspace/symbol': function('s:processWorkspaceSymbolReply')
     }
index 95e41df2d1846d0a719e7b15a102ed36e371d61b..b1295bbab5e6b3256547a041de6e91837c32a712 100644 (file)
@@ -755,4 +755,60 @@ def lsp#removeWorkspaceFolder(dirArg: string)
   lspserver.removeWorkspaceFolder(dirName)
 enddef
 
+# visually select a range of positions around the current cursor.
+def lsp#selectionRange()
+  var ftype = &filetype
+  if ftype == ''
+    return
+  endif
+
+  var lspserver: dict<any> = s:lspGetServer(ftype)
+  if lspserver->empty()
+    ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found')
+    return
+  endif
+  if !lspserver.running
+    ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running')
+    return
+  endif
+
+  var fname = @%
+  if fname == ''
+    return
+  endif
+
+  # TODO: Also support passing a range
+  lspserver.selectionRange(fname)
+enddef
+
+# fold the entire document
+def lsp#foldDocument()
+  var ftype = &filetype
+  if ftype == ''
+    return
+  endif
+
+  var lspserver: dict<any> = s:lspGetServer(ftype)
+  if lspserver->empty()
+    ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found')
+    return
+  endif
+  if !lspserver.running
+    ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running')
+    return
+  endif
+
+  var fname = @%
+  if fname == ''
+    return
+  endif
+
+  if &foldmethod != 'manual'
+    ErrMsg("Error: Only works when 'foldmethod' is 'manual'")
+    return
+  endif
+
+  lspserver.foldRange(fname)
+enddef
+
 # vim: shiftwidth=2 softtabstop=2
index 12cb8b44095a455a11fc456a8a089e8417787341..619fa3413be6b77632feba5a56df0cb6e27eddf4 100644 (file)
@@ -73,14 +73,16 @@ def s:initServer(lspserver: dict<any>)
   var req = lspserver.createRequest('initialize')
 
   var clientCaps: dict<any> = {
-       workspace: {
-           workspaceFolders: v:true,
-           applyEdit: v:true,
-       },
-       textDocument: {},
-       window: {},
-       general: {}
-    }
+    workspace: {
+      workspaceFolders: v:true,
+      applyEdit: v:true,
+    },
+    textDocument: {
+      foldingRange: {lineFoldingOnly: v:true}
+    },
+    window: {},
+    general: {}
+  }
 
   # interface 'InitializeParams'
   var initparams: dict<any> = {}
@@ -655,6 +657,39 @@ def s:removeWorkspaceFolder(lspserver: dict<any>, dirName: string): void
   lspserver.workspaceFolders->remove(idx)
 enddef
 
+# select the text around the current cursor location
+def s:selectionRange(lspserver: dict<any>, fname: string)
+  # Check whether LSP server supports selection ranges
+  if !lspserver.caps->has_key('selectionRangeProvider')
+                       || !lspserver.caps.selectionRangeProvider
+    ErrMsg("Error: LSP server does not support selection ranges")
+    return
+  endif
+
+  var req = lspserver.createRequest('textDocument/selectionRange')
+  # interface SelectionRangeParams
+  # interface TextDocumentIdentifier
+  req.params->extend({textDocument: {uri: LspFileToUri(fname)}})
+  req.params->extend({positions: [s:getLspPosition()]})
+  lspserver.sendMessage(req)
+enddef
+
+# fold the entire document
+def s:foldRange(lspserver: dict<any>, fname: string)
+  # Check whether LSP server supports fold ranges
+  if !lspserver.caps->has_key('foldingRangeProvider')
+                       || !lspserver.caps.foldingRangeProvider
+    ErrMsg("Error: LSP server does not support folding")
+    return
+  endif
+
+  var req = lspserver.createRequest('textDocument/foldingRange')
+  # interface FoldingRangeParams
+  # interface TextDocumentIdentifier
+  req.params->extend({textDocument: {uri: LspFileToUri(fname)}})
+  lspserver.sendMessage(req)
+enddef
+
 export def NewLspServer(path: string, args: list<string>): dict<any>
   var lspserver: dict<any> = {
     path: path,
@@ -706,7 +741,9 @@ export def NewLspServer(path: string, args: list<string>): dict<any>
     codeAction: function('s:codeAction', [lspserver]),
     workspaceSymbols: function('s:workspaceSymbols', [lspserver]),
     addWorkspaceFolder: function('s:addWorkspaceFolder', [lspserver]),
-    removeWorkspaceFolder: function('s:removeWorkspaceFolder', [lspserver])
+    removeWorkspaceFolder: function('s:removeWorkspaceFolder', [lspserver]),
+    selectionRange: function('s:selectionRange', [lspserver]),
+    foldRange: function('s:foldRange', [lspserver])
   })
 
   return lspserver
index 06ca1c4cd10f4157b233d85adfa0e89ff03fc382..b97d0f30492d5b2d92204f0ab9f04f8b133978ec 100644 (file)
@@ -39,4 +39,5 @@ command! -nargs=0 -bar LspShowWorkspaceSymbols call lsp#showWorkspaceSymbols()
 command! -nargs=0 -bar LspWorkspaceListFolders call lsp#listWorkspaceFolders()
 command! -nargs=1 -bar -complete=dir LspWorkspaceAddFolder call lsp#addWorkspaceFolder(<q-args>)
 command! -nargs=1 -bar -complete=dir LspWorkspaceRemoveFolder call lsp#removeWorkspaceFolder(<q-args>)
-
+command! -nargs=0 -bar LspSelectionRange call lsp#selectionRange()
+command! -nargs=0 -bar LspFold call lsp#foldDocument()