From: Yegappan Lakshmanan Date: Sun, 18 Jun 2023 04:39:08 +0000 (-0700) Subject: :LspSymbolSeach command doesn't support command modifiers. When only one symbol is... X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=f81f8edff4561a94c2d9eac011f98d5737586d65;p=vim-lsp.git :LspSymbolSeach command doesn't support command modifiers. When only one symbol is found, jump to it --- diff --git a/autoload/lsp/lsp.vim b/autoload/lsp/lsp.vim index a2d7bed..730527a 100644 --- a/autoload/lsp/lsp.vim +++ b/autoload/lsp/lsp.vim @@ -952,7 +952,7 @@ enddef # Perform a workspace wide symbol lookup # Uses LSP "workspace/symbol" request -export def SymbolSearch(queryArg: string) +export def SymbolSearch(queryArg: string, cmdmods: string) var lspserver: dict = buf.CurbufGetServerChecked() if lspserver->empty() return @@ -967,7 +967,7 @@ export def SymbolSearch(queryArg: string) endif :redraw! - lspserver.workspaceQuery(query) + lspserver.workspaceQuery(query, true, cmdmods) enddef # Display the list of workspace folders diff --git a/autoload/lsp/lspserver.vim b/autoload/lsp/lspserver.vim index 03d89bd..3ef58dc 100644 --- a/autoload/lsp/lspserver.vim +++ b/autoload/lsp/lspserver.vim @@ -1433,7 +1433,7 @@ enddef # List project-wide symbols matching query string # Request: "workspace/symbol" # Param: WorkspaceSymbolParams -def WorkspaceQuerySymbols(lspserver: dict, query: string) +def WorkspaceQuerySymbols(lspserver: dict, query: string, firstCall: bool, cmdmods: string = '') # Check whether the LSP server supports listing workspace symbols if !lspserver.isWorkspaceSymbolProvider util.ErrMsg('LSP server does not support listing workspace symbols') @@ -1449,7 +1449,24 @@ def WorkspaceQuerySymbols(lspserver: dict, query: string) return endif - symbol.WorkspaceSymbolPopup(lspserver, query, reply.result) + var symInfo: list> = reply.result + + symInfo->map((_, sym) => { + if sym->has_key('location') + lspserver.decodeLocation(sym.location) + endif + return sym + }) + + if firstCall && symInfo->len() == 1 + # If there is only one symbol, then jump to the symbol location + var symLoc: dict = symInfo[0]->get('location', {}) + if !symLoc->empty() + symbol.GotoSymbol(lspserver, symLoc, false, cmdmods) + endif + else + symbol.WorkspaceSymbolPopup(lspserver, query, symInfo, cmdmods) + endif enddef # Add a workspace folder to the language server. diff --git a/autoload/lsp/symbol.vim b/autoload/lsp/symbol.vim index 177c761..ae19387 100644 --- a/autoload/lsp/symbol.vim +++ b/autoload/lsp/symbol.vim @@ -54,7 +54,7 @@ def FilterSymbols(lspserver: dict, popupID: number, key: string): bool # Update the popup with the new list of symbol names popupID->popup_settext('') if query != '' - lspserver.workspaceQuery(query) + lspserver.workspaceQuery(query, false) else []->setwinvar(popupID, 'LspSymbolTable') endif @@ -72,7 +72,7 @@ def FilterSymbols(lspserver: dict, popupID: number, key: string): bool enddef # Jump to the location of a symbol selected in the popup menu -def JumpToWorkspaceSymbol(popupID: number, result: number): void +def JumpToWorkspaceSymbol(cmdmods: string, popupID: number, result: number): void # clear the message displayed at the command-line :echo '' @@ -91,32 +91,40 @@ def JumpToWorkspaceSymbol(popupID: number, result: number): void # if the selected file is already present in a window, then jump to it var fname: string = symTbl[result - 1].file - var bufnum = fname->bufnr() - var winList: list = bufnum->win_findbuf() - if winList->empty() - # Not present in any window - if &modified || &buftype != '' - # the current buffer is modified or is not a normal buffer, then open - # the file in a new window - exe $'split {symTbl[result - 1].file}' + var bnr = fname->bufnr() + if cmdmods->empty() + var winList: list = bnr->win_findbuf() + if winList->empty() + # Not present in any window + if &modified || &buftype != '' + # the current buffer is modified or is not a normal buffer, then + # open the file in a new window + exe $'split {symTbl[result - 1].file}' + else + exe $'confirm edit {symTbl[result - 1].file}' + endif else - exe $'confirm edit {symTbl[result - 1].file}' - endif - else - if bufnr() != bufnum - var winID = fname->bufwinid() - if winID == -1 - # not present in the current tab page - winID = winList[0] + # If the target buffer is opened in the curent window, then don't + # change the window. + if bufnr() != bnr + # If the target buffer is opened in a window in the current tab + # page, then use it. + var winID = fname->bufwinid() + if winID == -1 + # not present in the current tab page.  Use the first window. + winID = winList[0] + endif + winID->win_gotoid() endif - winID->win_gotoid() endif + else + exe $'{cmdmods} split {symTbl[result - 1].file}' endif # Set the previous cursor location mark. Instead of using setpos(), m' is # used so that the current location is added to the jump list. :normal m' setcursorcharpos(symTbl[result - 1].pos.line + 1, - util.GetCharIdxWithoutCompChar(bufnum, + util.GetCharIdxWithoutCompChar(bnr, symTbl[result - 1].pos) + 1) catch # ignore exceptions @@ -124,7 +132,7 @@ def JumpToWorkspaceSymbol(popupID: number, result: number): void enddef # display a list of symbols from the workspace -def ShowSymbolMenu(lspserver: dict, query: string) +def ShowSymbolMenu(lspserver: dict, query: string, cmdmods: string) # Create the popup menu var lnum = &lines - &cmdheight - 2 - 10 var popupAttr = { @@ -141,7 +149,7 @@ def ShowSymbolMenu(lspserver: dict, query: string) fixed: 1, close: 'button', filter: function(FilterSymbols, [lspserver]), - callback: JumpToWorkspaceSymbol + callback: function('JumpToWorkspaceSymbol', [cmdmods]) } lspserver.workspaceSymbolPopup = popup_menu([], popupAttr) lspserver.workspaceSymbolQuery = query @@ -175,16 +183,15 @@ enddef # process the 'workspace/symbol' reply from the LSP server # Result: SymbolInformation[] | null export def WorkspaceSymbolPopup(lspserver: dict, query: string, - symInfo: list>) + symInfo: list>, cmdmods: string) var symbols: list> = [] var symbolType: string var fileName: string - var r: dict> var symName: string # Create a symbol popup menu if it is not present if lspserver.workspaceSymbolPopup->winbufnr() == -1 - ShowSymbolMenu(lspserver, query) + ShowSymbolMenu(lspserver, query, cmdmods) endif for symbol in symInfo @@ -195,8 +202,6 @@ export def WorkspaceSymbolPopup(lspserver: dict, query: string, # interface SymbolInformation fileName = util.LspUriToFile(symbol.location.uri) - r = symbol.location.range - lspserver.decodeRange(fileName->bufnr(), r) symName = symbol.name if symbol->has_key('containerName') && symbol.containerName != '' @@ -209,7 +214,7 @@ export def WorkspaceSymbolPopup(lspserver: dict, query: string, symbols->add({name: symName, file: fileName, - pos: r.start}) + pos: symbol.location.range.start}) endfor symbols->setwinvar(lspserver.workspaceSymbolPopup, 'LspSymbolTable') lspserver.workspaceSymbolPopup->popup_settext( diff --git a/autoload/lsp/util.vim b/autoload/lsp/util.vim index a63953c..023c835 100644 --- a/autoload/lsp/util.vim +++ b/autoload/lsp/util.vim @@ -261,8 +261,8 @@ export def JumpToLspLocation(location: dict, cmdmods: string) var fname = LspUriToFile(uri) # jump to the file and line containing the symbol + var bnr: number = fname->bufnr() if cmdmods->empty() - var bnr: number = fname->bufnr() if bnr == bufnr() # Set the previous cursor location mark. Instead of using setpos(), m' is # used so that the current location is added to the jump list. @@ -294,7 +294,12 @@ export def JumpToLspLocation(location: dict, cmdmods: string) endif endif else - exe $'{cmdmods} split {fname}' + if bnr == -1 + exe $'{cmdmods} split {fname}' + else + # Use "sbuffer" so that the 'switchbuf' option settings are used. + exe $'{cmdmods} sbuffer {bnr}' + endif endif setcursorcharpos(range.start.line + 1, GetCharIdxWithoutCompChar(bufnr(), range.start) + 1) diff --git a/doc/lsp.txt b/doc/lsp.txt index 6c8b47f..1185756 100644 --- a/doc/lsp.txt +++ b/doc/lsp.txt @@ -1047,9 +1047,11 @@ can map these commands to keys and make it easier to invoke them. :LspSymbolSearch Perform a workspace wide search for the symbol . If is not supplied, then you will be prompted to enter the symbol name (the keyword under the cursor is - used as the default). A popup window is opened with - the list of matching symbols. You can enter a few - characters to narrow down the list of matches. The + used as the default). If there is only one matching + symbol, then the cursor will be positioned at the + symbol location. Otherwise a popup window is opened + with the list of matching symbols. You can enter a + few characters to narrow down the list of matches. The displayed symbol name can be erased by pressing or and a new symbol search pattern can be entered. You can close the popup menu by @@ -1082,6 +1084,14 @@ can map these commands to keys and make it easier to invoke them. You can enter a new search pattern to do a workspace wide symbol search. + This command accepts |:command-modifiers| which can be + used to jump to a symbol in a horizontally or + vertically split window or a new tab page: > + + :topleft LspSymbolSearch foo + :vert LspSymbolSearch bar + :tab LspSymbolSearch baz +< *:LspWorkspaceAddFolder* :LspWorkspaceAddFolder {folder} Add a folder to the workspace diff --git a/plugin/lsp.vim b/plugin/lsp.vim index cc9856e..f38f97a 100644 --- a/plugin/lsp.vim +++ b/plugin/lsp.vim @@ -96,7 +96,7 @@ command! -nargs=0 -bar LspSuperTypeHierarchy lsp.TypeHierarchy(1) # Clangd specifc extension to switch from one C/C++ source file to a # corresponding header file command! -nargs=0 -bar LspSwitchSourceHeader lsp.SwitchSourceHeader() -command! -nargs=? -bar LspSymbolSearch lsp.SymbolSearch() +command! -nargs=? -bar LspSymbolSearch lsp.SymbolSearch(, ) command! -nargs=1 -bar -complete=dir LspWorkspaceAddFolder lsp.AddWorkspaceFolder() command! -nargs=0 -bar LspWorkspaceListFolders lsp.ListWorkspaceFolders() command! -nargs=1 -bar -complete=dir LspWorkspaceRemoveFolder lsp.RemoveWorkspaceFolder() diff --git a/test/clangd_offsetencoding.vim b/test/clangd_offsetencoding.vim index c61b37c..0918ab9 100644 --- a/test/clangd_offsetencoding.vim +++ b/test/clangd_offsetencoding.vim @@ -378,13 +378,13 @@ def g:Test_LspSymbolSearch_multibyte() g:WaitForServerFileLoad(0) cursor(1, 1) - feedkeys(":LspSymbolSearch Func1\\", "xt") + feedkeys(":LspSymbolSearch Func1\", "xt") assert_equal([5, 18], [line('.'), col('.')]) cursor(1, 1) - feedkeys(":LspSymbolSearch Func2\\", "xt") + feedkeys(":LspSymbolSearch Func2\", "xt") assert_equal([9, 14], [line('.'), col('.')]) cursor(1, 1) - feedkeys(":LspSymbolSearch Func3\\", "xt") + feedkeys(":LspSymbolSearch Func3\", "xt") assert_equal([13, 22], [line('.'), col('.')]) :%bw! diff --git a/test/clangd_tests.vim b/test/clangd_tests.vim index 3c88ff0..443ff98 100644 --- a/test/clangd_tests.vim +++ b/test/clangd_tests.vim @@ -1178,7 +1178,7 @@ def g:Test_LspSymbolSearch() g:WaitForServerFileLoad(0) cursor(1, 1) - feedkeys(":LspSymbolSearch lsptest_funcB\\", "xt") + feedkeys(":LspSymbolSearch lsptest_funcB\", "xt") assert_equal([5, 6], [line('.'), col('.')]) cursor(1, 1) @@ -1186,7 +1186,7 @@ def g:Test_LspSymbolSearch() assert_equal([9, 6], [line('.'), col('.')]) cursor(1, 1) - feedkeys(":LspSymbolSearch lsptest_funcA\\B\", "xt") + feedkeys(":LspSymbolSearch lsptest_func\A\B\", "xt") assert_equal([5, 6], [line('.'), col('.')]) var output = execute(':LspSymbolSearch lsptest_nonexist')->split("\n")