From 7e96e154fbbd31655989bd0aa5531b3bdba15f51 Mon Sep 17 00:00:00 2001 From: Andreas Louv Date: Sat, 8 Apr 2023 23:01:39 +0200 Subject: [PATCH] Make it possible to have multiple servers registred for a given filetype --- autoload/lsp/lsp.vim | 67 +++++++++++++++++++++++++++++++++----------- doc/lsp.txt | 17 +++++++---- 2 files changed, 63 insertions(+), 21 deletions(-) diff --git a/autoload/lsp/lsp.vim b/autoload/lsp/lsp.vim index 7b85dec..a1ff940 100644 --- a/autoload/lsp/lsp.vim +++ b/autoload/lsp/lsp.vim @@ -26,7 +26,7 @@ import './inlayhints.vim' var lspServers: list> = [] # filetype to LSP server map -var ftypeServerMap: dict> = {} +var ftypeServerMap: dict>> = {} var lspInitializedOnce = false @@ -45,13 +45,41 @@ enddef # Returns the LSP server for the a specific filetype. Returns an empty dict if # the server is not found. -def LspGetServer(ftype: string): dict - return ftypeServerMap->get(ftype, {}) +def LspGetServer(bnr: number, ftype: string): dict + if ftypeServerMap->has_key(ftype) + var lspservers = ftypeServerMap[ftype] + + # The best language server for the current buffer + var bestMatch: dict = {} + var bestScore: number = -1 + + var bufDir = bnr->bufname()->fnamemodify(':p:h') + + for lspserver in lspservers + var score: number = 0 + if !lspserver.rootSearchFiles->empty() + # The score is calculated by how deep the workspace root dir is, the + # deeper the better. + var path = util.FindNearestRootDir(bufDir, lspserver.rootSearchFiles) + score = path->strcharlen() + endif + if score > bestScore + bestMatch = lspserver + bestScore = score + endif + endfor + + return bestMatch + endif + + return {} enddef # Add a LSP server for a filetype def LspAddServer(ftype: string, lspsrv: dict) - ftypeServerMap->extend({[ftype]: lspsrv}) + var lspsrvlst = ftypeServerMap->has_key(ftype) ? ftypeServerMap[ftype] : [] + lspsrvlst->add(lspsrv) + ftypeServerMap[ftype] = lspsrvlst enddef # Enable/disable the logging of the language server protocol messages @@ -85,11 +113,14 @@ export def ShowAllServers() # Add filetype to server mapping information lines->add('Filetype Information') lines->add('====================') - for [ftype, lspserver] in ftypeServerMap->items() - lines->add($"Filetype: '{ftype}'") - lines->add($"Server Path: '{lspserver.path}'") - lines->add($"Status: {lspserver.running ? 'Running' : 'Not running'}") - lines->add('') + for [ftype, lspservers] in ftypeServerMap->items() + for lspserver in lspservers + lines->add($"Filetype: '{ftype}'") + lines->add($"Server Name: '{lspserver.name}'") + lines->add($"Server Path: '{lspserver.path}'") + lines->add($"Status: {lspserver.running ? 'Running' : 'Not running'}") + lines->add('') + endfor endfor # Add buffer to server mapping information @@ -143,12 +174,16 @@ enddef # Get LSP server running status for filetype 'ftype' # Return true if running, or false if not found or not running export def ServerRunning(ftype: string): bool - for [ft, lspserver] in ftypeServerMap->items() - if ftype ==# ft - return lspserver.running - endif - endfor - return v:false + if ftypeServerMap->has_key(ftype) + var lspservers = ftypeServerMap[ftype] + for lspserver in lspservers + if lspserver.running + return true + endif + endfor + endif + + return false enddef # Go to a definition using "textDocument/definition" LSP request @@ -363,7 +398,7 @@ export def AddFile(bnr: number): void if ftype == '' return endif - var lspserver: dict = LspGetServer(ftype) + var lspserver: dict = LspGetServer(bnr, ftype) if lspserver->empty() return endif diff --git a/doc/lsp.txt b/doc/lsp.txt index 56e5802..acd4cac 100644 --- a/doc/lsp.txt +++ b/doc/lsp.txt @@ -269,11 +269,18 @@ To add a language server, the following information is needed: searched upwards in all the parent directories. If multiple directories are found, then the directory closest to the directory of the current buffer is used - as the workspace root. If this parameter is not - specified or the files are not found, then the current - working directory is used as the workspace root for - decendent files, for any other files the parent - directory of the file is used. + as the workspace root. + + This option is also used to decide which server to run + when multiple servers are defined for a filetype. The + server with the longest found workspace root will be + selected as the relevant language server for a given + file. + + If this parameter is not specified or the files are not + found, then the current working directory is used as the + workspace root for decendent files, for any other files + the parent directory of the file is used. Aditionally the following configurations can be made: -- 2.48.1