summaryrefslogtreecommitdiffstats
path: root/runtime/pack
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-09-09 22:19:47 +0200
committerBram Moolenaar <Bram@vim.org>2017-09-09 22:19:47 +0200
commite09ba7bae5c867f6d3abc184709dd27488318e97 (patch)
tree8a512ae4bf2dd5d5b02feb8a6b3aed8f94e06d79 /runtime/pack
parent7be9b50fd7e238722c9ba5c0ef1d2a7e7e52b9e3 (diff)
patch 8.0.1085: terminal debugger can't set breakpointsv8.0.1085
Problem: The terminal debugger can't set breakpoints. Solution: Add :Break and :Delete commands. Also commands for stepping through code.
Diffstat (limited to 'runtime/pack')
-rw-r--r--runtime/pack/dist/opt/termdebug/plugin/termdebug.vim174
1 files changed, 142 insertions, 32 deletions
diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
index f69990b52b..1ee887aa55 100644
--- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
+++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
@@ -20,18 +20,26 @@
command -nargs=* -complete=file Termdebug call s:StartDebug(<q-args>)
" Name of the gdb command, defaults to "gdb".
-if !exists('debugger')
- let debugger = 'gdb'
+if !exists('termdebugger')
+ let termdebugger = 'gdb'
endif
" Sign used to highlight the line where the program has stopped.
+" There can be only one.
sign define debugPC linehl=debugPC
+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 debugPC term=reverse ctermbg=lightblue guibg=lightblue
+ hi default debugPC term=reverse ctermbg=lightblue guibg=lightblue
else
- hi debugPC term=reverse ctermbg=darkblue guibg=darkblue
+ hi default debugPC term=reverse ctermbg=darkblue guibg=darkblue
endif
-let s:pc_id = 12
+hi default debugBreakpoint term=reverse ctermbg=red guibg=red
func s:StartDebug(cmd)
let s:startwin = win_getid(winnr())
@@ -61,7 +69,7 @@ func s:StartDebug(cmd)
let commpty = job_info(term_getjob(s:commbuf))['tty_out']
" 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) . '"'
let gdbbuf = term_start(cmd, {
\ 'exit_cb': function('s:EndDebug'),
@@ -76,12 +84,24 @@ func s:StartDebug(cmd)
" Connect gdb to the communication pty, using the GDB/MI interface
call term_sendkeys(gdbbuf, 'new-ui mi ' . commpty . "\r")
+
+ " Install debugger commands.
+ call s:InstallCommands()
+
+ let s:breakpoints = {}
endfunc
func s:EndDebug(job, status)
exe 'bwipe! ' . s:ptybuf
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
" Handle a message received from gdb on the GDB/MI interface.
@@ -95,34 +115,124 @@ func s:CommOutput(chan, msg)
endif
if msg != ''
if msg =~ '^\*\(stopped\|running\)'
- let wid = win_getid(winnr())
-
- if win_gotoid(s:startwin)
- if msg =~ '^\*stopped'
- " TODO: proper parsing
- 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
+ call s:HandleCursor(msg)
+ elseif msg =~ '^\^done,bkpt='
+ call s:HandleNewBreakpoint(msg)
+ elseif msg =~ '^=breakpoint-deleted,'
+ call s:HandleBreakpointDelete(msg)
+ endif
+ endif
+ endfor
+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 'sign unplace ' . s:pc_id
+ exe 'edit ' . fnameescape(fname)
endif
-
- call win_gotoid(wid)
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
- endfor
+
+ 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