autoload/handlers.vim | 72 ++++++++++++++++++++++++++++++++++++----------------- autoload/lsp.vim | 16 ++++++++-------- autoload/lspserver.vim | 31 ++++++++++++++++++++++--------- doc/lsp.txt | 33 +++++++++++++++++++++++++++++++++ plugin/lsp.vim | 24 ++++++++++++++---------- diff --git a/autoload/handlers.vim b/autoload/handlers.vim index 3a1b9b940596e2ca5715d2389d25e8ffc4a53e76..b13b691fc135df50ed950cf97fde99bf5dd62abd 100644 --- a/autoload/handlers.vim +++ b/autoload/handlers.vim @@ -105,11 +105,14 @@ # Result: Location | Location[] | LocationLink[] | null def s:processDefDeclReply(lspserver: dict, req: dict, reply: dict): void if reply.result->empty() util.WarnMsg("Error: definition is not found") - # pop the tag stack - var tagstack: dict = gettagstack() - if tagstack.length > 0 - settagstack(winnr(), {curidx: tagstack.length}, 't') + if !lspserver.peekDefDecl + # pop the tag stack + var tagstack: dict = gettagstack() + if tagstack.length > 0 + settagstack(winnr(), {curidx: tagstack.length}, 't') + endif endif + lspserver.peekDefDecl = false return endif @@ -120,32 +123,55 @@ else location = reply.result endif var fname = util.LspUriToFile(location.uri) - var wid = fname->bufwinid() - if wid != -1 - wid->win_gotoid() + if lspserver.peekDefDecl + # 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 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 + pos->add(location.range.start.line + 1) + pos->extend([start_col, end_col - start_col]) + matchaddpos('Search', [pos], 10, 101) + win_gotoid(cur_wid) else - var bnr: number = fname->bufnr() - if bnr != -1 - if &modified || &buftype != '' - exe 'sbuffer ' .. bnr - else - exe 'buf ' .. bnr - endif + # jump to the file and line containing the symbol + var wid = fname->bufwinid() + if wid != -1 + wid->win_gotoid() else - if &modified || &buftype != '' - # if the current buffer has unsaved changes, then open the file in a - # new window - exe 'split ' .. fname + var bnr: number = fname->bufnr() + if bnr != -1 + if &modified || &buftype != '' + exe 'sbuffer ' .. bnr + else + exe 'buf ' .. bnr + endif else - exe 'edit ' .. fname + if &modified || &buftype != '' + # if the current buffer has unsaved changes, then open the file in a + # new window + exe 'split ' .. fname + else + exe 'edit ' .. fname + endif endif endif + # Set the previous cursor location mark + setpos("'`", getcurpos()) + setcursorcharpos(location.range.start.line + 1, + location.range.start.character + 1) endif - # Set the previous cursor location mark - setpos("'`", getcurpos()) - setcursorcharpos(location.range.start.line + 1, - location.range.start.character + 1) redraw! + lspserver.peekDefDecl = false enddef # process the 'textDocument/signatureHelp' reply from the LSP server diff --git a/autoload/lsp.vim b/autoload/lsp.vim index fdaa0eb5a160edacf00bf6d2ada9d891e612c4d5..bd29f2c99cd35ab31e9e2d7a52319b90f443a474 100644 --- a/autoload/lsp.vim +++ b/autoload/lsp.vim @@ -157,7 +157,7 @@ endfor enddef # Go to a definition using "textDocument/definition" LSP request -def lsp#gotoDefinition() +def lsp#gotoDefinition(peek: bool) var ftype: string = &filetype if ftype == '' || @% == '' return @@ -173,11 +173,11 @@ util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif - lspserver.gotoDefinition() + lspserver.gotoDefinition(peek) enddef # Go to a declaration using "textDocument/declaration" LSP request -def lsp#gotoDeclaration() +def lsp#gotoDeclaration(peek: bool) var ftype: string = &filetype if ftype == '' return @@ -193,11 +193,11 @@ util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif - lspserver.gotoDeclaration() + lspserver.gotoDeclaration(peek) enddef # Go to a type definition using "textDocument/typeDefinition" LSP request -def lsp#gotoTypedef() +def lsp#gotoTypedef(peek: bool) var ftype: string = &filetype if ftype == '' return @@ -213,11 +213,11 @@ util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif - lspserver.gotoTypeDef() + lspserver.gotoTypeDef(peek) enddef # Go to a implementation using "textDocument/implementation" LSP request -def lsp#gotoImplementation() +def lsp#gotoImplementation(peek: bool) var ftype: string = &filetype if ftype == '' return @@ -233,7 +233,7 @@ util.ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') return endif - lspserver.gotoImplementation() + lspserver.gotoImplementation(peek) enddef # Show the signature using "textDocument/signatureHelp" LSP method diff --git a/autoload/lspserver.vim b/autoload/lspserver.vim index 32601c6b4ae3eafdcc51a2794dd75c814d371c13..814b9194733a986b36c6684fcb3fdcd05d4b18c6 100644 --- a/autoload/lspserver.vim +++ b/autoload/lspserver.vim @@ -413,7 +413,7 @@ enddef # Request: "textDocument/definition" # Param: DefinitionParams -def s:gotoDefinition(lspserver: dict): void +def s:gotoDefinition(lspserver: dict, peek: bool): void # Check whether LSP server supports jumping to a definition if !lspserver.caps->has_key('definitionProvider') || !lspserver.caps.definitionProvider @@ -421,7 +421,10 @@ util.ErrMsg("Error: LSP server does not support jumping to a definition") return endif - util.PushCursorToTagStack() + if !peek + util.PushCursorToTagStack() + endif + lspserver.peekDefDecl = peek var req = lspserver.createRequest('textDocument/definition') # interface DefinitionParams # interface TextDocumentPositionParams @@ -431,7 +434,7 @@ enddef # Request: "textDocument/declaration" # Param: DeclarationParams -def s:gotoDeclaration(lspserver: dict): void +def s:gotoDeclaration(lspserver: dict, peek: bool): void # Check whether LSP server supports jumping to a declaration if !lspserver.caps->has_key('declarationProvider') || !lspserver.caps.declarationProvider @@ -439,7 +442,10 @@ util.ErrMsg("Error: LSP server does not support jumping to a declaration") return endif - util.PushCursorToTagStack() + if !peek + util.PushCursorToTagStack() + endif + lspserver.peekDefDecl = peek var req = lspserver.createRequest('textDocument/declaration') # interface DeclarationParams @@ -451,7 +457,7 @@ enddef # Request: "textDocument/typeDefinition" # Param: TypeDefinitionParams -def s:gotoTypeDef(lspserver: dict): void +def s:gotoTypeDef(lspserver: dict, peek: bool): void # Check whether LSP server supports jumping to a type definition if !lspserver.caps->has_key('typeDefinitionProvider') || !lspserver.caps.typeDefinitionProvider @@ -459,7 +465,10 @@ util.ErrMsg("Error: LSP server does not support jumping to a type definition") return endif - util.PushCursorToTagStack() + if !peek + util.PushCursorToTagStack() + endif + lspserver.peekDefDecl = peek var req = lspserver.createRequest('textDocument/typeDefinition') # interface TypeDefinitionParams @@ -471,7 +480,7 @@ enddef # Request: "textDocument/implementation" # Param: ImplementationParams -def s:gotoImplementation(lspserver: dict): void +def s:gotoImplementation(lspserver: dict, peek: bool): void # Check whether LSP server supports jumping to a implementation if !lspserver.caps->has_key('implementationProvider') || !lspserver.caps.implementationProvider @@ -479,7 +488,10 @@ util.ErrMsg("Error: LSP server does not support jumping to an implementation") return endif - util.PushCursorToTagStack() + if !peek + util.PushCursorToTagStack() + endif + lspserver.peekDefDecl = peek var req = lspserver.createRequest('textDocument/implementation') # interface ImplementationParams @@ -839,7 +851,8 @@ completePending: false, completionTriggerChars: [], diagsMap: {}, workspaceSymbolPopup: 0, - workspaceSymbolQuery: '' + workspaceSymbolQuery: '', + peekDefDecl: false } # Add the LSP server functions lspserver->extend({ diff --git a/doc/lsp.txt b/doc/lsp.txt index 2976c7b3acf5e2004e4fb62454159e60b930f8db..49fb602ea0f857065002f0ac197b351844c416d6 100644 --- a/doc/lsp.txt +++ b/doc/lsp.txt @@ -73,6 +73,14 @@ :LspGotoDefinition Go to the definition of the symbol under cursor :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. +:LspPeekTypeDef Open the type definition of the symbol under cursor in + the preview window. +:LspPeekImpl Open the implementation of the symbol under cursor in + the preview 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. @@ -232,6 +240,31 @@ :LspGotoImpl Jumps to the implementation of the symbol under the cursor. The behavior of this command is similar to the |:LspGotoDefinition| command. Note that not all the LSP servers support this feature. + + *: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. + + *:LspPeekDeclaration* +:LspPeekDeclaration Displays the line where the symbol under the + cursor is declared in the |preview-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 + 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 + command is similar to the |:LspPeekDefinition| + command. Note that not all the LSP servers support + this feature. *:LspShowSignature* :LspShowSignature Displays the signature of the symbol (e.g. a function diff --git a/plugin/lsp.vim b/plugin/lsp.vim index 8683e639089068d7879f39e45e49bb0d3b81f521..133415c17838494c744e21e3fc9485809950bf4f 100644 --- a/plugin/lsp.vim +++ b/plugin/lsp.vim @@ -20,10 +20,14 @@ " LSP commands command! -nargs=0 -bar LspShowServers call lsp#showServers() command! -nargs=1 -bar LspSetTrace call lsp#setTraceServer() -command! -nargs=0 -bar LspGotoDefinition call lsp#gotoDefinition() -command! -nargs=0 -bar LspGotoDeclaration call lsp#gotoDeclaration() -command! -nargs=0 -bar LspGotoTypeDef call lsp#gotoTypedef() -command! -nargs=0 -bar LspGotoImpl call lsp#gotoImplementation() +command! -nargs=0 -bar LspGotoDefinition call lsp#gotoDefinition(v:false) +command! -nargs=0 -bar LspGotoDeclaration call lsp#gotoDeclaration(v:false) +command! -nargs=0 -bar LspGotoTypeDef call lsp#gotoTypedef(v:false) +command! -nargs=0 -bar LspGotoImpl call lsp#gotoImplementation(v:false) +command! -nargs=0 -bar LspPeekDefinition call lsp#gotoDefinition(v:true) +command! -nargs=0 -bar LspPeekDeclaration call lsp#gotoDeclaration(v:true) +command! -nargs=0 -bar LspPeekTypeDef call lsp#gotoTypedef(v:true) +command! -nargs=0 -bar LspPeekImpl call lsp#gotoImplementation(v:true) command! -nargs=0 -bar LspShowSignature call lsp#showSignature() command! -nargs=0 -bar LspDiagShow call lsp#showDiagnostics() command! -nargs=0 -bar LspDiagCurrent call lsp#showCurrentDiag() @@ -49,10 +53,10 @@ command! -nargs=1 -bar -complete=dir LspWorkspaceRemoveFolder call lsp#removeWorkspaceFolder() " Add the GUI menu entries if has('gui_running') - anoremenu L&sp.Goto.Definition :call lsp#gotoDefinition() - anoremenu L&sp.Goto.Declaration :call lsp#gotoDeclaration() - anoremenu L&sp.Goto.Implementation :call lsp#gotoImplementation() - anoremenu L&sp.Goto.TypeDef :call lsp#gotoTypedef() + anoremenu L&sp.Goto.Definition :call lsp#gotoDefinition(v:false) + anoremenu L&sp.Goto.Declaration :call lsp#gotoDeclaration(v:false) + anoremenu L&sp.Goto.Implementation :call lsp#gotoImplementation(v:false) + anoremenu L&sp.Goto.TypeDef :call lsp#gotoTypedef(v:false) anoremenu L&sp.Show\ Signature :call lsp#showSignature() anoremenu L&sp.Show\ References :call lsp#showReferences() @@ -77,9 +81,9 @@ anoremenu L&sp.Diagnostics.Prev :call lsp#jumpToDiag('prev') if &mousemodel =~ 'popup' anoremenu PopUp.L&sp.Go\ to\ Definition - \ :call lsp#gotoDefinition() + \ :call lsp#gotoDefinition(v:false) anoremenu PopUp.L&sp.Go\ to\ Declaration - \ :call lsp#gotoDeclaration() + \ :call lsp#gotoDeclaration(v:false) anoremenu Popup.L&sp.Find\ All\ References \ :call lsp#showReferences() anoremenu PopUp.L&sp.Show\ Detail