From: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Wed, 30 Dec 2020 22:44:48 +0000 (-0800)
Subject: Add support for workspace folders
X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=5fb6cd001f1d59c1f545e61ca86308d2e09b65c8;p=vim-lsp.git

Add support for workspace folders
---

diff --git a/autoload/lsp.vim b/autoload/lsp.vim
index 8bf65c3..bc3e1ee 100644
--- a/autoload/lsp.vim
+++ b/autoload/lsp.vim
@@ -1127,6 +1127,7 @@ def s:initServer(lspserver: dict<any>)
 
   var clientCaps: dict<any> = {
 	'workspace': {
+	    'workspaceFolders': v:true,
 	    'applyEdit': v:true,
 	},
 	'textDocument': {},
@@ -1183,6 +1184,7 @@ def s:startServer(lspserver: dict<any>): number
   lspserver.nextID = 1
   lspserver.requests = {}
   lspserver.completePending = v:false
+  lspserver.workspaceFolders = [getcwd()]
 
   var job = job_start(cmd, opts)
   if job->job_status() == 'fail'
@@ -2267,4 +2269,127 @@ def lsp#showWorkspaceSymbols()
   lspserver.sendMessage(req)
 enddef
 
+# Display the list of workspace folders
+def lsp#listWorkspaceFolders()
+  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
+
+  echomsg 'Workspace Folders: ' .. string(lspserver.workspaceFolders)
+enddef
+
+# Add a workspace folder. Default is to use the current folder.
+def lsp#addWorkspaceFolder(dirArg: string)
+  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
+
+  if !lspserver.caps->has_key('workspace')
+	  || !lspserver.caps.workspace->has_key('workspaceFolders')
+	  || !lspserver.caps.workspace.workspaceFolders->has_key('supported')
+	  || !lspserver.caps.workspace.workspaceFolders.supported
+      ErrMsg('Error: LSP server does not support workspace folders')
+    return
+  endif
+
+  var dirName: string = dirArg
+  if dirName == ''
+    dirName = input("Add Workspace Folder: ", getcwd(), 'dir')
+    if dirName == ''
+      return
+    endif
+  endif
+  :redraw!
+  if !dirName->isdirectory()
+    ErrMsg('Error: ' .. dirName .. ' is not a directory')
+    return
+  endif
+
+  if lspserver.workspaceFolders->index(dirName) != -1
+    ErrMsg('Error: ' .. dirName .. ' is already part of this workspace')
+    return
+  endif
+
+  var notif: dict<any> = lspserver.createNotification('workspace/didChangeWorkspaceFolders')
+  # interface DidChangeWorkspaceFoldersParams
+  notif.params->extend({'event': {'added': [dirName], 'removed': []}})
+  lspserver.sendMessage(notif)
+
+  lspserver.workspaceFolders->add(dirName)
+enddef
+
+# Remove a workspace folder. Default is to use the current folder.
+def lsp#removeWorkspaceFolder(dirArg: string)
+  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
+
+  if !lspserver.caps->has_key('workspace')
+	  || !lspserver.caps.workspace->has_key('workspaceFolders')
+	  || !lspserver.caps.workspace.workspaceFolders->has_key('supported')
+	  || !lspserver.caps.workspace.workspaceFolders.supported
+      ErrMsg('Error: LSP server does not support workspace folders')
+    return
+  endif
+
+  var dirName: string = dirArg
+  if dirName == ''
+    dirName = input("Remove Workspace Folder: ", getcwd(), 'dir')
+    if dirName == ''
+      return
+    endif
+  endif
+  :redraw!
+  if !dirName->isdirectory()
+    ErrMsg('Error: ' .. dirName .. ' is not a directory')
+    return
+  endif
+
+  var idx: number = lspserver.workspaceFolders->index(dirName)
+  if idx == -1
+    ErrMsg('Error: ' .. dirName .. ' is not currently part of this workspace')
+    return
+  endif
+
+  var notif: dict<any> = lspserver.createNotification('workspace/didChangeWorkspaceFolders')
+  # interface DidChangeWorkspaceFoldersParams
+  notif.params->extend({'event': {'added': [], 'removed': [dirName]}})
+  lspserver.sendMessage(notif)
+
+  lspserver.workspaceFolders->remove(idx)
+enddef
+
 # vim: shiftwidth=2 softtabstop=2
diff --git a/plugin/lsp.vim b/plugin/lsp.vim
index b701a16..06ca1c4 100644
--- a/plugin/lsp.vim
+++ b/plugin/lsp.vim
@@ -36,4 +36,7 @@ command! -nargs=0 -bar LspCalling call lsp#outgoingCalls()
 command! -nargs=0 -bar LspRename call lsp#rename()
 command! -nargs=0 -bar LspCodeAction call lsp#codeAction()
 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>)