From 5fb6cd001f1d59c1f545e61ca86308d2e09b65c8 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Wed, 30 Dec 2020 14:44:48 -0800 Subject: [PATCH] Add support for workspace folders --- autoload/lsp.vim | 125 +++++++++++++++++++++++++++++++++++++++++++++++ plugin/lsp.vim | 3 ++ 2 files changed, 128 insertions(+) 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) var clientCaps: dict = { 'workspace': { + 'workspaceFolders': v:true, 'applyEdit': v:true, }, 'textDocument': {}, @@ -1183,6 +1184,7 @@ def s:startServer(lspserver: dict): 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 = 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 = 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 = 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 = 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 = 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() +command! -nargs=1 -bar -complete=dir LspWorkspaceRemoveFolder call lsp#removeWorkspaceFolder() -- 2.48.1