From a297e67103015dd592c2e6bc08d7dd01d4f9aac6 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Tue, 1 Nov 2022 23:11:33 -0700 Subject: [PATCH] When peeking a symbol definition, declaration, etc. use a popup window instead of a preview window --- autoload/lsp/handlers.vim | 3 --- autoload/lsp/lspserver.vim | 1 + autoload/lsp/symbol.vim | 44 +++++++++++++++++++++++++++----------- doc/lsp.txt | 23 ++++++++++---------- test/unit_tests.vim | 41 +++++++++++++++++++++++++++++++++-- 5 files changed, 84 insertions(+), 28 deletions(-) diff --git a/autoload/lsp/handlers.vim b/autoload/lsp/handlers.vim index 0c9a704..cfa3239 100644 --- a/autoload/lsp/handlers.vim +++ b/autoload/lsp/handlers.vim @@ -4,12 +4,9 @@ vim9script # Refer to https://microsoft.github.io/language-server-protocol/specification # for the Language Server Protocol (LSP) specification. -import './options.vim' as opt import './util.vim' import './diag.vim' -import './outline.vim' import './textedit.vim' -import './symbol.vim' # Process various reply messages from the LSP server export def ProcessReply(lspserver: dict, req: dict, reply: dict): void diff --git a/autoload/lsp/lspserver.vim b/autoload/lsp/lspserver.vim index 3f539de..14fb706 100644 --- a/autoload/lsp/lspserver.vim +++ b/autoload/lsp/lspserver.vim @@ -1482,6 +1482,7 @@ export def NewLspServer(path: string, args: list, isSync: bool, initiali diagsMap: {}, workspaceSymbolPopup: -1, workspaceSymbolQuery: '', + peekSymbolPopup: -1, callHierarchyType: '', selection: {} } diff --git a/autoload/lsp/symbol.vim b/autoload/lsp/symbol.vim index b5e4886..d1282a6 100644 --- a/autoload/lsp/symbol.vim +++ b/autoload/lsp/symbol.vim @@ -280,22 +280,43 @@ export def GotoSymbol(lspserver: dict, location: dict, peekSymbol: boo if peekSymbol # open the definition/declaration in the preview window and highlight the # matching symbol - exe $'pedit {fname}' - var cur_wid = win_getid() - wincmd P - var pvwbuf = bufnr() - setcursorcharpos(location.range.start.line + 1, - location.range.start.character + 1) - silent! matchdelete(101) + + var bnum = bufadd(fname) + if bnum == 0 + # Failed to create or find a buffer + return + endif + + if lspserver.peekSymbolPopup->winbufnr() != -1 + # If the symbol popup window is already present, close it. + lspserver.peekSymbolPopup->popup_close() + endif + var ptitle = $"{fnamemodify(fname, ':t')} ({fnamemodify(fname, ':h')})" + lspserver.peekSymbolPopup = popup_atcursor(bnum, {moved: 'any', + title: ptitle, + minwidth: 10, + maxwidth: 60, + minheight: 10, + maxheight: 10, + mapping: false, + wrap: false}) + + # Highlight the symbol name and center the line in the popup + var pwid = lspserver.peekSymbolPopup + var pwbuf = winbufnr(pwid) var pos: list = [] var start_col: number var end_col: number - start_col = util.GetLineByteFromPos(pvwbuf, location.range.start) + 1 - end_col = util.GetLineByteFromPos(pvwbuf, location.range.end) + 1 + start_col = util.GetLineByteFromPos(pwbuf, location.range.start) + 1 + end_col = util.GetLineByteFromPos(pwbuf, location.range.end) + 1 pos->add(location.range.start.line + 1) pos->extend([start_col, end_col - start_col]) - matchaddpos('Search', [pos], 10, 101) - win_gotoid(cur_wid) + matchaddpos('Search', [pos], 10, 101, {window: pwid}) + var cmds =<< trim eval END + cursor({location.range.start.line + 1}, 1) + normal! z. + END + win_execute(pwid, cmds, 'silent!') else # jump to the file and line containing the symbol var bnr: number = fname->bufnr() @@ -331,7 +352,6 @@ export def GotoSymbol(lspserver: dict, location: dict, peekSymbol: boo setcursorcharpos(location.range.start.line + 1, location.range.start.character + 1) endif - redraw! enddef # Process the LSP server reply message for a 'textDocument/definition' request diff --git a/doc/lsp.txt b/doc/lsp.txt index 9fd5372..b987c35 100644 --- a/doc/lsp.txt +++ b/doc/lsp.txt @@ -73,14 +73,14 @@ The following commands are provided: :LspGotoDeclaration Go to the declaration of the symbol under cursor :LspGotoTypeDef Go to the type definition of the symbol under cursor :LspGotoImpl Go to the implementation of the symbol under cursor -:LspPeekDefinition Open the definition of the symbol under cursor in the - preview window. -:LspPeekDeclaration Open the declaration of the symbol under cursor in the - preview window. +:LspPeekDefinition Open the definition of the symbol under cursor in a + popup window. +:LspPeekDeclaration Open the declaration of the symbol under cursor in a + popup window. :LspPeekTypeDef Open the type definition of the symbol under cursor in - the preview window. + a popup window. :LspPeekImpl Open the implementation of the symbol under cursor in - the preview window. + a popup window. :LspShowSignature Display the signature of the symbol under cursor. :LspDiagShow Display the diagnostics messages from the LSP server for the current buffer in a location list. @@ -335,25 +335,26 @@ diagnostic messages, you can add the following line to your .vimrc file: < *:LspPeekDefinition* :LspPeekDefinition Displays the line where the symbol under the cursor is - defined in the |preview-window|. The symbol is - highlighted in the preview window. + defined in a popup window. The symbol is highlighted + in the popup window. Moving the cursor or pressing + will close the popup window. *:LspPeekDeclaration* :LspPeekDeclaration Displays the line where the symbol under the - cursor is declared in the |preview-window|. The + cursor is declared in a popup window. The behavior of this command is similar to the |:LspPeekDefinition| command. *:LspPeekTypeDef* :LspPeekTypeDef Displays the line where the type of the symbol under - the cursor is defined in the |preview-window|. The + the cursor is defined in a popup window. The behavior of this command is similar to the |:LspPeekDefinition| command. Note that not all the LSP servers support this feature. *:LspPeekImpl* :LspPeekImpl Displays the implementation of the symbol under the - cursor in the |preview-window|. The behavior of this + cursor in a popup window. The behavior of this command is similar to the |:LspPeekDefinition| command. Note that not all the LSP servers support this feature. diff --git a/test/unit_tests.vim b/test/unit_tests.vim index aae2a6e..85ee435 100644 --- a/test/unit_tests.vim +++ b/test/unit_tests.vim @@ -218,6 +218,20 @@ def Test_LspShowReferences() assert_equal(1, getloclist(0)->len()) qfl = getloclist(0) assert_equal([1, 5], [qfl[0].lnum, qfl[0].col]) + :lclose + + # Test for LspPeekReferences + + # Opening the preview window with an unsaved buffer displays the "E37: No + # write since last change" error message. To disable this message, mark the + # buffer as not modified. + setlocal nomodified + cursor(1, 5) + :LspPeekReferences + assert_equal([3, 3], [winnr('$'), winnr()]) + assert_equal('preview', win_gettype(1)) + assert_equal('loclist', win_gettype(2)) + bw! # empty file @@ -501,7 +515,7 @@ def Test_LspSelection() enddef # Test for :LspGotoDefinition, :LspGotoDeclaration and :LspGotoImpl -def Test_LspGotoDefinition() +def Test_LspGotoSymbol() silent! edit Xtest.cpp sleep 200m var lines: list =<< trim END @@ -565,7 +579,30 @@ def Test_LspGotoDefinition() m = execute('messages')->split("\n") assert_equal('Error: implementation is not found', m[1]) endif - bw! + + # Test for LspPeekDeclaration + cursor(24, 6) + var bnum = bufnr() + :LspPeekDeclaration + var plist = popup_list() + assert_true(1, plist->len()) + assert_equal(bnum, plist[0]->winbufnr()) + assert_equal(6, line('.', plist[0])) + popup_clear() + # tag stack should not be changed + assert_fails("normal! \", 'E555:') + + # Test for LspPeekDefinition + :LspPeekDefinition + plist = popup_list() + assert_true(1, plist->len()) + assert_equal(bnum, plist[0]->winbufnr()) + assert_equal(9, line('.', plist[0])) + popup_clear() + # tag stack should not be changed + assert_fails("normal! \", 'E555:') + + :%bw! # empty file assert_equal('', execute('LspGotoDefinition')) -- 2.48.1