summaryrefslogtreecommitdiffstats
path: root/runtime/pack
diff options
context:
space:
mode:
authorlaburnumT <flo.striker@gmail.com>2023-05-13 16:29:15 +0200
committerChristian Brabandt <cb@256bit.org>2023-08-20 20:00:27 +0200
commit9f29621415146abc046471440515e9e34f3e57a1 (patch)
tree4af74897b346f882cbf73013120814b31aa7ac11 /runtime/pack
parent72904d5fda0a1bc78f4bc9080c158226e6e90d5c (diff)
Runtime(termdebug): Add support to view local and argument variables
closes: 12403 Signed-off-by: Christian Brabandt <cb@256bit.org>
Diffstat (limited to 'runtime/pack')
-rw-r--r--runtime/pack/dist/opt/termdebug/plugin/termdebug.vim179
1 files changed, 157 insertions, 22 deletions
diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
index d053851024..2c6b98828f 100644
--- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
+++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
@@ -69,6 +69,7 @@ let s:pc_id = 12
let s:asm_id = 13
let s:break_id = 14 " breakpoint number is added to this
let s:stopped = 1
+let s:running = 0
let s:parsing_disasm_msg = 0
let s:asm_lines = []
@@ -145,6 +146,9 @@ func s:StartDebug_internal(dict)
let s:ptywin = 0
let s:pid = 0
let s:asmwin = 0
+ let s:asmbuf = 0
+ let s:varwin = 0
+ let s:varbuf = 0
if exists('#User#TermdebugStartPre')
doauto <nomodeline> User TermdebugStartPre
@@ -153,7 +157,7 @@ func s:StartDebug_internal(dict)
" Uncomment this line to write logging in "debuglog".
" call ch_logfile('debuglog', 'w')
- let s:sourcewin = win_getid(winnr())
+ let s:sourcewin = win_getid()
" Remember the old value of 'signcolumn' for each buffer that it's set in, so
" that we can restore the value for all buffers.
@@ -201,11 +205,17 @@ func s:StartDebug_internal(dict)
endif
if s:GetDisasmWindow()
- let curwinid = win_getid(winnr())
+ let curwinid = win_getid()
call s:GotoAsmwinOrCreateIt()
call win_gotoid(curwinid)
endif
+ if s:GetVariablesWindow()
+ let curwinid = win_getid()
+ call s:GotoVariableswinOrCreateIt()
+ call win_gotoid(curwinid)
+ endif
+
if exists('#User#TermdebugStartPost')
doauto <nomodeline> User TermdebugStartPost
endif
@@ -215,6 +225,13 @@ endfunc
func s:CloseBuffers()
exe 'bwipe! ' . s:ptybuf
exe 'bwipe! ' . s:commbuf
+ if s:asmbuf > 0
+ exe 'bwipe! ' . s:asmbuf
+ endif
+ if s:varbuf > 0
+ exe 'bwipe! ' . s:varbuf
+ endif
+ s:running = 0
unlet! s:gdbwin
endfunc
@@ -239,7 +256,7 @@ func s:StartDebug_term(dict)
return
endif
let pty = job_info(term_getjob(s:ptybuf))['tty_out']
- let s:ptywin = win_getid(winnr())
+ let s:ptywin = win_getid()
if s:vertical
" Assuming the source code window will get a signcolumn, use two more
" columns for that, thus one less for the terminal window.
@@ -302,7 +319,7 @@ func s:StartDebug_term(dict)
call s:CloseBuffers()
return
endif
- let s:gdbwin = win_getid(winnr())
+ let s:gdbwin = win_getid()
" Wait for the "startupdone" message before sending any commands.
let try_count = 0
@@ -390,7 +407,7 @@ func s:StartDebug_prompt(dict)
else
new
endif
- let s:gdbwin = win_getid(winnr())
+ let s:gdbwin = win_getid()
let s:promptbuf = bufnr('')
call prompt_setprompt(s:promptbuf, 'gdb> ')
set buftype=prompt
@@ -451,7 +468,7 @@ func s:StartDebug_prompt(dict)
call job_stop(s:gdbjob)
return
endif
- let s:ptywin = win_getid(winnr())
+ let s:ptywin = win_getid()
let pty = job_info(term_getjob(s:ptybuf))['tty_out']
call s:SendCommand('tty ' . pty)
@@ -615,7 +632,7 @@ func s:GdbOutCallback(channel, text)
return
endif
- let curwinid = win_getid(winnr())
+ let curwinid = win_getid()
call win_gotoid(s:gdbwin)
" Add the output above the current prompt.
@@ -688,13 +705,20 @@ func s:EndTermDebug(job, status)
endif
exe 'bwipe! ' . s:commbuf
+ if s:asmbuf > 0
+ exe 'bwipe! ' . s:asmbuf
+ endif
+ if s:varbuf > 0
+ exe 'bwipe! ' . s:varbuf
+ endif
+ let s:running = 0
unlet s:gdbwin
call s:EndDebugCommon()
endfunc
func s:EndDebugCommon()
- let curwinid = win_getid(winnr())
+ let curwinid = win_getid()
if exists('s:ptybuf') && s:ptybuf
exe 'bwipe! ' . s:ptybuf
@@ -746,7 +770,7 @@ func s:EndPromptDebug(job, status)
doauto <nomodeline> User TermdebugStopPre
endif
- let curwinid = win_getid(winnr())
+ let curwinid = win_getid()
call win_gotoid(s:gdbwin)
set nomodified
close
@@ -777,9 +801,9 @@ endfunc
" - CommOutput: ^error,msg="No function contains specified address."
func s:HandleDisasmMsg(msg)
if a:msg =~ '^\^done'
- let curwinid = win_getid(winnr())
+ let curwinid = win_getid()
if win_gotoid(s:asmwin)
- silent normal! gg0"_dG
+ silent! %delete _
call setline(1, s:asm_lines)
set nomodified
set filetype=asm
@@ -822,6 +846,49 @@ func s:HandleDisasmMsg(msg)
endif
endfunc
+func s:ParseVarinfo(varinfo)
+ let dict = {}
+ let nameIdx = matchstrpos(a:varinfo, '{name="\([^"]*\)"')
+ let dict['name'] = a:varinfo[nameIdx[1] + 7 : nameIdx[2] - 2]
+ let typeIdx = matchstrpos(a:varinfo, ',type="\([^"]*\)"')
+ let dict['type'] = a:varinfo[typeIdx[1] + 7 : typeIdx[2] - 2]
+ let valueIdx = matchstrpos(a:varinfo, ',value="\(.*\)"}')
+ if valueIdx[1] == -1
+ let dict['value'] = 'Complex value'
+ else
+ let dict['value'] = a:varinfo[valueIdx[1] + 8 : valueIdx[2] - 3]
+ endif
+ return dict
+endfunc
+
+func s:HandleVariablesMsg(msg)
+ let curwinid = win_getid()
+ if win_gotoid(s:varwin)
+
+ silent! %delete _
+ let spaceBuffer = 20
+ call setline(1, 'Type' .
+ \ repeat(' ', 16) .
+ \ 'Name' .
+ \ repeat(' ', 16) .
+ \ 'Value')
+ let cnt = 1
+ let capture = '{name=".\{-}",\%(arg=".\{-}",\)\{0,1\}type=".\{-}"\%(,value=".\{-}"\)\{0,1\}}'
+ let varinfo = matchstr(a:msg, capture, 0, cnt)
+ while varinfo != ''
+ let vardict = s:ParseVarinfo(varinfo)
+ call setline(cnt + 1, vardict['type'] .
+ \ repeat(' ', max([20 - len(vardict['type']), 1])) .
+ \ vardict['name'] .
+ \ repeat(' ', max([20 - len(vardict['name']), 1])) .
+ \ vardict['value'])
+ let cnt += 1
+ let varinfo = matchstr(a:msg, capture, 0, cnt)
+ endwhile
+ endif
+ call win_gotoid(curwinid)
+endfunc
+
" Handle a message received from gdb on the GDB/MI interface.
func s:CommOutput(chan, msg)
let msgs = split(a:msg, "\r")
@@ -852,6 +919,8 @@ func s:CommOutput(chan, msg)
elseif msg =~ '^disassemble'
let s:parsing_disasm_msg = 1
let s:asm_lines = []
+ elseif msg =~ '^\^done,variables='
+ call s:HandleVariablesMsg(msg)
endif
endif
endfor
@@ -897,6 +966,7 @@ func s:InstallCommands()
command Program call s:GotoProgram()
command Source call s:GotoSourcewinOrCreateIt()
command Asm call s:GotoAsmwinOrCreateIt()
+ command Var call s:GotoVariableswinOrCreateIt()
command Winbar call s:InstallWinbar(1)
let map = 1
@@ -950,7 +1020,7 @@ func s:InstallWinbar(force)
nnoremenu WinBar.Cont :Continue<CR>
nnoremenu WinBar.Stop :Stop<CR>
nnoremenu WinBar.Eval :Evaluate<CR>
- call add(s:winbar_winids, win_getid(winnr()))
+ call add(s:winbar_winids, win_getid())
endif
endfunc
@@ -971,6 +1041,7 @@ func s:DeleteCommands()
delcommand Program
delcommand Source
delcommand Asm
+ delcommand Var
delcommand Winbar
if exists('s:k_map_saved')
@@ -984,7 +1055,7 @@ func s:DeleteCommands()
if has('menu')
" Remove the WinBar entries from all windows where it was added.
- let curwinid = win_getid(winnr())
+ let curwinid = win_getid()
for winid in s:winbar_winids
if win_gotoid(winid)
aunmenu WinBar.Step
@@ -1240,7 +1311,7 @@ endfunc
func s:GotoSourcewinOrCreateIt()
if !win_gotoid(s:sourcewin)
new
- let s:sourcewin = win_getid(winnr())
+ let s:sourcewin = win_getid()
call s:InstallWinbar(0)
endif
endfunc
@@ -1273,19 +1344,21 @@ func s:GotoAsmwinOrCreateIt()
exe 'new'
endif
- let s:asmwin = win_getid(winnr())
+ let s:asmwin = win_getid()
setlocal nowrap
setlocal number
setlocal noswapfile
setlocal buftype=nofile
+ setlocal bufhidden=wipe
+ setlocal signcolumn=no
setlocal modifiable
- let asmbuf = bufnr('Termdebug-asm-listing')
- if asmbuf > 0
- exe 'buffer' . asmbuf
+ if s:asmbuf > 0
+ exe 'buffer' . s:asmbuf
else
- exe 'file Termdebug-asm-listing'
+ silent file Termdebug-asm-listing
+ let s:asmbuf = bufnr('Termdebug-asm-listing')
endif
if s:GetDisasmWindowHeight() > 0
@@ -1306,17 +1379,75 @@ func s:GotoAsmwinOrCreateIt()
endif
endfunc
+func s:GetVariablesWindow()
+ if exists('g:termdebug_config')
+ return get(g:termdebug_config, 'variables_window', 0)
+ endif
+ if exists('g:termdebug_disasm_window')
+ return g:termdebug_variables_window
+ endif
+ return 0
+endfunc
+
+func s:GetVariablesWindowHeight()
+ if exists('g:termdebug_config')
+ return get(g:termdebug_config, 'variables_window_height', 0)
+ endif
+ if exists('g:termdebug_variables_window') && g:termdebug_variables_window > 1
+ return g:termdebug_variables_window
+ endif
+ return 0
+endfunc
+
+func s:GotoVariableswinOrCreateIt()
+ if !win_gotoid(s:varwin)
+ if win_gotoid(s:sourcewin)
+ exe 'rightbelow new'
+ else
+ exe 'new'
+ endif
+
+ let s:varwin = win_getid()
+
+ setlocal nowrap
+ setlocal noswapfile
+ setlocal buftype=nofile
+ setlocal bufhidden=wipe
+ setlocal signcolumn=no
+ setlocal modifiable
+
+ if s:varbuf > 0
+ exe 'buffer' . s:varbuf
+ else
+ silent file Termdebug-variables-listing
+ let s:varbuf = bufnr('Termdebug-variables-listing')
+ endif
+
+ if s:GetVariablesWindowHeight() > 0
+ exe 'resize ' .. s:GetVariablesWindowHeight()
+ endif
+ endif
+
+ if s:running
+ call s:SendCommand('-stack-list-variables 2')
+ endif
+endfunc
+
" Handle stopping and running message from gdb.
" Will update the sign that shows the current position.
func s:HandleCursor(msg)
- let wid = win_getid(winnr())
+ let wid = win_getid()
if a:msg =~ '^\*stopped'
call ch_log('program stopped')
let s:stopped = 1
+ if a:msg =~ '^\*stopped,reason="exited-normally"'
+ let s:running = 0
+ endif
elseif a:msg =~ '^\*running'
call ch_log('program running')
let s:stopped = 0
+ let s:running = 1
endif
if a:msg =~ 'fullname='
@@ -1330,7 +1461,7 @@ func s:HandleCursor(msg)
if asm_addr != ''
let s:asm_addr = asm_addr
- let curwinid = win_getid(winnr())
+ let curwinid = win_getid()
if win_gotoid(s:asmwin)
let lnum = search('^' . s:asm_addr)
if lnum == 0
@@ -1345,6 +1476,10 @@ func s:HandleCursor(msg)
endif
endif
+ if s:running && s:stopped && bufwinnr('Termdebug-variables-listing') != -1
+ call s:SendCommand('-stack-list-variables 2')
+ endif
+
if a:msg =~ '^\(\*stopped\|=thread-selected\)' && filereadable(fname)
let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\1', '')
if lnum =~ '^[0-9]*$'
@@ -1363,7 +1498,7 @@ echomsg 'different fname: "' .. expand('%:p') .. '" vs "' .. fnamemodify(fname,
if &modified
" TODO: find existing window
exe 'split ' . fnameescape(fname)
- let s:sourcewin = win_getid(winnr())
+ let s:sourcewin = win_getid()
call s:InstallWinbar(0)
else
exe 'edit ' . fnameescape(fname)