mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:8.0.1085: terminal debugger can't set breakpoints
Problem: The terminal debugger can't set breakpoints.
Solution: Add :Break and :Delete commands. Also commands for stepping
through code.
e09ba7bae5
This commit is contained in:
parent
bbc32fc831
commit
9e9015ee23
182
runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
vendored
182
runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
vendored
@ -25,18 +25,26 @@ endif
|
|||||||
command -nargs=* -complete=file Termdebug call s:StartDebug(<q-args>)
|
command -nargs=* -complete=file Termdebug call s:StartDebug(<q-args>)
|
||||||
|
|
||||||
" Name of the gdb command, defaults to "gdb".
|
" Name of the gdb command, defaults to "gdb".
|
||||||
if !exists('debugger')
|
if !exists('termdebugger')
|
||||||
let debugger = 'gdb'
|
let termdebugger = 'gdb'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Sign used to highlight the line where the program has stopped.
|
" Sign used to highlight the line where the program has stopped.
|
||||||
|
" There can be only one.
|
||||||
sign define debugPC linehl=debugPC
|
sign define debugPC linehl=debugPC
|
||||||
if &background == 'light'
|
|
||||||
hi debugPC term=reverse ctermbg=lightblue guibg=lightblue
|
|
||||||
else
|
|
||||||
hi debugPC term=reverse ctermbg=darkblue guibg=darkblue
|
|
||||||
endif
|
|
||||||
let s:pc_id = 12
|
let s:pc_id = 12
|
||||||
|
let s:break_id = 13
|
||||||
|
|
||||||
|
" Sign used to indicate a breakpoint.
|
||||||
|
" Can be used multiple times.
|
||||||
|
sign define debugBreakpoint text=>> texthl=debugBreakpoint
|
||||||
|
|
||||||
|
if &background == 'light'
|
||||||
|
hi default debugPC term=reverse ctermbg=lightblue guibg=lightblue
|
||||||
|
else
|
||||||
|
hi default debugPC term=reverse ctermbg=darkblue guibg=darkblue
|
||||||
|
endif
|
||||||
|
hi default debugBreakpoint term=reverse ctermbg=red guibg=red
|
||||||
|
|
||||||
func s:StartDebug(cmd)
|
func s:StartDebug(cmd)
|
||||||
let s:startwin = win_getid(winnr())
|
let s:startwin = win_getid(winnr())
|
||||||
@ -66,7 +74,7 @@ func s:StartDebug(cmd)
|
|||||||
let commpty = job_info(term_getjob(s:commbuf))['tty_out']
|
let commpty = job_info(term_getjob(s:commbuf))['tty_out']
|
||||||
|
|
||||||
" Open a terminal window to run the debugger.
|
" Open a terminal window to run the debugger.
|
||||||
let cmd = [g:debugger, '-tty', pty, a:cmd]
|
let cmd = [g:termdebugger, '-tty', pty, a:cmd]
|
||||||
echomsg 'executing "' . join(cmd) . '"'
|
echomsg 'executing "' . join(cmd) . '"'
|
||||||
let gdbbuf = term_start(cmd, {
|
let gdbbuf = term_start(cmd, {
|
||||||
\ 'exit_cb': function('s:EndDebug'),
|
\ 'exit_cb': function('s:EndDebug'),
|
||||||
@ -81,12 +89,24 @@ func s:StartDebug(cmd)
|
|||||||
|
|
||||||
" Connect gdb to the communication pty, using the GDB/MI interface
|
" Connect gdb to the communication pty, using the GDB/MI interface
|
||||||
call term_sendkeys(gdbbuf, 'new-ui mi ' . commpty . "\r")
|
call term_sendkeys(gdbbuf, 'new-ui mi ' . commpty . "\r")
|
||||||
|
|
||||||
|
" Install debugger commands.
|
||||||
|
call s:InstallCommands()
|
||||||
|
|
||||||
|
let s:breakpoints = {}
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func s:EndDebug(job, status)
|
func s:EndDebug(job, status)
|
||||||
exe 'bwipe! ' . s:ptybuf
|
exe 'bwipe! ' . s:ptybuf
|
||||||
exe 'bwipe! ' . s:commbuf
|
exe 'bwipe! ' . s:commbuf
|
||||||
call setwinvar(s:startwin, '&signcolumn', s:startsigncolumn)
|
|
||||||
|
let curwinid = win_getid(winnr())
|
||||||
|
|
||||||
|
call win_gotoid(s:startwin)
|
||||||
|
let &signcolumn = s:startsigncolumn
|
||||||
|
call s:DeleteCommands()
|
||||||
|
|
||||||
|
call win_gotoid(curwinid)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" Handle a message received from gdb on the GDB/MI interface.
|
" Handle a message received from gdb on the GDB/MI interface.
|
||||||
@ -100,34 +120,124 @@ func s:CommOutput(chan, msg)
|
|||||||
endif
|
endif
|
||||||
if msg != ''
|
if msg != ''
|
||||||
if msg =~ '^\*\(stopped\|running\)'
|
if msg =~ '^\*\(stopped\|running\)'
|
||||||
let wid = win_getid(winnr())
|
call s:HandleCursor(msg)
|
||||||
|
elseif msg =~ '^\^done,bkpt='
|
||||||
if win_gotoid(s:startwin)
|
call s:HandleNewBreakpoint(msg)
|
||||||
if msg =~ '^\*stopped'
|
elseif msg =~ '^=breakpoint-deleted,'
|
||||||
" TODO: proper parsing
|
call s:HandleBreakpointDelete(msg)
|
||||||
let fname = substitute(msg, '.*fullname="\([^"]*\)".*', '\1', '')
|
|
||||||
let lnum = substitute(msg, '.*line="\([^"]*\)".*', '\1', '')
|
|
||||||
if lnum =~ '^[0-9]*$'
|
|
||||||
if expand('%:h') != fname
|
|
||||||
if &modified
|
|
||||||
" TODO: find existing window
|
|
||||||
exe 'split ' . fnameescape(fname)
|
|
||||||
let s:startwin = win_getid(winnr())
|
|
||||||
else
|
|
||||||
exe 'edit ' . fnameescape(fname)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
exe lnum
|
|
||||||
exe 'sign place ' . s:pc_id . ' line=' . lnum . ' name=debugPC file=' . fnameescape(fname)
|
|
||||||
setlocal signcolumn=yes
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
exe 'sign unplace ' . s:pc_id
|
|
||||||
endif
|
|
||||||
|
|
||||||
call win_gotoid(wid)
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Install commands in the current window to control the debugger.
|
||||||
|
func s:InstallCommands()
|
||||||
|
command Break call s:SetBreakpoint()
|
||||||
|
command Delete call s:DeleteBreakpoint()
|
||||||
|
command Step call s:SendCommand('-exec-step')
|
||||||
|
command NNext call s:SendCommand('-exec-next')
|
||||||
|
command Finish call s:SendCommand('-exec-finish')
|
||||||
|
command Continue call s:SendCommand('-exec-continue')
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Delete installed debugger commands in the current window.
|
||||||
|
func s:DeleteCommands()
|
||||||
|
delcommand Break
|
||||||
|
delcommand Delete
|
||||||
|
delcommand Step
|
||||||
|
delcommand NNext
|
||||||
|
delcommand Finish
|
||||||
|
delcommand Continue
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" :Break - Set a breakpoint at the cursor position.
|
||||||
|
func s:SetBreakpoint()
|
||||||
|
call term_sendkeys(s:commbuf, '-break-insert --source '
|
||||||
|
\ . fnameescape(expand('%:p')) . ' --line ' . line('.') . "\r")
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" :Delete - Delete a breakpoint at the cursor position.
|
||||||
|
func s:DeleteBreakpoint()
|
||||||
|
let fname = fnameescape(expand('%:p'))
|
||||||
|
let lnum = line('.')
|
||||||
|
for [key, val] in items(s:breakpoints)
|
||||||
|
if val['fname'] == fname && val['lnum'] == lnum
|
||||||
|
call term_sendkeys(s:commbuf, '-break-delete ' . key . "\r")
|
||||||
|
" Assume this always wors, the reply is simply "^done".
|
||||||
|
exe 'sign unplace ' . (s:break_id + key)
|
||||||
|
unlet s:breakpoints[key]
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" :Next, :Continue, etc - send a command to gdb
|
||||||
|
func s:SendCommand(cmd)
|
||||||
|
call term_sendkeys(s:commbuf, a:cmd . "\r")
|
||||||
|
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())
|
||||||
|
|
||||||
|
if win_gotoid(s:startwin)
|
||||||
|
if a:msg =~ '^\*stopped'
|
||||||
|
let fname = substitute(a:msg, '.*fullname="\([^"]*\)".*', '\1', '')
|
||||||
|
let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\1', '')
|
||||||
|
if lnum =~ '^[0-9]*$'
|
||||||
|
if expand('%:h') != fname
|
||||||
|
if &modified
|
||||||
|
" TODO: find existing window
|
||||||
|
exe 'split ' . fnameescape(fname)
|
||||||
|
let s:startwin = win_getid(winnr())
|
||||||
|
else
|
||||||
|
exe 'edit ' . fnameescape(fname)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
exe lnum
|
||||||
|
exe 'sign place ' . s:pc_id . ' line=' . lnum . ' name=debugPC file=' . fnameescape(fname)
|
||||||
|
setlocal signcolumn=yes
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
exe 'sign unplace ' . s:pc_id
|
||||||
|
endif
|
||||||
|
|
||||||
|
call win_gotoid(wid)
|
||||||
|
endif
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Handle setting a breakpoint
|
||||||
|
" Will update the sign that shows the breakpoint
|
||||||
|
func s:HandleNewBreakpoint(msg)
|
||||||
|
let nr = substitute(a:msg, '.*number="\([0-9]\)*\".*', '\1', '') + 0
|
||||||
|
if nr == 0
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if has_key(s:breakpoints, nr)
|
||||||
|
let entry = s:breakpoints[nr]
|
||||||
|
else
|
||||||
|
let entry = {}
|
||||||
|
let s:breakpoints[nr] = entry
|
||||||
|
endif
|
||||||
|
|
||||||
|
let fname = substitute(a:msg, '.*fullname="\([^"]*\)".*', '\1', '')
|
||||||
|
let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\1', '')
|
||||||
|
|
||||||
|
exe 'sign place ' . (s:break_id + nr) . ' line=' . lnum . ' name=debugBreakpoint file=' . fnameescape(fname)
|
||||||
|
|
||||||
|
let entry['fname'] = fname
|
||||||
|
let entry['lnum'] = lnum
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Handle deleting a breakpoint
|
||||||
|
" Will remove the sign that shows the breakpoint
|
||||||
|
func s:HandleBreakpointDelete(msg)
|
||||||
|
let nr = substitute(a:msg, '.*id="\([0-9]*\)\".*', '\1', '') + 0
|
||||||
|
if nr == 0
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
exe 'sign unplace ' . (s:break_id + nr)
|
||||||
|
unlet s:breakpoints[nr]
|
||||||
|
endfunc
|
||||||
|
Loading…
Reference in New Issue
Block a user