aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaehwang Jung <tomtomjhj@gmail.com>2023-12-19 00:47:01 +0900
committerGitHub <noreply@github.com>2023-12-18 15:47:01 +0000
commitcd1b14f027f375a9de17fdf106016470f52035f7 (patch)
tree5890d7d572f32c3fce0b20c8eb3093be0cc8f8c2
parent6cb78e2d1c4c6c63c628c965076a07ce5f7adbb6 (diff)
downloadrneovim-cd1b14f027f375a9de17fdf106016470f52035f7.tar.gz
rneovim-cd1b14f027f375a9de17fdf106016470f52035f7.tar.bz2
rneovim-cd1b14f027f375a9de17fdf106016470f52035f7.zip
feat(termdebug): improve `:Evaluate` floating window (#26621)
Problem: - The :Evaluate result window is not cleaned up when the cursor moves. - This window is not focusable. Solution: Replace the old implementation from autozimu/LanguageClient-neovim with vim.lsp.util.open_floating_preview and implement custom focusing logic. Also remove g:termdebug_useFloatingHover option now that it's working correctly.
-rw-r--r--runtime/doc/nvim_terminal_emulator.txt8
-rw-r--r--runtime/pack/dist/opt/termdebug/plugin/termdebug.vim165
2 files changed, 28 insertions, 145 deletions
diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt
index 67e5e53c95..557e714ddc 100644
--- a/runtime/doc/nvim_terminal_emulator.txt
+++ b/runtime/doc/nvim_terminal_emulator.txt
@@ -240,7 +240,7 @@ gdb window and use a "print" command, e.g.: >
If mouse pointer movements are working, Vim will also show a balloon when the
mouse rests on text that can be evaluated by gdb.
You can also use the "K" mapping that will either use Nvim floating windows
-if available to show the results or print below the status bar.
+to show the results.
Now go back to the source window and put the cursor on the first line after
the for loop, then type: >
@@ -320,6 +320,8 @@ Inspecting variables ~
This is similar to using "print" in the gdb window.
You can usually shorten `:Evaluate` to `:Ev`.
+The result is displayed in a floating window.
+You can move the cursor to this window by running `:Evaluate` (or `K`) again.
Navigating stack frames ~
@@ -475,10 +477,6 @@ If the command needs an argument use a List: >vim
If there is no g:termdebug_config you can use: >vim
let g:termdebugger = ['rr', 'replay', '--']
-To not use Nvim floating windows for previewing variable evaluation, set the
-`g:termdebug_useFloatingHover` variable like this: >vim
- let g:termdebug_useFloatingHover = 0
-
If you are a mouse person, you can also define a mapping using your right
click to one of the terminal command like evaluate the variable under the
cursor: >vim
diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
index ee2dc4478e..a253acc63f 100644
--- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
+++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
@@ -35,21 +35,14 @@
" The communication with gdb uses GDB/MI. See:
" https://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI.html
"
-" For neovim compatibility, the vim specific calls were replaced with neovim
-" specific calls:
-" term_start -> termopen
-" term_sendkeys -> chansend
-" term_getline -> getbufline
-" job_info && term_getjob -> using linux command ps to get the tty
-" balloon -> nvim floating window
+" NEOVIM COMPATIBILITY
"
-" The code for opening the floating window was taken from the beautiful
-" implementation of LanguageClient-Neovim:
-" https://github.com/autozimu/LanguageClient-neovim/blob/0ed9b69dca49c415390a8317b19149f97ae093fa/autoload/LanguageClient.vim#L304
-"
-" Neovim terminal also works seamlessly on windows, which is why the ability
-" Author: Bram Moolenaar
-" Copyright: Vim license applies, see ":help license"
+" The vim specific functionalities were replaced with neovim specific calls:
+" - term_start -> termopen
+" - term_sendkeys -> chansend
+" - term_getline -> getbufline
+" - job_info && term_getjob -> nvim_get_chan_info
+" - balloon -> vim.lsp.util.open_floating_preview
" In case this gets sourced twice.
if exists(':Termdebug')
@@ -1313,7 +1306,14 @@ endfunc
" :Evaluate - evaluate what is specified / under the cursor
func s:Evaluate(range, arg)
+ if s:eval_float_win_id > 0 && nvim_win_is_valid(s:eval_float_win_id)
+ \ && a:range == 0 && empty(a:arg)
+ call nvim_set_current_win(s:eval_float_win_id)
+ return
+ endif
let expr = s:GetEvaluationExpression(a:range, a:arg)
+ let s:evalFromBalloonExpr = 1
+ let s:evalFromBalloonExprResult = ''
let s:ignoreEvalError = 0
call s:SendEval(expr)
endfunc
@@ -1370,6 +1370,8 @@ let s:ignoreEvalError = 0
let s:evalFromBalloonExpr = 0
let s:evalFromBalloonExprResult = ''
+let s:eval_float_win_id = -1
+
" Handle the result of data-evaluate-expression
func s:HandleEvaluate(msg)
let value = a:msg
@@ -1392,9 +1394,15 @@ func s:HandleEvaluate(msg)
else
let s:evalFromBalloonExprResult .= ' = ' . value
endif
- let s:evalFromBalloonExprResult = split(s:evalFromBalloonExprResult, '\\n')
- call s:OpenHoverPreview(s:evalFromBalloonExprResult, v:null)
- let s:evalFromBalloonExprResult = ''
+ " NEOVIM:
+ " - Result pretty-printing is not implemented. Vim prettifies the result
+ " with balloon_split(), which is not ported to nvim.
+ " - Manually implement window focusing. Sometimes the result of pointer
+ " evaluation arrives in two separate messages, one for the address
+ " itself and the other for the value in that address. So with the stock
+ " focus option, the second message will focus the window containing the
+ " first message.
+ let s:eval_float_win_id = luaeval('select(2, vim.lsp.util.open_floating_preview(_A))', [s:evalFromBalloonExprResult])
else
echomsg '"' . s:evalexpr . '": ' . value
endif
@@ -1403,132 +1411,9 @@ func s:HandleEvaluate(msg)
" Looks like a pointer, also display what it points to.
let s:ignoreEvalError = 1
call s:SendEval('*' . s:evalexpr)
- else
- let s:evalFromBalloonExprResult = ''
endif
endfunc
-function! s:ShouldUseFloatWindow() abort
- if exists('*nvim_open_win') && (get(g:, 'termdebug_useFloatingHover', 1) == 1)
- return v:true
- else
- return v:false
- endif
-endfunction
-
-function! s:CloseFloatingHoverOnCursorMove(win_id, opened) abort
- if getpos('.') == a:opened
- " Just after opening floating window, CursorMoved event is run.
- " To avoid closing floating window immediately, check the cursor
- " was really moved
- return
- endif
- autocmd! nvim_termdebug_close_hover
- let winnr = win_id2win(a:win_id)
- if winnr == 0
- return
- endif
- call nvim_win_close(a:win_id, v:true)
-endfunction
-
-function! s:CloseFloatingHoverOnBufEnter(win_id, bufnr) abort
- let winnr = win_id2win(a:win_id)
- if winnr == 0
- " Float window was already closed
- autocmd! nvim_termdebug_close_hover
- return
- endif
- if winnr == winnr()
- " Cursor is moving into floating window. Do not close it
- return
- endif
- if bufnr('%') == a:bufnr
- " When current buffer opened hover window, it's not another buffer. Skipped
- return
- endif
- autocmd! nvim_termdebug_close_hover
- call nvim_win_close(a:win_id, v:true)
-endfunction
-
-" Open preview window. Window is open in:
-" - Floating window on Neovim (0.4.0 or later)
-" - Preview window on Neovim (0.3.0 or earlier) or Vim
-function! s:OpenHoverPreview(lines, filetype) abort
- " Use local variable since parameter is not modifiable
- let lines = a:lines
- let bufnr = bufnr('%')
-
- let use_float_win = s:ShouldUseFloatWindow()
- if use_float_win
- let pos = getpos('.')
-
- " Calculate width and height
- let width = 0
- for index in range(len(lines))
- let line = lines[index]
- let lw = strdisplaywidth(line)
- if lw > width
- let width = lw
- endif
- let lines[index] = line
- endfor
-
- let height = len(lines)
-
- " Calculate anchor
- " Prefer North, but if there is no space, fallback into South
- let bottom_line = line('w0') + winheight(0) - 1
- if pos[1] + height <= bottom_line
- let vert = 'N'
- let row = 1
- else
- let vert = 'S'
- let row = 0
- endif
-
- " Prefer West, but if there is no space, fallback into East
- if pos[2] + width <= &columns
- let hor = 'W'
- let col = 0
- else
- let hor = 'E'
- let col = 1
- endif
-
- let buf = nvim_create_buf(v:false, v:true)
- call nvim_buf_set_lines(buf, 0, -1, v:true, lines)
- " using v:true for second argument of nvim_open_win make the floating
- " window disappear
- let float_win_id = nvim_open_win(buf, v:false, {
- \ 'relative': 'cursor',
- \ 'anchor': vert . hor,
- \ 'row': row,
- \ 'col': col,
- \ 'width': width,
- \ 'height': height,
- \ 'style': 'minimal',
- \ })
-
- if a:filetype isnot v:null
- call nvim_set_option_value('filetype', a:filetype, { 'win' : float_win_id })
- endif
-
- call nvim_set_option_value('modified', v:false, { 'buf' : buf })
- call nvim_set_option_value('modifiable', v:false, { 'buf' : buf })
-
- " Unlike preview window, :pclose does not close window. Instead, close
- " hover window automatically when cursor is moved.
- let call_after_move = printf('<SID>CloseFloatingHoverOnCursorMove(%d, %s)', float_win_id, string(pos))
- let call_on_bufenter = printf('<SID>CloseFloatingHoverOnBufEnter(%d, %d)', float_win_id, bufnr)
- augroup nvim_termdebug_close_hover
- execute 'autocmd CursorMoved,CursorMovedI,InsertEnter <buffer> call ' . call_after_move
- execute 'autocmd BufEnter * call ' . call_on_bufenter
- augroup END
- else
- echomsg a:lines[0]
- endif
-endfunction
-
" Handle an error.
func s:HandleError(msg)
if s:ignoreEvalError