mirror of
https://github.com/vim/vim
synced 2025-07-16 01:01:58 +00:00
patch 9.1.0817: termdebug: cannot evaluate expr in a popup
Problem: termdebug: cannot evaluate expr in a popup Solution: enhance termdebug plugin and allow to evaluate expressions in a popup window, add a unit test (Peter Wolf). fixes: #15877 closes: #15933 Signed-off-by: Peter Wolf <pwolf2310@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
2abec431e1
commit
8f1d09828a
@ -10664,6 +10664,7 @@ termdebug-stepping terminal.txt /*termdebug-stepping*
|
||||
termdebug-timeout terminal.txt /*termdebug-timeout*
|
||||
termdebug-variables terminal.txt /*termdebug-variables*
|
||||
termdebug_disasm_window terminal.txt /*termdebug_disasm_window*
|
||||
termdebug_evaluate_in_popup terminal.txt /*termdebug_evaluate_in_popup*
|
||||
termdebug_map_K terminal.txt /*termdebug_map_K*
|
||||
termdebug_map_minus terminal.txt /*termdebug_map_minus*
|
||||
termdebug_map_plus terminal.txt /*termdebug_map_plus*
|
||||
|
@ -1,4 +1,4 @@
|
||||
*terminal.txt* For Vim version 9.1. Last change: 2024 Jul 28
|
||||
*terminal.txt* For Vim version 9.1. Last change: 2024 Oct 27
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@ -1537,6 +1537,7 @@ If there is no g:termdebug_config you can use: >
|
||||
<
|
||||
However, the latter form will be deprecated in future releases.
|
||||
|
||||
|
||||
Mappings ~
|
||||
The termdebug plugin enables a few default mappings. All those mappings
|
||||
are reset to their original values once the termdebug session concludes.
|
||||
@ -1591,6 +1592,7 @@ If the current window has enough horizontal space, it will be vertically split
|
||||
and the Var window will be shown side by side with the source code window (and
|
||||
the height options won't be used).
|
||||
|
||||
|
||||
Communication ~
|
||||
*termdebug-communication*
|
||||
There is another, hidden, buffer, which is used for Vim to communicate with
|
||||
@ -1675,10 +1677,11 @@ If there is no g:termdebug_config you can use: >
|
||||
|
||||
However, the latter form will be deprecated in future releases.
|
||||
|
||||
|
||||
Change default signs ~
|
||||
*termdebug_signs*
|
||||
Termdebug uses the hex number of the breakpoint ID in the signcolumn to
|
||||
represent breakpoints. if it is greater than "0xFF", then it will be displayed
|
||||
represent breakpoints. If it is greater than "0xFF", then it will be displayed
|
||||
as "F+", due to we really only have two screen cells for the sign.
|
||||
|
||||
If you want to customize the breakpoint signs: >
|
||||
@ -1716,4 +1719,18 @@ Set the wide value to 1 to use a vertical split without ever changing
|
||||
'columns'. This is useful when the terminal can't be resized by Vim.
|
||||
|
||||
|
||||
Evaluate in Popup Window at Cursor ~
|
||||
*termdebug_evaluate_in_popup*
|
||||
By default |:Evaluate| will simply echo its output. For larger entities this
|
||||
might become difficult to read or even truncated.
|
||||
Alternatively, the evaluation result may be output into a popup window at the
|
||||
current cursor position: >
|
||||
let g:termdebug_config['evaluate_in_popup'] = v:true
|
||||
This can also be used in a "one-shot" manner: >
|
||||
func OnCursorHold()
|
||||
let g:termdebug_config['evaluate_in_popup'] = v:true
|
||||
:Evaluate
|
||||
let g:termdebug_config['evaluate_in_popup'] = v:false
|
||||
endfunc
|
||||
<
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
@ -121,7 +121,9 @@ var breakpoint_locations: dict<any>
|
||||
var BreakpointSigns: list<string>
|
||||
|
||||
var evalFromBalloonExpr: bool
|
||||
var evalFromBalloonExprResult: string
|
||||
var evalInPopup: bool
|
||||
var evalPopupId: number
|
||||
var evalExprResult: string
|
||||
var ignoreEvalError: bool
|
||||
var evalexpr: string
|
||||
# Remember the old value of 'signcolumn' for each buffer that it's set in, so
|
||||
@ -202,7 +204,9 @@ def InitScriptVariables()
|
||||
BreakpointSigns = []
|
||||
|
||||
evalFromBalloonExpr = false
|
||||
evalFromBalloonExprResult = ''
|
||||
evalInPopup = false
|
||||
evalPopupId = -1
|
||||
evalExprResult = ''
|
||||
ignoreEvalError = false
|
||||
evalexpr = ''
|
||||
# Remember the old value of 'signcolumn' for each buffer that it's set in, so
|
||||
@ -1478,10 +1482,23 @@ def SendEval(expr: string)
|
||||
evalexpr = exprLHS
|
||||
enddef
|
||||
|
||||
# Returns whether to evaluate in a popup or not, defaults to false.
|
||||
def EvaluateInPopup(): bool
|
||||
if exists('g:termdebug_config')
|
||||
return get(g:termdebug_config, 'evaluate_in_popup', false)
|
||||
endif
|
||||
return false
|
||||
enddef
|
||||
|
||||
# :Evaluate - evaluate what is specified / under the cursor
|
||||
def Evaluate(range: number, arg: string)
|
||||
var expr = GetEvaluationExpression(range, arg)
|
||||
echom $"expr: {expr}"
|
||||
if EvaluateInPopup()
|
||||
evalInPopup = true
|
||||
evalExprResult = ''
|
||||
else
|
||||
echomsg $'expr: {expr}'
|
||||
endif
|
||||
ignoreEvalError = false
|
||||
SendEval(expr)
|
||||
enddef
|
||||
@ -1541,6 +1558,37 @@ def Balloon_show(expr: string)
|
||||
endif
|
||||
enddef
|
||||
|
||||
def Popup_format(expr: string): list<string>
|
||||
var lines = expr
|
||||
->substitute('{', '{\n', 'g')
|
||||
->substitute('}', '\n}', 'g')
|
||||
->substitute(',', ',\n', 'g')
|
||||
->split('\n')
|
||||
var indentation = 0
|
||||
var formatted_lines = []
|
||||
for line in lines
|
||||
var stripped = line->substitute('^\s\+', '', '')
|
||||
if stripped =~ '^}'
|
||||
indentation -= 2
|
||||
endif
|
||||
formatted_lines->add(repeat(' ', indentation) .. stripped)
|
||||
if stripped =~ '{$'
|
||||
indentation += 2
|
||||
endif
|
||||
endfor
|
||||
return formatted_lines
|
||||
enddef
|
||||
|
||||
def Popup_show(expr: string)
|
||||
var formatted = Popup_format(expr)
|
||||
if evalPopupId != -1
|
||||
popup_close(evalPopupId)
|
||||
endif
|
||||
# Specifying the line is necessary, as the winbar seems to cause issues
|
||||
# otherwise. I.e., the popup would be shown one line too high.
|
||||
evalPopupId = popup_atcursor(formatted, {'line': 'cursor-1'})
|
||||
enddef
|
||||
|
||||
def HandleEvaluate(msg: string)
|
||||
var value = msg
|
||||
->substitute('.*value="\(.*\)"', '\1', '')
|
||||
@ -1555,13 +1603,12 @@ def HandleEvaluate(msg: string)
|
||||
#\ ->substitute('\\0x00', NullRep, 'g')
|
||||
#\ ->substitute('\\0x\(\x\x\)', {-> eval('"\x' .. submatch(1) .. '"')}, 'g')
|
||||
->substitute(NullRepl, '\\000', 'g')
|
||||
if evalFromBalloonExpr
|
||||
if empty(evalFromBalloonExprResult)
|
||||
evalFromBalloonExprResult = $'{evalexpr}: {value}'
|
||||
if evalFromBalloonExpr || evalInPopup
|
||||
if empty(evalExprResult)
|
||||
evalExprResult = $'{evalexpr}: {value}'
|
||||
else
|
||||
evalFromBalloonExprResult ..= $' = {value}'
|
||||
evalExprResult ..= $' = {value}'
|
||||
endif
|
||||
Balloon_show(evalFromBalloonExprResult)
|
||||
else
|
||||
echomsg $'"{evalexpr}": {value}'
|
||||
endif
|
||||
@ -1570,8 +1617,12 @@ def HandleEvaluate(msg: string)
|
||||
# Looks like a pointer, also display what it points to.
|
||||
ignoreEvalError = true
|
||||
SendEval($'*{evalexpr}')
|
||||
else
|
||||
elseif evalFromBalloonExpr
|
||||
Balloon_show(evalExprResult)
|
||||
evalFromBalloonExpr = false
|
||||
elseif evalInPopup
|
||||
Popup_show(evalExprResult)
|
||||
evalInPopup = false
|
||||
endif
|
||||
enddef
|
||||
|
||||
@ -1588,7 +1639,7 @@ def TermDebugBalloonExpr(): string
|
||||
return ''
|
||||
endif
|
||||
evalFromBalloonExpr = true
|
||||
evalFromBalloonExprResult = ''
|
||||
evalExprResult = ''
|
||||
ignoreEvalError = true
|
||||
var expr = CleanupExpr(v:beval_text)
|
||||
SendEval(expr)
|
||||
|
20
src/testdir/dumps/Test_termdebug_evaluate_in_popup_01.dump
Normal file
20
src/testdir/dumps/Test_termdebug_evaluate_in_popup_01.dump
Normal file
@ -0,0 +1,20 @@
|
||||
|U+0&#ffffff0|s|i|n|g| |h|o|s|t| |l|i|b|t|h|r|e|a|d|_|d|b| |l|i|b|r|a|r|y| |"|/+0#00e0003&|l|i|b|/|x|8|6|_|6|4|-|l|i|n|u|x|-|g|n|u|/|l|i|b|t|h|r|e|a|d|_|d|b|.|s|o|.|1|"+0#0000000&|.|
|
||||
@75
|
||||
|B|r|e|a|k|p|o|i|n|t| |1|,| |m+0#e0e0004&|a|i|n| +0#0000000&|(|a+0#00e0e07&|r|g|c|=+0#0000000&|1|,| |a+0#00e0e07&|r|g|v|=+0#0000000&|0|x|7|f@6|d|e|f|8|)| @26
|
||||
@4|a|t| |X+0#00e0003&|T|D|_|e|v|a|l|u|a|t|e|_|i|n|_|p|o|p|u|p|.|c|:+0#0000000&|9| @42
|
||||
|9| @8|r+2#0000e05&|e|t|u|r|n| +0#0000000&|0+0#e000e06&|;+0#e000002&| +0#0000000&@55
|
||||
@75
|
||||
|g+0#ffffff16#00e0003|d|b| |[|r|u|n@1|i|n|g|]| @43|1|,|1| @11|T|o|p
|
||||
| +0#0000000#ffffff0@74
|
||||
@75
|
||||
@75
|
||||
@75
|
||||
@75
|
||||
|d+0#ffffff16#00e0003|e|b|u|p+0#0000001#ffd7ff255|:| |{| @3|g+0#ffffff16#00e0003|r|a|m| |[|a|c|t|i|v|e|]| @31|0|,|0|-|1| @9|A|l@1
|
||||
| +0#0000000#e0e0e08| +2#ffffff16#6c6c6c255|S|t| +0#0000001#ffd7ff255@1|x| |=| |1|,|x+2#ffffff16#6c6c6c255|t| | +0#0000000#e0e0e08@1| +2#ffffff16#6c6c6c255|F|i|n|i|s|h| | +0#0000000#e0e0e08@1| +2#ffffff16#6c6c6c255|C|o|n|t| | +0#0000000#e0e0e08@1| +2#ffffff16#6c6c6c255|S|t|o|p| | +0#0000000#e0e0e08@1| +2#ffffff16#6c6c6c255|E|v|a|l| | +0#0000000#e0e0e08@25
|
||||
| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1| +0#0000001#ffd7ff255@1|y| |=| |2| |o+0#0000000#ffffff0|i|n|t| |p| |=| |{|a|r|g|c|,| |2+0#e000002&|}+0#0000000&|;| @43
|
||||
| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1|}+0#0000001#ffd7ff255| @6|o+0#0000000#ffffff0|i|n|t|*| |p|_|p|t|r| |=| |&|p|;| @45
|
||||
|0+0&#ff404010|1| +0fd7ff255@1>r+0#af5f00255&|e|t|u|r|n| +0#0000000&|0+0#e000002&|;+0#0000000&| @61
|
||||
| +0#0000e05#a8a8a8255@1|}+0#0000000#ffffff0| @71
|
||||
|X+3&&|T|D|_|e|v|a|l|u|a|t|e|_|i|n|_|p|o|p|u|p|.|c| @33|9|,|3| @11|B|o|t
|
||||
|:+0&&|E|v|a|l|u|a|t|e| |p| @63
|
@ -0,0 +1,9 @@
|
||||
" replace hex addresses with |0|x|f@12|
|
||||
:%s/|0|x|\(\(\w\|@\)\+|\)\+/|0|x|f@12|/g
|
||||
|
||||
" Only keep screen lines relevant to the actual popup and evaluation.
|
||||
" Especially the top lines are too instable and cause flakiness between
|
||||
" different systems and tool versions.
|
||||
normal! G
|
||||
normal! 8k
|
||||
normal! dgg
|
20
src/testdir/dumps/Test_termdebug_evaluate_in_popup_02.dump
Normal file
20
src/testdir/dumps/Test_termdebug_evaluate_in_popup_02.dump
Normal file
@ -0,0 +1,20 @@
|
||||
|U+0&#ffffff0|s|i|n|g| |h|o|s|t| |l|i|b|t|h|r|e|a|d|_|d|b| |l|i|b|r|a|r|y| |"|/+0#00e0003&|l|i|b|/|x|8|6|_|6|4|-|l|i|n|u|x|-|g|n|u|/|l|i|b|t|h|r|e|a|d|_|d|b|.|s|o|.|1|"+0#0000000&|.|
|
||||
@75
|
||||
|B|r|e|a|k|p|o|i|n|t| |1|,| |m+0#e0e0004&|a|i|n| +0#0000000&|(|a+0#00e0e07&|r|g|c|=+0#0000000&|1|,| |a+0#00e0e07&|r|g|v|=+0#0000000&|0|x|7|f@6|d|e|f|8|)| @26
|
||||
@4|a|t| |X+0#00e0003&|T|D|_|e|v|a|l|u|a|t|e|_|i|n|_|p|o|p|u|p|.|c|:+0#0000000&|9| @42
|
||||
|9| @8|r+2#0000e05&|e|t|u|r|n| +0#0000000&|0+0#e000e06&|;+0#e000002&| +0#0000000&@55
|
||||
@75
|
||||
|g+0#ffffff16#00e0003|d|b| |[|r|u|n@1|i|n|g|]| @43|1|,|1| @11|T|o|p
|
||||
| +0#0000000#ffffff0@74
|
||||
@75
|
||||
@75
|
||||
@75
|
||||
@75
|
||||
|d+0#ffffff16#00e0003|e|b|u|p+0#0000001#ffd7ff255|_|p|t|r|:| |0|x|7|f@6|d@1|c|0| |=| |{| +0#ffffff16#00e0003@27|0|,|0|-|1| @9|A|l@1
|
||||
| +0#0000000#e0e0e08| +2#ffffff16#6c6c6c255|S|t| +0#0000001#ffd7ff255@1|x| |=| |1|,| @16|o+2#ffffff16#6c6c6c255|n|t| | +0#0000000#e0e0e08@1| +2#ffffff16#6c6c6c255|S|t|o|p| | +0#0000000#e0e0e08@1| +2#ffffff16#6c6c6c255|E|v|a|l| | +0#0000000#e0e0e08@25
|
||||
| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1| +0#0000001#ffd7ff255@1|y| |=| |2| @17|}+0#0000000#ffffff0|;| @43
|
||||
| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1|}+0#0000001#ffd7ff255| @23| +0#0000000#ffffff0@45
|
||||
|0+0&#ff404010|1| +0fd7ff255@1>r+0#af5f00255&|e|t|u|r|n| +0#0000000&|0+0#e000002&|;+0#0000000&| @61
|
||||
| +0#0000e05#a8a8a8255@1|}+0#0000000#ffffff0| @71
|
||||
|X+3&&|T|D|_|e|v|a|l|u|a|t|e|_|i|n|_|p|o|p|u|p|.|c| @33|9|,|3| @11|B|o|t
|
||||
|:+0&&|E|v|a|l|u|a|t|e| |p|_|p|t|r| @59
|
@ -0,0 +1,9 @@
|
||||
" replace hex addresses with |0|x|f@12|
|
||||
:%s/|0|x|\(\(\w\|@\)\+|\)\+/|0|x|f@12|/g
|
||||
|
||||
" Only keep screen lines relevant to the actual popup and evaluation.
|
||||
" Especially the top lines are too instable and cause flakiness between
|
||||
" different systems and tool versions.
|
||||
normal! G
|
||||
normal! 8k
|
||||
normal! dgg
|
@ -1,6 +1,7 @@
|
||||
" Test for the termdebug plugin
|
||||
|
||||
source shared.vim
|
||||
source screendump.vim
|
||||
source check.vim
|
||||
|
||||
CheckUnix
|
||||
@ -243,6 +244,94 @@ func Test_termdebug_tbreak()
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
func Test_termdebug_evaluate()
|
||||
let bin_name = 'XTD_evaluate'
|
||||
let src_name = bin_name .. '.c'
|
||||
call s:generate_files(bin_name)
|
||||
|
||||
edit XTD_evaluate.c
|
||||
Termdebug ./XTD_evaluate
|
||||
call WaitForAssert({-> assert_true(get(g:, "termdebug_is_running", v:false))})
|
||||
call WaitForAssert({-> assert_equal(3, winnr('$'))})
|
||||
let gdb_buf = winbufnr(1)
|
||||
wincmd b
|
||||
|
||||
" return stmt in main
|
||||
Break 22
|
||||
call term_wait(gdb_buf)
|
||||
Run
|
||||
call term_wait(gdb_buf, 400)
|
||||
redraw!
|
||||
|
||||
" Evaluate an expression
|
||||
Evaluate n
|
||||
call term_wait(gdb_buf)
|
||||
call assert_equal(execute('1messages')->trim(), '"n": 7')
|
||||
Evaluate argc
|
||||
call term_wait(gdb_buf)
|
||||
call assert_equal(execute('1messages')->trim(), '"argc": 1')
|
||||
Evaluate isprime(n)
|
||||
call term_wait(gdb_buf)
|
||||
call assert_equal(execute('1messages')->trim(), '"isprime(n)": 1')
|
||||
|
||||
wincmd t
|
||||
quit!
|
||||
redraw!
|
||||
call s:cleanup_files(bin_name)
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
func Test_termdebug_evaluate_in_popup()
|
||||
CheckScreendump
|
||||
let bin_name = 'XTD_evaluate_in_popup'
|
||||
let src_name = bin_name .. '.c'
|
||||
let code =<< trim END
|
||||
struct Point {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
struct Point p = {argc, 2};
|
||||
struct Point* p_ptr = &p;
|
||||
return 0;
|
||||
}
|
||||
END
|
||||
call writefile(code, src_name, 'D')
|
||||
call system($'{g:GCC} -g -o {bin_name} {src_name}')
|
||||
|
||||
let lines =<< trim END
|
||||
edit XTD_evaluate_in_popup.c
|
||||
packadd termdebug
|
||||
let g:termdebug_config = {}
|
||||
let g:termdebug_config['evaluate_in_popup'] = v:true
|
||||
Termdebug ./XTD_evaluate_in_popup
|
||||
wincmd b
|
||||
Break 9
|
||||
Run
|
||||
END
|
||||
|
||||
call writefile(lines, 'Xscript', 'D')
|
||||
let buf = RunVimInTerminal('-S Xscript', {})
|
||||
call TermWait(buf, 400)
|
||||
|
||||
call term_sendkeys(buf, ":Evaluate p\<CR>")
|
||||
call TermWait(buf, 400)
|
||||
call VerifyScreenDump(buf, 'Test_termdebug_evaluate_in_popup_01', {})
|
||||
|
||||
call term_sendkeys(buf, ":Evaluate p_ptr\<CR>")
|
||||
call TermWait(buf, 400)
|
||||
call VerifyScreenDump(buf, 'Test_termdebug_evaluate_in_popup_02', {})
|
||||
|
||||
" Cleanup
|
||||
call term_sendkeys(buf, ":Gdb")
|
||||
call term_sendkeys(buf, ":quit!\<CR>")
|
||||
call term_sendkeys(buf, ":qa!\<CR>")
|
||||
call StopVimInTerminal(buf)
|
||||
call delete(bin_name)
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
func Test_termdebug_mapping()
|
||||
%bw!
|
||||
call assert_true(maparg('K', 'n', 0, 1)->empty())
|
||||
|
@ -704,6 +704,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
817,
|
||||
/**/
|
||||
816,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user