aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Dewar <seandewar@users.noreply.github.com>2023-08-21 09:28:58 +0100
committerSean Dewar <seandewar@users.noreply.github.com>2023-08-25 10:59:55 +0100
commit949dd14d8b2acfc8feda7410ed35e28a2d895992 (patch)
treed16e7975a6b496d5b2cae73018e4773367eb50be
parent0b0d912763890652c20d219ad92ab8d91195ca02 (diff)
downloadrneovim-949dd14d8b2acfc8feda7410ed35e28a2d895992.tar.gz
rneovim-949dd14d8b2acfc8feda7410ed35e28a2d895992.tar.bz2
rneovim-949dd14d8b2acfc8feda7410ed35e28a2d895992.zip
vim-patch:9f2962141514
Runtime(termdebug): Add support to view local and argument variables closes: 12403 https://github.com/vim/vim/commit/9f29621415146abc046471440515e9e34f3e57a1 Rename the existing "s:running" (#16790) to "s:gdb_running" to not clash with the "s:running" introduced in this patch (which instead relates to whether the debugged program is currently running in gdb). Keep the file `:retab`bed as before. Co-authored-by: laburnumT <flo.striker@gmail.com>
-rw-r--r--runtime/doc/nvim_terminal_emulator.txt13
-rw-r--r--runtime/pack/dist/opt/termdebug/plugin/termdebug.vim195
2 files changed, 177 insertions, 31 deletions
diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt
index bbcc686207..482b608ef9 100644
--- a/runtime/doc/nvim_terminal_emulator.txt
+++ b/runtime/doc/nvim_terminal_emulator.txt
@@ -325,7 +325,9 @@ Other commands ~
isn't one
*:Asm* jump to the window with the disassembly, create it if there
isn't one
-
+ *:Var* jump to the window with the local and argument variables,
+ create it if there isn't one. This window updates whenever the
+ program is stopped
Events ~
*termdebug-events*
@@ -400,6 +402,15 @@ If there is no g:termdebug_config you can use: >vim
let g:termdebug_disasm_window = 15
Any value greater than 1 will set the Asm window height to that value.
+ *termdebug_variables_window*
+If you want the Var window shown by default, set the flag to 1.
+the "variables_window_height" entry can be used to set the window height: >vim
+ let g:termdebug_config['variables_window'] = 1
+ let g:termdebug_config['variables_window_height'] = 15
+If there is no g:termdebug_config you can use: >vim
+ let g:termdebug_variables_window = 15
+Any value greater than 1 will set the Var window height to that value.
+
Communication ~
*termdebug-communication*
There is another, hidden, buffer, which is used for Vim to communicate with
diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
index e8b78b3f5f..a8480fcc43 100644
--- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
+++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
@@ -75,6 +75,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 = []
@@ -151,6 +152,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
@@ -159,7 +163,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.
@@ -207,11 +211,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
@@ -220,11 +230,18 @@ endfunc
" Use when debugger didn't start or ended.
func s:CloseBuffers()
exe 'bwipe! ' . s:ptybuf
+ 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
func s:CheckGdbRunning()
- if !s:running
+ if !s:gdb_running
echoerr string(s:GetCommand()[0]) . ' exited unexpectedly'
call s:CloseBuffers()
return ''
@@ -246,7 +263,7 @@ func s:StartDebug_term(dict)
let pty_job_info = nvim_get_chan_info(s:pty_job_id)
let s:ptybuf = pty_job_info['buffer']
let pty = pty_job_info['pty']
- 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.
@@ -317,11 +334,11 @@ func s:StartDebug_term(dict)
call s:CloseBuffers()
return
endif
- let s:running = v:true
+ let s:gdb_running = v:true
let s:starting = v:true
let gdb_job_info = nvim_get_chan_info(s:gdb_job_id)
let s:gdbbuf = gdb_job_info['buffer']
- let s:gdbwin = win_getid(winnr())
+ let s:gdbwin = win_getid()
" Wait for the "startupdone" message before sending any commands.
let try_count = 0
@@ -409,7 +426,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
@@ -476,7 +493,7 @@ func s:StartDebug_prompt(dict)
let pty_job_info = nvim_get_chan_info(s:pty_job_id)
let s:ptybuf = pty_job_info['buffer']
let pty = pty_job_info['pty']
- let s:ptywin = win_getid(winnr())
+ let s:ptywin = win_getid()
call s:SendCommand('tty ' . pty)
" Since GDB runs in a prompt window, the environment has not been set to
@@ -655,7 +672,7 @@ func s:GdbOutCallback(job_id, msgs, event)
let index += 1
endfor
- let curwinid = win_getid(winnr())
+ let curwinid = win_getid()
call win_gotoid(s:gdbwin)
" Add the output above the current prompt.
@@ -728,7 +745,7 @@ func s:GetAsmAddr(msg)
endfunc
func s:EndTermDebug(job_id, exit_code, event)
- let s:running = v:false
+ let s:gdb_running = v:false
if s:starting
return
endif
@@ -737,13 +754,20 @@ func s:EndTermDebug(job_id, exit_code, event)
doauto <nomodeline> User TermdebugStopPre
endif
+ 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
@@ -785,7 +809,7 @@ func s:EndPromptDebug(job_id, exit_code, event)
doauto <nomodeline> User TermdebugStopPre
endif
- let curwinid = win_getid(winnr())
+ let curwinid = win_getid()
call win_gotoid(s:gdbwin)
close
if curwinid != s:gdbwin
@@ -813,9 +837,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
@@ -857,6 +881,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
+
func s:CommOutput(job_id, msgs, event)
for msg in a:msgs
@@ -885,6 +952,8 @@ func s:CommOutput(job_id, msgs, event)
elseif msg =~ '^disassemble'
let s:parsing_disasm_msg = 1
let s:asm_lines = []
+ elseif msg =~ '^\^done,variables='
+ call s:HandleVariablesMsg(msg)
endif
endif
endfor
@@ -930,6 +999,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
@@ -962,11 +1032,11 @@ func s:InstallCommands()
if popup
let s:saved_mousemodel = &mousemodel
let &mousemodel = 'popup_setpos'
- an 1.200 PopUp.-SEP3- <Nop>
- an 1.210 PopUp.Set\ breakpoint :Break<CR>
- an 1.220 PopUp.Clear\ breakpoint :Clear<CR>
- an 1.230 PopUp.Run\ until :Until<CR>
- an 1.240 PopUp.Evaluate :Evaluate<CR>
+ an 1.200 PopUp.-SEP3- <Nop>
+ an 1.210 PopUp.Set\ breakpoint :Break<CR>
+ an 1.220 PopUp.Clear\ breakpoint :Clear<CR>
+ an 1.230 PopUp.Run\ until :Until<CR>
+ an 1.240 PopUp.Evaluate :Evaluate<CR>
endif
endif
@@ -984,7 +1054,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
@@ -1005,6 +1075,7 @@ func s:DeleteCommands()
delcommand Program
delcommand Source
delcommand Asm
+ delcommand Var
delcommand Winbar
if exists('s:k_map_saved')
@@ -1019,7 +1090,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
@@ -1382,7 +1453,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
@@ -1415,19 +1486,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
@@ -1448,17 +1521,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='
@@ -1472,7 +1603,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
@@ -1487,6 +1618,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]*$'
@@ -1505,7 +1640,7 @@ func s:HandleCursor(msg)
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)