From: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Wed, 2 Nov 2022 06:11:33 +0000 (-0700)
Subject: When peeking a symbol definition, declaration, etc. use a popup window instead of... 
X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=a297e67103015dd592c2e6bc08d7dd01d4f9aac6;p=vim-lsp.git

When peeking a symbol definition, declaration, etc. use a popup window instead of a preview window
---

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<any>, req: dict<any>, reply: dict<any>): 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<string>, 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<any>, location: dict<any>, 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<number> = []
     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<any>, location: dict<any>, 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
+			<Esc> 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<string> =<< 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! \<C-t>", '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! \<C-t>", 'E555:')
+
+  :%bw!
 
   # empty file
   assert_equal('', execute('LspGotoDefinition'))