Skip to content

Commit 8f1d098

Browse files
BigPeetchrisbra
authored andcommitted
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>
1 parent 2abec43 commit 8f1d098

9 files changed

Lines changed: 230 additions & 12 deletions

runtime/doc/tags

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10664,6 +10664,7 @@ termdebug-stepping terminal.txt /*termdebug-stepping*
1066410664
termdebug-timeout terminal.txt /*termdebug-timeout*
1066510665
termdebug-variables terminal.txt /*termdebug-variables*
1066610666
termdebug_disasm_window terminal.txt /*termdebug_disasm_window*
10667+
termdebug_evaluate_in_popup terminal.txt /*termdebug_evaluate_in_popup*
1066710668
termdebug_map_K terminal.txt /*termdebug_map_K*
1066810669
termdebug_map_minus terminal.txt /*termdebug_map_minus*
1066910670
termdebug_map_plus terminal.txt /*termdebug_map_plus*

runtime/doc/terminal.txt

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*terminal.txt* For Vim version 9.1. Last change: 2024 Jul 28
1+
*terminal.txt* For Vim version 9.1. Last change: 2024 Oct 27
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1537,6 +1537,7 @@ If there is no g:termdebug_config you can use: >
15371537
<
15381538
However, the latter form will be deprecated in future releases.
15391539

1540+
15401541
Mappings ~
15411542
The termdebug plugin enables a few default mappings. All those mappings
15421543
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
15911592
and the Var window will be shown side by side with the source code window (and
15921593
the height options won't be used).
15931594

1595+
15941596
Communication ~
15951597
*termdebug-communication*
15961598
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: >
16751677
16761678
However, the latter form will be deprecated in future releases.
16771679

1680+
16781681
Change default signs ~
16791682
*termdebug_signs*
16801683
Termdebug uses the hex number of the breakpoint ID in the signcolumn to
1681-
represent breakpoints. if it is greater than "0xFF", then it will be displayed
1684+
represent breakpoints. If it is greater than "0xFF", then it will be displayed
16821685
as "F+", due to we really only have two screen cells for the sign.
16831686

16841687
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
17161719
'columns'. This is useful when the terminal can't be resized by Vim.
17171720

17181721

1722+
Evaluate in Popup Window at Cursor ~
1723+
*termdebug_evaluate_in_popup*
1724+
By default |:Evaluate| will simply echo its output. For larger entities this
1725+
might become difficult to read or even truncated.
1726+
Alternatively, the evaluation result may be output into a popup window at the
1727+
current cursor position: >
1728+
let g:termdebug_config['evaluate_in_popup'] = v:true
1729+
This can also be used in a "one-shot" manner: >
1730+
func OnCursorHold()
1731+
let g:termdebug_config['evaluate_in_popup'] = v:true
1732+
:Evaluate
1733+
let g:termdebug_config['evaluate_in_popup'] = v:false
1734+
endfunc
1735+
<
17191736
vim:tw=78:ts=8:noet:ft=help:norl:

runtime/pack/dist/opt/termdebug/plugin/termdebug.vim

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,9 @@ var breakpoint_locations: dict<any>
121121
var BreakpointSigns: list<string>
122122

123123
var evalFromBalloonExpr: bool
124-
var evalFromBalloonExprResult: string
124+
var evalInPopup: bool
125+
var evalPopupId: number
126+
var evalExprResult: string
125127
var ignoreEvalError: bool
126128
var evalexpr: string
127129
# Remember the old value of 'signcolumn' for each buffer that it's set in, so
@@ -202,7 +204,9 @@ def InitScriptVariables()
202204
BreakpointSigns = []
203205

204206
evalFromBalloonExpr = false
205-
evalFromBalloonExprResult = ''
207+
evalInPopup = false
208+
evalPopupId = -1
209+
evalExprResult = ''
206210
ignoreEvalError = false
207211
evalexpr = ''
208212
# Remember the old value of 'signcolumn' for each buffer that it's set in, so
@@ -1478,10 +1482,23 @@ def SendEval(expr: string)
14781482
evalexpr = exprLHS
14791483
enddef
14801484

1485+
# Returns whether to evaluate in a popup or not, defaults to false.
1486+
def EvaluateInPopup(): bool
1487+
if exists('g:termdebug_config')
1488+
return get(g:termdebug_config, 'evaluate_in_popup', false)
1489+
endif
1490+
return false
1491+
enddef
1492+
14811493
# :Evaluate - evaluate what is specified / under the cursor
14821494
def Evaluate(range: number, arg: string)
14831495
var expr = GetEvaluationExpression(range, arg)
1484-
echom $"expr: {expr}"
1496+
if EvaluateInPopup()
1497+
evalInPopup = true
1498+
evalExprResult = ''
1499+
else
1500+
echomsg $'expr: {expr}'
1501+
endif
14851502
ignoreEvalError = false
14861503
SendEval(expr)
14871504
enddef
@@ -1541,6 +1558,37 @@ def Balloon_show(expr: string)
15411558
endif
15421559
enddef
15431560

1561+
def Popup_format(expr: string): list<string>
1562+
var lines = expr
1563+
->substitute('{', '{\n', 'g')
1564+
->substitute('}', '\n}', 'g')
1565+
->substitute(',', ',\n', 'g')
1566+
->split('\n')
1567+
var indentation = 0
1568+
var formatted_lines = []
1569+
for line in lines
1570+
var stripped = line->substitute('^\s\+', '', '')
1571+
if stripped =~ '^}'
1572+
indentation -= 2
1573+
endif
1574+
formatted_lines->add(repeat(' ', indentation) .. stripped)
1575+
if stripped =~ '{$'
1576+
indentation += 2
1577+
endif
1578+
endfor
1579+
return formatted_lines
1580+
enddef
1581+
1582+
def Popup_show(expr: string)
1583+
var formatted = Popup_format(expr)
1584+
if evalPopupId != -1
1585+
popup_close(evalPopupId)
1586+
endif
1587+
# Specifying the line is necessary, as the winbar seems to cause issues
1588+
# otherwise. I.e., the popup would be shown one line too high.
1589+
evalPopupId = popup_atcursor(formatted, {'line': 'cursor-1'})
1590+
enddef
1591+
15441592
def HandleEvaluate(msg: string)
15451593
var value = msg
15461594
->substitute('.*value="\(.*\)"', '\1', '')
@@ -1555,13 +1603,12 @@ def HandleEvaluate(msg: string)
15551603
#\ ->substitute('\\0x00', NullRep, 'g')
15561604
#\ ->substitute('\\0x\(\x\x\)', {-> eval('"\x' .. submatch(1) .. '"')}, 'g')
15571605
->substitute(NullRepl, '\\000', 'g')
1558-
if evalFromBalloonExpr
1559-
if empty(evalFromBalloonExprResult)
1560-
evalFromBalloonExprResult = $'{evalexpr}: {value}'
1606+
if evalFromBalloonExpr || evalInPopup
1607+
if empty(evalExprResult)
1608+
evalExprResult = $'{evalexpr}: {value}'
15611609
else
1562-
evalFromBalloonExprResult ..= $' = {value}'
1610+
evalExprResult ..= $' = {value}'
15631611
endif
1564-
Balloon_show(evalFromBalloonExprResult)
15651612
else
15661613
echomsg $'"{evalexpr}": {value}'
15671614
endif
@@ -1570,8 +1617,12 @@ def HandleEvaluate(msg: string)
15701617
# Looks like a pointer, also display what it points to.
15711618
ignoreEvalError = true
15721619
SendEval($'*{evalexpr}')
1573-
else
1620+
elseif evalFromBalloonExpr
1621+
Balloon_show(evalExprResult)
15741622
evalFromBalloonExpr = false
1623+
elseif evalInPopup
1624+
Popup_show(evalExprResult)
1625+
evalInPopup = false
15751626
endif
15761627
enddef
15771628

@@ -1588,7 +1639,7 @@ def TermDebugBalloonExpr(): string
15881639
return ''
15891640
endif
15901641
evalFromBalloonExpr = true
1591-
evalFromBalloonExprResult = ''
1642+
evalExprResult = ''
15921643
ignoreEvalError = true
15931644
var expr = CleanupExpr(v:beval_text)
15941645
SendEval(expr)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
|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&|.|
2+
@75
3+
|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+
@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
5+
|9| @8|r+2#0000e05&|e|t|u|r|n| +0#0000000&|0+0#e000e06&|;+0#e000002&| +0#0000000&@55
6+
@75
7+
|g+0#ffffff16#00e0003|d|b| |[|r|u|n@1|i|n|g|]| @43|1|,|1| @11|T|o|p
8+
| +0#0000000#ffffff0@74
9+
@75
10+
@75
11+
@75
12+
@75
13+
|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
14+
| +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
15+
| +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
16+
| +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
17+
|0+0&#ff404010|1| +0&#5fd7ff255@1>r+0#af5f00255&|e|t|u|r|n| +0#0000000&|0+0#e000002&|;+0#0000000&| @61
18+
| +0#0000e05#a8a8a8255@1|}+0#0000000#ffffff0| @71
19+
|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
20+
|:+0&&|E|v|a|l|u|a|t|e| |p| @63
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
" replace hex addresses with |0|x|f@12|
2+
:%s/|0|x|\(\(\w\|@\)\+|\)\+/|0|x|f@12|/g
3+
4+
" Only keep screen lines relevant to the actual popup and evaluation.
5+
" Especially the top lines are too instable and cause flakiness between
6+
" different systems and tool versions.
7+
normal! G
8+
normal! 8k
9+
normal! dgg
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
|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&|.|
2+
@75
3+
|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+
@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
5+
|9| @8|r+2#0000e05&|e|t|u|r|n| +0#0000000&|0+0#e000e06&|;+0#e000002&| +0#0000000&@55
6+
@75
7+
|g+0#ffffff16#00e0003|d|b| |[|r|u|n@1|i|n|g|]| @43|1|,|1| @11|T|o|p
8+
| +0#0000000#ffffff0@74
9+
@75
10+
@75
11+
@75
12+
@75
13+
|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
14+
| +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
15+
| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1| +0#0000001#ffd7ff255@1|y| |=| |2| @17|}+0#0000000#ffffff0|;| @43
16+
| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1|}+0#0000001#ffd7ff255| @23| +0#0000000#ffffff0@45
17+
|0+0&#ff404010|1| +0&#5fd7ff255@1>r+0#af5f00255&|e|t|u|r|n| +0#0000000&|0+0#e000002&|;+0#0000000&| @61
18+
| +0#0000e05#a8a8a8255@1|}+0#0000000#ffffff0| @71
19+
|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
20+
|:+0&&|E|v|a|l|u|a|t|e| |p|_|p|t|r| @59
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
" replace hex addresses with |0|x|f@12|
2+
:%s/|0|x|\(\(\w\|@\)\+|\)\+/|0|x|f@12|/g
3+
4+
" Only keep screen lines relevant to the actual popup and evaluation.
5+
" Especially the top lines are too instable and cause flakiness between
6+
" different systems and tool versions.
7+
normal! G
8+
normal! 8k
9+
normal! dgg

src/testdir/test_termdebug.vim

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
" Test for the termdebug plugin
22

33
source shared.vim
4+
source screendump.vim
45
source check.vim
56

67
CheckUnix
@@ -243,6 +244,94 @@ func Test_termdebug_tbreak()
243244
%bw!
244245
endfunc
245246

247+
func Test_termdebug_evaluate()
248+
let bin_name = 'XTD_evaluate'
249+
let src_name = bin_name .. '.c'
250+
call s:generate_files(bin_name)
251+
252+
edit XTD_evaluate.c
253+
Termdebug ./XTD_evaluate
254+
call WaitForAssert({-> assert_true(get(g:, "termdebug_is_running", v:false))})
255+
call WaitForAssert({-> assert_equal(3, winnr('$'))})
256+
let gdb_buf = winbufnr(1)
257+
wincmd b
258+
259+
" return stmt in main
260+
Break 22
261+
call term_wait(gdb_buf)
262+
Run
263+
call term_wait(gdb_buf, 400)
264+
redraw!
265+
266+
" Evaluate an expression
267+
Evaluate n
268+
call term_wait(gdb_buf)
269+
call assert_equal(execute('1messages')->trim(), '"n": 7')
270+
Evaluate argc
271+
call term_wait(gdb_buf)
272+
call assert_equal(execute('1messages')->trim(), '"argc": 1')
273+
Evaluate isprime(n)
274+
call term_wait(gdb_buf)
275+
call assert_equal(execute('1messages')->trim(), '"isprime(n)": 1')
276+
277+
wincmd t
278+
quit!
279+
redraw!
280+
call s:cleanup_files(bin_name)
281+
%bw!
282+
endfunc
283+
284+
func Test_termdebug_evaluate_in_popup()
285+
CheckScreendump
286+
let bin_name = 'XTD_evaluate_in_popup'
287+
let src_name = bin_name .. '.c'
288+
let code =<< trim END
289+
struct Point {
290+
int x;
291+
int y;
292+
};
293+
294+
int main(int argc, char* argv[]) {
295+
struct Point p = {argc, 2};
296+
struct Point* p_ptr = &p;
297+
return 0;
298+
}
299+
END
300+
call writefile(code, src_name, 'D')
301+
call system($'{g:GCC} -g -o {bin_name} {src_name}')
302+
303+
let lines =<< trim END
304+
edit XTD_evaluate_in_popup.c
305+
packadd termdebug
306+
let g:termdebug_config = {}
307+
let g:termdebug_config['evaluate_in_popup'] = v:true
308+
Termdebug ./XTD_evaluate_in_popup
309+
wincmd b
310+
Break 9
311+
Run
312+
END
313+
314+
call writefile(lines, 'Xscript', 'D')
315+
let buf = RunVimInTerminal('-S Xscript', {})
316+
call TermWait(buf, 400)
317+
318+
call term_sendkeys(buf, ":Evaluate p\<CR>")
319+
call TermWait(buf, 400)
320+
call VerifyScreenDump(buf, 'Test_termdebug_evaluate_in_popup_01', {})
321+
322+
call term_sendkeys(buf, ":Evaluate p_ptr\<CR>")
323+
call TermWait(buf, 400)
324+
call VerifyScreenDump(buf, 'Test_termdebug_evaluate_in_popup_02', {})
325+
326+
" Cleanup
327+
call term_sendkeys(buf, ":Gdb")
328+
call term_sendkeys(buf, ":quit!\<CR>")
329+
call term_sendkeys(buf, ":qa!\<CR>")
330+
call StopVimInTerminal(buf)
331+
call delete(bin_name)
332+
%bw!
333+
endfunc
334+
246335
func Test_termdebug_mapping()
247336
%bw!
248337
call assert_true(maparg('K', 'n', 0, 1)->empty())

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,8 @@ static char *(features[]) =
704704

705705
static int included_patches[] =
706706
{ /* Add new patch number below this line */
707+
/**/
708+
817,
707709
/**/
708710
816,
709711
/**/

0 commit comments

Comments
 (0)