1fe386641SBram Moolenaar" Debugger plugin using gdb.
2c572da5fSBram Moolenaar"
3c572da5fSBram Moolenaar" WORK IN PROGRESS - much doesn't work yet
4c572da5fSBram Moolenaar"
5fe386641SBram Moolenaar" Open two visible terminal windows:
6c572da5fSBram Moolenaar" 1. run a pty, as with ":term NONE"
7c572da5fSBram Moolenaar" 2. run gdb, passing the pty
8fe386641SBram Moolenaar" The current window is used to view source code and follows gdb.
9fe386641SBram Moolenaar"
10fe386641SBram Moolenaar" A third terminal window is hidden, it is used for communication with gdb.
11fe386641SBram Moolenaar"
12fe386641SBram Moolenaar" The communication with gdb uses GDB/MI.  See:
13fe386641SBram Moolenaar" https://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI.html
14c572da5fSBram Moolenaar"
15c572da5fSBram Moolenaar" Author: Bram Moolenaar
16fe386641SBram Moolenaar" Copyright: Vim license applies, see ":help license"
17c572da5fSBram Moolenaar
1837c64c78SBram Moolenaar" In case this gets loaded twice.
1937c64c78SBram Moolenaarif exists(':Termdebug')
2037c64c78SBram Moolenaar  finish
2137c64c78SBram Moolenaarendif
2237c64c78SBram Moolenaar
23*60e73f2aSBram Moolenaar" Uncomment this line to write logging in "debuglog".
24*60e73f2aSBram Moolenaar" call ch_logfile('debuglog', 'w')
25*60e73f2aSBram Moolenaar
26fe386641SBram Moolenaar" The command that starts debugging, e.g. ":Termdebug vim".
27fe386641SBram Moolenaar" To end type "quit" in the gdb window.
28c572da5fSBram Moolenaarcommand -nargs=* -complete=file Termdebug call s:StartDebug(<q-args>)
29c572da5fSBram Moolenaar
30fe386641SBram Moolenaar" Name of the gdb command, defaults to "gdb".
31e09ba7baSBram Moolenaarif !exists('termdebugger')
32e09ba7baSBram Moolenaar  let termdebugger = 'gdb'
33c572da5fSBram Moolenaarendif
34c572da5fSBram Moolenaar
35fe386641SBram Moolenaarlet s:pc_id = 12
36e09ba7baSBram Moolenaarlet s:break_id = 13
37*60e73f2aSBram Moolenaarlet s:stopped = 1
38e09ba7baSBram Moolenaar
39e09ba7baSBram Moolenaarif &background == 'light'
40e09ba7baSBram Moolenaar  hi default debugPC term=reverse ctermbg=lightblue guibg=lightblue
41e09ba7baSBram Moolenaarelse
42e09ba7baSBram Moolenaar  hi default debugPC term=reverse ctermbg=darkblue guibg=darkblue
43e09ba7baSBram Moolenaarendif
44e09ba7baSBram Moolenaarhi default debugBreakpoint term=reverse ctermbg=red guibg=red
45fe386641SBram Moolenaar
46c572da5fSBram Moolenaarfunc s:StartDebug(cmd)
47fe386641SBram Moolenaar  let s:startwin = win_getid(winnr())
48fe386641SBram Moolenaar  let s:startsigncolumn = &signcolumn
49fe386641SBram Moolenaar
5024a98a0eSBram Moolenaar  let s:save_columns = 0
5124a98a0eSBram Moolenaar  if exists('g:termdebug_wide')
5224a98a0eSBram Moolenaar    if &columns < g:termdebug_wide
5338baa3e6SBram Moolenaar      let s:save_columns = &columns
5438baa3e6SBram Moolenaar      let &columns = g:termdebug_wide
5524a98a0eSBram Moolenaar    endif
5638baa3e6SBram Moolenaar    let vertical = 1
5738baa3e6SBram Moolenaar  else
5838baa3e6SBram Moolenaar    let vertical = 0
5938baa3e6SBram Moolenaar  endif
6038baa3e6SBram Moolenaar
61c572da5fSBram Moolenaar  " Open a terminal window without a job, to run the debugged program
62fe386641SBram Moolenaar  let s:ptybuf = term_start('NONE', {
63fe386641SBram Moolenaar	\ 'term_name': 'gdb program',
6438baa3e6SBram Moolenaar	\ 'vertical': vertical,
65fe386641SBram Moolenaar	\ })
66fe386641SBram Moolenaar  if s:ptybuf == 0
67fe386641SBram Moolenaar    echoerr 'Failed to open the program terminal window'
68fe386641SBram Moolenaar    return
69fe386641SBram Moolenaar  endif
70fe386641SBram Moolenaar  let pty = job_info(term_getjob(s:ptybuf))['tty_out']
7145d5f26dSBram Moolenaar  let s:ptywin = win_getid(winnr())
72fe386641SBram Moolenaar
73fe386641SBram Moolenaar  " Create a hidden terminal window to communicate with gdb
74fe386641SBram Moolenaar  let s:commbuf = term_start('NONE', {
75fe386641SBram Moolenaar	\ 'term_name': 'gdb communication',
76fe386641SBram Moolenaar	\ 'out_cb': function('s:CommOutput'),
77fe386641SBram Moolenaar	\ 'hidden': 1,
78fe386641SBram Moolenaar	\ })
79fe386641SBram Moolenaar  if s:commbuf == 0
80fe386641SBram Moolenaar    echoerr 'Failed to open the communication terminal window'
81fe386641SBram Moolenaar    exe 'bwipe! ' . s:ptybuf
82fe386641SBram Moolenaar    return
83fe386641SBram Moolenaar  endif
84fe386641SBram Moolenaar  let commpty = job_info(term_getjob(s:commbuf))['tty_out']
85c572da5fSBram Moolenaar
86c572da5fSBram Moolenaar  " Open a terminal window to run the debugger.
87c3632516SBram Moolenaar  " Add -quiet to avoid the intro message causing a hit-enter prompt.
88c3632516SBram Moolenaar  let cmd = [g:termdebugger, '-quiet', '-tty', pty, a:cmd]
89c572da5fSBram Moolenaar  echomsg 'executing "' . join(cmd) . '"'
90*60e73f2aSBram Moolenaar  let s:gdbbuf = term_start(cmd, {
91c572da5fSBram Moolenaar	\ 'exit_cb': function('s:EndDebug'),
92fe386641SBram Moolenaar	\ 'term_finish': 'close',
93c572da5fSBram Moolenaar	\ })
94*60e73f2aSBram Moolenaar  if s:gdbbuf == 0
95fe386641SBram Moolenaar    echoerr 'Failed to open the gdb terminal window'
96fe386641SBram Moolenaar    exe 'bwipe! ' . s:ptybuf
97fe386641SBram Moolenaar    exe 'bwipe! ' . s:commbuf
98fe386641SBram Moolenaar    return
99fe386641SBram Moolenaar  endif
10045d5f26dSBram Moolenaar  let s:gdbwin = win_getid(winnr())
101fe386641SBram Moolenaar
102fe386641SBram Moolenaar  " Connect gdb to the communication pty, using the GDB/MI interface
10301164a65SBram Moolenaar  " If you get an error "undefined command" your GDB is too old.
104*60e73f2aSBram Moolenaar  call term_sendkeys(s:gdbbuf, 'new-ui mi ' . commpty . "\r")
105*60e73f2aSBram Moolenaar
106*60e73f2aSBram Moolenaar  " Interpret commands while the target is running.  This should usualy only be
107*60e73f2aSBram Moolenaar  " exec-interrupt, since many commands don't work properly while the target is
108*60e73f2aSBram Moolenaar  " running.
109*60e73f2aSBram Moolenaar  call s:SendCommand('-gdb-set mi-async on')
110e09ba7baSBram Moolenaar
11138baa3e6SBram Moolenaar  " Sign used to highlight the line where the program has stopped.
11238baa3e6SBram Moolenaar  " There can be only one.
11338baa3e6SBram Moolenaar  sign define debugPC linehl=debugPC
11438baa3e6SBram Moolenaar
11538baa3e6SBram Moolenaar  " Sign used to indicate a breakpoint.
11638baa3e6SBram Moolenaar  " Can be used multiple times.
11738baa3e6SBram Moolenaar  sign define debugBreakpoint text=>> texthl=debugBreakpoint
11838baa3e6SBram Moolenaar
11945d5f26dSBram Moolenaar  " Install debugger commands in the text window.
12045d5f26dSBram Moolenaar  call win_gotoid(s:startwin)
121e09ba7baSBram Moolenaar  call s:InstallCommands()
12245d5f26dSBram Moolenaar  call win_gotoid(s:gdbwin)
123e09ba7baSBram Moolenaar
124e09ba7baSBram Moolenaar  let s:breakpoints = {}
1251b9645deSBram Moolenaar
1261b9645deSBram Moolenaar  augroup TermDebug
1271b9645deSBram Moolenaar    au BufRead * call s:BufRead()
1281b9645deSBram Moolenaar    au BufUnload * call s:BufUnloaded()
1291b9645deSBram Moolenaar  augroup END
130c572da5fSBram Moolenaarendfunc
131c572da5fSBram Moolenaar
132c572da5fSBram Moolenaarfunc s:EndDebug(job, status)
133c572da5fSBram Moolenaar  exe 'bwipe! ' . s:ptybuf
134fe386641SBram Moolenaar  exe 'bwipe! ' . s:commbuf
135e09ba7baSBram Moolenaar
136e09ba7baSBram Moolenaar  let curwinid = win_getid(winnr())
137e09ba7baSBram Moolenaar
138e09ba7baSBram Moolenaar  call win_gotoid(s:startwin)
139e09ba7baSBram Moolenaar  let &signcolumn = s:startsigncolumn
140e09ba7baSBram Moolenaar  call s:DeleteCommands()
141e09ba7baSBram Moolenaar
142e09ba7baSBram Moolenaar  call win_gotoid(curwinid)
14338baa3e6SBram Moolenaar  if s:save_columns > 0
14438baa3e6SBram Moolenaar    let &columns = s:save_columns
14538baa3e6SBram Moolenaar  endif
1461b9645deSBram Moolenaar
1471b9645deSBram Moolenaar  au! TermDebug
148fe386641SBram Moolenaarendfunc
149fe386641SBram Moolenaar
150fe386641SBram Moolenaar" Handle a message received from gdb on the GDB/MI interface.
151fe386641SBram Moolenaarfunc s:CommOutput(chan, msg)
152fe386641SBram Moolenaar  let msgs = split(a:msg, "\r")
153fe386641SBram Moolenaar
154fe386641SBram Moolenaar  for msg in msgs
155fe386641SBram Moolenaar    " remove prefixed NL
156fe386641SBram Moolenaar    if msg[0] == "\n"
157fe386641SBram Moolenaar      let msg = msg[1:]
158fe386641SBram Moolenaar    endif
159fe386641SBram Moolenaar    if msg != ''
1601b9645deSBram Moolenaar      if msg =~ '^\(\*stopped\|\*running\|=thread-selected\)'
161e09ba7baSBram Moolenaar	call s:HandleCursor(msg)
16245d5f26dSBram Moolenaar      elseif msg =~ '^\^done,bkpt=' || msg =~ '^=breakpoint-created,'
163e09ba7baSBram Moolenaar	call s:HandleNewBreakpoint(msg)
164e09ba7baSBram Moolenaar      elseif msg =~ '^=breakpoint-deleted,'
165e09ba7baSBram Moolenaar	call s:HandleBreakpointDelete(msg)
16645d5f26dSBram Moolenaar      elseif msg =~ '^\^done,value='
16745d5f26dSBram Moolenaar	call s:HandleEvaluate(msg)
16845d5f26dSBram Moolenaar      elseif msg =~ '^\^error,msg='
16945d5f26dSBram Moolenaar	call s:HandleError(msg)
170e09ba7baSBram Moolenaar      endif
171e09ba7baSBram Moolenaar    endif
172e09ba7baSBram Moolenaar  endfor
173e09ba7baSBram Moolenaarendfunc
174e09ba7baSBram Moolenaar
175e09ba7baSBram Moolenaar" Install commands in the current window to control the debugger.
176e09ba7baSBram Moolenaarfunc s:InstallCommands()
177e09ba7baSBram Moolenaar  command Break call s:SetBreakpoint()
178e09ba7baSBram Moolenaar  command Delete call s:DeleteBreakpoint()
179e09ba7baSBram Moolenaar  command Step call s:SendCommand('-exec-step')
18045d5f26dSBram Moolenaar  command Over call s:SendCommand('-exec-next')
181e09ba7baSBram Moolenaar  command Finish call s:SendCommand('-exec-finish')
182*60e73f2aSBram Moolenaar  command -nargs=* Run call s:Run(<q-args>)
183*60e73f2aSBram Moolenaar  command -nargs=* Arguments call s:SendCommand('-exec-arguments ' . <q-args>)
184*60e73f2aSBram Moolenaar  command Stop call s:SendCommand('-exec-interrupt')
185e09ba7baSBram Moolenaar  command Continue call s:SendCommand('-exec-continue')
18645d5f26dSBram Moolenaar  command -range -nargs=* Evaluate call s:Evaluate(<range>, <q-args>)
18745d5f26dSBram Moolenaar  command Gdb call win_gotoid(s:gdbwin)
18845d5f26dSBram Moolenaar  command Program call win_gotoid(s:ptywin)
18945d5f26dSBram Moolenaar
19045d5f26dSBram Moolenaar  " TODO: can the K mapping be restored?
19145d5f26dSBram Moolenaar  nnoremap K :Evaluate<CR>
1921b9645deSBram Moolenaar
1931b9645deSBram Moolenaar  if has('menu')
19424a98a0eSBram Moolenaar    nnoremenu WinBar.Step :Step<CR>
19524a98a0eSBram Moolenaar    nnoremenu WinBar.Next :Over<CR>
19624a98a0eSBram Moolenaar    nnoremenu WinBar.Finish :Finish<CR>
19724a98a0eSBram Moolenaar    nnoremenu WinBar.Cont :Continue<CR>
198*60e73f2aSBram Moolenaar    nnoremenu WinBar.Stop :Stop<CR>
19924a98a0eSBram Moolenaar    nnoremenu WinBar.Eval :Evaluate<CR>
2001b9645deSBram Moolenaar  endif
201e09ba7baSBram Moolenaarendfunc
202e09ba7baSBram Moolenaar
203e09ba7baSBram Moolenaar" Delete installed debugger commands in the current window.
204e09ba7baSBram Moolenaarfunc s:DeleteCommands()
205e09ba7baSBram Moolenaar  delcommand Break
206e09ba7baSBram Moolenaar  delcommand Delete
207e09ba7baSBram Moolenaar  delcommand Step
20845d5f26dSBram Moolenaar  delcommand Over
209e09ba7baSBram Moolenaar  delcommand Finish
210*60e73f2aSBram Moolenaar  delcommand Run
211*60e73f2aSBram Moolenaar  delcommand Arguments
212*60e73f2aSBram Moolenaar  delcommand Stop
213e09ba7baSBram Moolenaar  delcommand Continue
21445d5f26dSBram Moolenaar  delcommand Evaluate
21545d5f26dSBram Moolenaar  delcommand Gdb
21645d5f26dSBram Moolenaar  delcommand Program
21745d5f26dSBram Moolenaar
21845d5f26dSBram Moolenaar  nunmap K
2191b9645deSBram Moolenaar
2201b9645deSBram Moolenaar  if has('menu')
2211b9645deSBram Moolenaar    aunmenu WinBar.Step
2221b9645deSBram Moolenaar    aunmenu WinBar.Next
2231b9645deSBram Moolenaar    aunmenu WinBar.Finish
2241b9645deSBram Moolenaar    aunmenu WinBar.Cont
225*60e73f2aSBram Moolenaar    aunmenu WinBar.Stop
2261b9645deSBram Moolenaar    aunmenu WinBar.Eval
2271b9645deSBram Moolenaar  endif
2281b9645deSBram Moolenaar
22945d5f26dSBram Moolenaar  exe 'sign unplace ' . s:pc_id
23045d5f26dSBram Moolenaar  for key in keys(s:breakpoints)
23145d5f26dSBram Moolenaar    exe 'sign unplace ' . (s:break_id + key)
23245d5f26dSBram Moolenaar  endfor
23338baa3e6SBram Moolenaar  sign undefine debugPC
23438baa3e6SBram Moolenaar  sign undefine debugBreakpoint
23545d5f26dSBram Moolenaar  unlet s:breakpoints
236e09ba7baSBram Moolenaarendfunc
237e09ba7baSBram Moolenaar
238e09ba7baSBram Moolenaar" :Break - Set a breakpoint at the cursor position.
239e09ba7baSBram Moolenaarfunc s:SetBreakpoint()
240*60e73f2aSBram Moolenaar  " Setting a breakpoint may not work while the program is running.
241*60e73f2aSBram Moolenaar  " Interrupt to make it work.
242*60e73f2aSBram Moolenaar  let do_continue = 0
243*60e73f2aSBram Moolenaar  if !s:stopped
244*60e73f2aSBram Moolenaar    let do_continue = 1
245*60e73f2aSBram Moolenaar    call s:SendCommand('-exec-interrupt')
246*60e73f2aSBram Moolenaar    sleep 10m
247*60e73f2aSBram Moolenaar  endif
248*60e73f2aSBram Moolenaar  call s:SendCommand('-break-insert --source '
249*60e73f2aSBram Moolenaar	\ . fnameescape(expand('%:p')) . ' --line ' . line('.'))
250*60e73f2aSBram Moolenaar  if do_continue
251*60e73f2aSBram Moolenaar    call s:SendCommand('-exec-continue')
252*60e73f2aSBram Moolenaar  endif
253e09ba7baSBram Moolenaarendfunc
254e09ba7baSBram Moolenaar
255e09ba7baSBram Moolenaar" :Delete - Delete a breakpoint at the cursor position.
256e09ba7baSBram Moolenaarfunc s:DeleteBreakpoint()
257e09ba7baSBram Moolenaar  let fname = fnameescape(expand('%:p'))
258e09ba7baSBram Moolenaar  let lnum = line('.')
259e09ba7baSBram Moolenaar  for [key, val] in items(s:breakpoints)
260e09ba7baSBram Moolenaar    if val['fname'] == fname && val['lnum'] == lnum
261e09ba7baSBram Moolenaar      call term_sendkeys(s:commbuf, '-break-delete ' . key . "\r")
262e09ba7baSBram Moolenaar      " Assume this always wors, the reply is simply "^done".
263e09ba7baSBram Moolenaar      exe 'sign unplace ' . (s:break_id + key)
264e09ba7baSBram Moolenaar      unlet s:breakpoints[key]
265e09ba7baSBram Moolenaar      break
266e09ba7baSBram Moolenaar    endif
267e09ba7baSBram Moolenaar  endfor
268e09ba7baSBram Moolenaarendfunc
269e09ba7baSBram Moolenaar
270e09ba7baSBram Moolenaar" :Next, :Continue, etc - send a command to gdb
271e09ba7baSBram Moolenaarfunc s:SendCommand(cmd)
272e09ba7baSBram Moolenaar  call term_sendkeys(s:commbuf, a:cmd . "\r")
273e09ba7baSBram Moolenaarendfunc
274e09ba7baSBram Moolenaar
275*60e73f2aSBram Moolenaarfunc s:Run(args)
276*60e73f2aSBram Moolenaar  if a:args != ''
277*60e73f2aSBram Moolenaar    call s:SendCommand('-exec-arguments ' . a:args)
278*60e73f2aSBram Moolenaar  endif
279*60e73f2aSBram Moolenaar  call s:SendCommand('-exec-run')
280*60e73f2aSBram Moolenaarendfunc
281*60e73f2aSBram Moolenaar
28245d5f26dSBram Moolenaar" :Evaluate - evaluate what is under the cursor
28345d5f26dSBram Moolenaarfunc s:Evaluate(range, arg)
28445d5f26dSBram Moolenaar  if a:arg != ''
28545d5f26dSBram Moolenaar    let expr = a:arg
28645d5f26dSBram Moolenaar  elseif a:range == 2
28745d5f26dSBram Moolenaar    let pos = getcurpos()
28845d5f26dSBram Moolenaar    let reg = getreg('v', 1, 1)
28945d5f26dSBram Moolenaar    let regt = getregtype('v')
29045d5f26dSBram Moolenaar    normal! gv"vy
29145d5f26dSBram Moolenaar    let expr = @v
29245d5f26dSBram Moolenaar    call setpos('.', pos)
29345d5f26dSBram Moolenaar    call setreg('v', reg, regt)
29445d5f26dSBram Moolenaar  else
29545d5f26dSBram Moolenaar    let expr = expand('<cexpr>')
29645d5f26dSBram Moolenaar  endif
297*60e73f2aSBram Moolenaar  call s:SendCommand('-data-evaluate-expression "' . expr . '"')
29845d5f26dSBram Moolenaar  let s:evalexpr = expr
29945d5f26dSBram Moolenaarendfunc
30045d5f26dSBram Moolenaar
30145d5f26dSBram Moolenaar" Handle the result of data-evaluate-expression
30245d5f26dSBram Moolenaarfunc s:HandleEvaluate(msg)
3031b9645deSBram Moolenaar  let value = substitute(a:msg, '.*value="\(.*\)"', '\1', '')
3041b9645deSBram Moolenaar  let value = substitute(value, '\\"', '"', 'g')
3051b9645deSBram Moolenaar  echomsg '"' . s:evalexpr . '": ' . value
3061b9645deSBram Moolenaar
3077f2e9d7cSBram Moolenaar  if s:evalexpr[0] != '*' && value =~ '^0x' && value != '0x0' && value !~ '"$'
3081b9645deSBram Moolenaar    " Looks like a pointer, also display what it points to.
3091b9645deSBram Moolenaar    let s:evalexpr = '*' . s:evalexpr
3101b9645deSBram Moolenaar    call term_sendkeys(s:commbuf, '-data-evaluate-expression "' . s:evalexpr . "\"\r")
3111b9645deSBram Moolenaar  endif
31245d5f26dSBram Moolenaarendfunc
31345d5f26dSBram Moolenaar
31445d5f26dSBram Moolenaar" Handle an error.
31545d5f26dSBram Moolenaarfunc s:HandleError(msg)
31645d5f26dSBram Moolenaar  echoerr substitute(a:msg, '.*msg="\(.*\)"', '\1', '')
31745d5f26dSBram Moolenaarendfunc
31845d5f26dSBram Moolenaar
319e09ba7baSBram Moolenaar" Handle stopping and running message from gdb.
320e09ba7baSBram Moolenaar" Will update the sign that shows the current position.
321e09ba7baSBram Moolenaarfunc s:HandleCursor(msg)
322fe386641SBram Moolenaar  let wid = win_getid(winnr())
323fe386641SBram Moolenaar
324*60e73f2aSBram Moolenaar  if a:msg =~ '^\*stopped'
325*60e73f2aSBram Moolenaar    let s:stopped = 1
326*60e73f2aSBram Moolenaar  elseif a:msg =~ '^\*running'
327*60e73f2aSBram Moolenaar    let s:stopped = 0
328*60e73f2aSBram Moolenaar  endif
329*60e73f2aSBram Moolenaar
330fe386641SBram Moolenaar  if win_gotoid(s:startwin)
331e09ba7baSBram Moolenaar    let fname = substitute(a:msg, '.*fullname="\([^"]*\)".*', '\1', '')
3321b9645deSBram Moolenaar    if a:msg =~ '^\(\*stopped\|=thread-selected\)' && filereadable(fname)
333e09ba7baSBram Moolenaar      let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\1', '')
334fe386641SBram Moolenaar      if lnum =~ '^[0-9]*$'
3351b9645deSBram Moolenaar	if expand('%:p') != fnamemodify(fname, ':p')
336fe386641SBram Moolenaar	  if &modified
337fe386641SBram Moolenaar	    " TODO: find existing window
338fe386641SBram Moolenaar	    exe 'split ' . fnameescape(fname)
339fe386641SBram Moolenaar	    let s:startwin = win_getid(winnr())
340fe386641SBram Moolenaar	  else
341fe386641SBram Moolenaar	    exe 'edit ' . fnameescape(fname)
342fe386641SBram Moolenaar	  endif
343fe386641SBram Moolenaar	endif
344fe386641SBram Moolenaar	exe lnum
34501164a65SBram Moolenaar	exe 'sign unplace ' . s:pc_id
3461b9645deSBram Moolenaar	exe 'sign place ' . s:pc_id . ' line=' . lnum . ' name=debugPC file=' . fname
347fe386641SBram Moolenaar	setlocal signcolumn=yes
348fe386641SBram Moolenaar      endif
349fe386641SBram Moolenaar    else
350fe386641SBram Moolenaar      exe 'sign unplace ' . s:pc_id
351fe386641SBram Moolenaar    endif
352fe386641SBram Moolenaar
353fe386641SBram Moolenaar    call win_gotoid(wid)
354fe386641SBram Moolenaar  endif
355e09ba7baSBram Moolenaarendfunc
356e09ba7baSBram Moolenaar
357e09ba7baSBram Moolenaar" Handle setting a breakpoint
358e09ba7baSBram Moolenaar" Will update the sign that shows the breakpoint
359e09ba7baSBram Moolenaarfunc s:HandleNewBreakpoint(msg)
360e09ba7baSBram Moolenaar  let nr = substitute(a:msg, '.*number="\([0-9]\)*\".*', '\1', '') + 0
361e09ba7baSBram Moolenaar  if nr == 0
362e09ba7baSBram Moolenaar    return
363fe386641SBram Moolenaar  endif
364e09ba7baSBram Moolenaar
365e09ba7baSBram Moolenaar  if has_key(s:breakpoints, nr)
366e09ba7baSBram Moolenaar    let entry = s:breakpoints[nr]
367e09ba7baSBram Moolenaar  else
368e09ba7baSBram Moolenaar    let entry = {}
369e09ba7baSBram Moolenaar    let s:breakpoints[nr] = entry
370fe386641SBram Moolenaar  endif
371e09ba7baSBram Moolenaar
372e09ba7baSBram Moolenaar  let fname = substitute(a:msg, '.*fullname="\([^"]*\)".*', '\1', '')
373e09ba7baSBram Moolenaar  let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\1', '')
374e09ba7baSBram Moolenaar  let entry['fname'] = fname
375e09ba7baSBram Moolenaar  let entry['lnum'] = lnum
3761b9645deSBram Moolenaar
3771b9645deSBram Moolenaar  if bufloaded(fname)
3781b9645deSBram Moolenaar    call s:PlaceSign(nr, entry)
3791b9645deSBram Moolenaar  endif
3801b9645deSBram Moolenaarendfunc
3811b9645deSBram Moolenaar
3821b9645deSBram Moolenaarfunc s:PlaceSign(nr, entry)
3831b9645deSBram Moolenaar  exe 'sign place ' . (s:break_id + a:nr) . ' line=' . a:entry['lnum'] . ' name=debugBreakpoint file=' . a:entry['fname']
3841b9645deSBram Moolenaar  let a:entry['placed'] = 1
385e09ba7baSBram Moolenaarendfunc
386e09ba7baSBram Moolenaar
387e09ba7baSBram Moolenaar" Handle deleting a breakpoint
388e09ba7baSBram Moolenaar" Will remove the sign that shows the breakpoint
389e09ba7baSBram Moolenaarfunc s:HandleBreakpointDelete(msg)
390e09ba7baSBram Moolenaar  let nr = substitute(a:msg, '.*id="\([0-9]*\)\".*', '\1', '') + 0
391e09ba7baSBram Moolenaar  if nr == 0
392e09ba7baSBram Moolenaar    return
393e09ba7baSBram Moolenaar  endif
3941b9645deSBram Moolenaar  if has_key(s:breakpoints, nr)
3951b9645deSBram Moolenaar    let entry = s:breakpoints[nr]
3961b9645deSBram Moolenaar    if has_key(entry, 'placed')
397e09ba7baSBram Moolenaar      exe 'sign unplace ' . (s:break_id + nr)
3981b9645deSBram Moolenaar      unlet entry['placed']
3991b9645deSBram Moolenaar    endif
400e09ba7baSBram Moolenaar    unlet s:breakpoints[nr]
4011b9645deSBram Moolenaar  endif
402c572da5fSBram Moolenaarendfunc
4031b9645deSBram Moolenaar
4041b9645deSBram Moolenaar" Handle a BufRead autocommand event: place any signs.
4051b9645deSBram Moolenaarfunc s:BufRead()
4061b9645deSBram Moolenaar  let fname = expand('<afile>:p')
4071b9645deSBram Moolenaar  for [nr, entry] in items(s:breakpoints)
4081b9645deSBram Moolenaar    if entry['fname'] == fname
4091b9645deSBram Moolenaar      call s:PlaceSign(nr, entry)
4101b9645deSBram Moolenaar    endif
4111b9645deSBram Moolenaar  endfor
4121b9645deSBram Moolenaarendfunc
4131b9645deSBram Moolenaar
4141b9645deSBram Moolenaar" Handle a BufUnloaded autocommand event: unplace any signs.
4151b9645deSBram Moolenaarfunc s:BufUnloaded()
4161b9645deSBram Moolenaar  let fname = expand('<afile>:p')
4171b9645deSBram Moolenaar  for [nr, entry] in items(s:breakpoints)
4181b9645deSBram Moolenaar    if entry['fname'] == fname
4191b9645deSBram Moolenaar      let entry['placed'] = 0
4201b9645deSBram Moolenaar    endif
4211b9645deSBram Moolenaar  endfor
4221b9645deSBram Moolenaarendfunc
4231b9645deSBram Moolenaar
424