Mercurial > vim
comparison runtime/pack/dist/opt/termdebug/plugin/termdebug.vim @ 12833:db9ffed7e1fc v8.0.1293
patch 8.0.1293: setting a breakpoint in the terminal debugger sometimes fails
commit https://github.com/vim/vim/commit/60e73f2acc890f07056fa1bea8dbe89d26918b3e
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Nov 12 18:02:06 2017 +0100
patch 8.0.1293: setting a breakpoint in the terminal debugger sometimes fails
Problem: Setting a breakpoint in the terminal debugger sometimes fails.
Solution: Interrupt the program if needed. Set the interface to async.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sun, 12 Nov 2017 18:15:04 +0100 |
parents | f690da1b3c04 |
children | ebb4f6c93598 |
comparison
equal
deleted
inserted
replaced
12832:3b4c04beb913 | 12833:db9ffed7e1fc |
---|---|
18 " In case this gets loaded twice. | 18 " In case this gets loaded twice. |
19 if exists(':Termdebug') | 19 if exists(':Termdebug') |
20 finish | 20 finish |
21 endif | 21 endif |
22 | 22 |
23 " Uncomment this line to write logging in "debuglog". | |
24 " call ch_logfile('debuglog', 'w') | |
25 | |
23 " The command that starts debugging, e.g. ":Termdebug vim". | 26 " The command that starts debugging, e.g. ":Termdebug vim". |
24 " To end type "quit" in the gdb window. | 27 " To end type "quit" in the gdb window. |
25 command -nargs=* -complete=file Termdebug call s:StartDebug(<q-args>) | 28 command -nargs=* -complete=file Termdebug call s:StartDebug(<q-args>) |
26 | 29 |
27 " Name of the gdb command, defaults to "gdb". | 30 " Name of the gdb command, defaults to "gdb". |
29 let termdebugger = 'gdb' | 32 let termdebugger = 'gdb' |
30 endif | 33 endif |
31 | 34 |
32 let s:pc_id = 12 | 35 let s:pc_id = 12 |
33 let s:break_id = 13 | 36 let s:break_id = 13 |
37 let s:stopped = 1 | |
34 | 38 |
35 if &background == 'light' | 39 if &background == 'light' |
36 hi default debugPC term=reverse ctermbg=lightblue guibg=lightblue | 40 hi default debugPC term=reverse ctermbg=lightblue guibg=lightblue |
37 else | 41 else |
38 hi default debugPC term=reverse ctermbg=darkblue guibg=darkblue | 42 hi default debugPC term=reverse ctermbg=darkblue guibg=darkblue |
81 | 85 |
82 " Open a terminal window to run the debugger. | 86 " Open a terminal window to run the debugger. |
83 " Add -quiet to avoid the intro message causing a hit-enter prompt. | 87 " Add -quiet to avoid the intro message causing a hit-enter prompt. |
84 let cmd = [g:termdebugger, '-quiet', '-tty', pty, a:cmd] | 88 let cmd = [g:termdebugger, '-quiet', '-tty', pty, a:cmd] |
85 echomsg 'executing "' . join(cmd) . '"' | 89 echomsg 'executing "' . join(cmd) . '"' |
86 let gdbbuf = term_start(cmd, { | 90 let s:gdbbuf = term_start(cmd, { |
87 \ 'exit_cb': function('s:EndDebug'), | 91 \ 'exit_cb': function('s:EndDebug'), |
88 \ 'term_finish': 'close', | 92 \ 'term_finish': 'close', |
89 \ }) | 93 \ }) |
90 if gdbbuf == 0 | 94 if s:gdbbuf == 0 |
91 echoerr 'Failed to open the gdb terminal window' | 95 echoerr 'Failed to open the gdb terminal window' |
92 exe 'bwipe! ' . s:ptybuf | 96 exe 'bwipe! ' . s:ptybuf |
93 exe 'bwipe! ' . s:commbuf | 97 exe 'bwipe! ' . s:commbuf |
94 return | 98 return |
95 endif | 99 endif |
96 let s:gdbwin = win_getid(winnr()) | 100 let s:gdbwin = win_getid(winnr()) |
97 | 101 |
98 " Connect gdb to the communication pty, using the GDB/MI interface | 102 " Connect gdb to the communication pty, using the GDB/MI interface |
99 " If you get an error "undefined command" your GDB is too old. | 103 " If you get an error "undefined command" your GDB is too old. |
100 call term_sendkeys(gdbbuf, 'new-ui mi ' . commpty . "\r") | 104 call term_sendkeys(s:gdbbuf, 'new-ui mi ' . commpty . "\r") |
105 | |
106 " Interpret commands while the target is running. This should usualy only be | |
107 " exec-interrupt, since many commands don't work properly while the target is | |
108 " running. | |
109 call s:SendCommand('-gdb-set mi-async on') | |
101 | 110 |
102 " Sign used to highlight the line where the program has stopped. | 111 " Sign used to highlight the line where the program has stopped. |
103 " There can be only one. | 112 " There can be only one. |
104 sign define debugPC linehl=debugPC | 113 sign define debugPC linehl=debugPC |
105 | 114 |
168 command Break call s:SetBreakpoint() | 177 command Break call s:SetBreakpoint() |
169 command Delete call s:DeleteBreakpoint() | 178 command Delete call s:DeleteBreakpoint() |
170 command Step call s:SendCommand('-exec-step') | 179 command Step call s:SendCommand('-exec-step') |
171 command Over call s:SendCommand('-exec-next') | 180 command Over call s:SendCommand('-exec-next') |
172 command Finish call s:SendCommand('-exec-finish') | 181 command Finish call s:SendCommand('-exec-finish') |
182 command -nargs=* Run call s:Run(<q-args>) | |
183 command -nargs=* Arguments call s:SendCommand('-exec-arguments ' . <q-args>) | |
184 command Stop call s:SendCommand('-exec-interrupt') | |
173 command Continue call s:SendCommand('-exec-continue') | 185 command Continue call s:SendCommand('-exec-continue') |
174 command -range -nargs=* Evaluate call s:Evaluate(<range>, <q-args>) | 186 command -range -nargs=* Evaluate call s:Evaluate(<range>, <q-args>) |
175 command Gdb call win_gotoid(s:gdbwin) | 187 command Gdb call win_gotoid(s:gdbwin) |
176 command Program call win_gotoid(s:ptywin) | 188 command Program call win_gotoid(s:ptywin) |
177 | 189 |
181 if has('menu') | 193 if has('menu') |
182 nnoremenu WinBar.Step :Step<CR> | 194 nnoremenu WinBar.Step :Step<CR> |
183 nnoremenu WinBar.Next :Over<CR> | 195 nnoremenu WinBar.Next :Over<CR> |
184 nnoremenu WinBar.Finish :Finish<CR> | 196 nnoremenu WinBar.Finish :Finish<CR> |
185 nnoremenu WinBar.Cont :Continue<CR> | 197 nnoremenu WinBar.Cont :Continue<CR> |
198 nnoremenu WinBar.Stop :Stop<CR> | |
186 nnoremenu WinBar.Eval :Evaluate<CR> | 199 nnoremenu WinBar.Eval :Evaluate<CR> |
187 endif | 200 endif |
188 endfunc | 201 endfunc |
189 | 202 |
190 " Delete installed debugger commands in the current window. | 203 " Delete installed debugger commands in the current window. |
192 delcommand Break | 205 delcommand Break |
193 delcommand Delete | 206 delcommand Delete |
194 delcommand Step | 207 delcommand Step |
195 delcommand Over | 208 delcommand Over |
196 delcommand Finish | 209 delcommand Finish |
210 delcommand Run | |
211 delcommand Arguments | |
212 delcommand Stop | |
197 delcommand Continue | 213 delcommand Continue |
198 delcommand Evaluate | 214 delcommand Evaluate |
199 delcommand Gdb | 215 delcommand Gdb |
200 delcommand Program | 216 delcommand Program |
201 | 217 |
204 if has('menu') | 220 if has('menu') |
205 aunmenu WinBar.Step | 221 aunmenu WinBar.Step |
206 aunmenu WinBar.Next | 222 aunmenu WinBar.Next |
207 aunmenu WinBar.Finish | 223 aunmenu WinBar.Finish |
208 aunmenu WinBar.Cont | 224 aunmenu WinBar.Cont |
225 aunmenu WinBar.Stop | |
209 aunmenu WinBar.Eval | 226 aunmenu WinBar.Eval |
210 endif | 227 endif |
211 | 228 |
212 exe 'sign unplace ' . s:pc_id | 229 exe 'sign unplace ' . s:pc_id |
213 for key in keys(s:breakpoints) | 230 for key in keys(s:breakpoints) |
218 unlet s:breakpoints | 235 unlet s:breakpoints |
219 endfunc | 236 endfunc |
220 | 237 |
221 " :Break - Set a breakpoint at the cursor position. | 238 " :Break - Set a breakpoint at the cursor position. |
222 func s:SetBreakpoint() | 239 func s:SetBreakpoint() |
223 call term_sendkeys(s:commbuf, '-break-insert --source ' | 240 " Setting a breakpoint may not work while the program is running. |
224 \ . fnameescape(expand('%:p')) . ' --line ' . line('.') . "\r") | 241 " Interrupt to make it work. |
242 let do_continue = 0 | |
243 if !s:stopped | |
244 let do_continue = 1 | |
245 call s:SendCommand('-exec-interrupt') | |
246 sleep 10m | |
247 endif | |
248 call s:SendCommand('-break-insert --source ' | |
249 \ . fnameescape(expand('%:p')) . ' --line ' . line('.')) | |
250 if do_continue | |
251 call s:SendCommand('-exec-continue') | |
252 endif | |
225 endfunc | 253 endfunc |
226 | 254 |
227 " :Delete - Delete a breakpoint at the cursor position. | 255 " :Delete - Delete a breakpoint at the cursor position. |
228 func s:DeleteBreakpoint() | 256 func s:DeleteBreakpoint() |
229 let fname = fnameescape(expand('%:p')) | 257 let fname = fnameescape(expand('%:p')) |
240 endfunc | 268 endfunc |
241 | 269 |
242 " :Next, :Continue, etc - send a command to gdb | 270 " :Next, :Continue, etc - send a command to gdb |
243 func s:SendCommand(cmd) | 271 func s:SendCommand(cmd) |
244 call term_sendkeys(s:commbuf, a:cmd . "\r") | 272 call term_sendkeys(s:commbuf, a:cmd . "\r") |
273 endfunc | |
274 | |
275 func s:Run(args) | |
276 if a:args != '' | |
277 call s:SendCommand('-exec-arguments ' . a:args) | |
278 endif | |
279 call s:SendCommand('-exec-run') | |
245 endfunc | 280 endfunc |
246 | 281 |
247 " :Evaluate - evaluate what is under the cursor | 282 " :Evaluate - evaluate what is under the cursor |
248 func s:Evaluate(range, arg) | 283 func s:Evaluate(range, arg) |
249 if a:arg != '' | 284 if a:arg != '' |
257 call setpos('.', pos) | 292 call setpos('.', pos) |
258 call setreg('v', reg, regt) | 293 call setreg('v', reg, regt) |
259 else | 294 else |
260 let expr = expand('<cexpr>') | 295 let expr = expand('<cexpr>') |
261 endif | 296 endif |
262 call term_sendkeys(s:commbuf, '-data-evaluate-expression "' . expr . "\"\r") | 297 call s:SendCommand('-data-evaluate-expression "' . expr . '"') |
263 let s:evalexpr = expr | 298 let s:evalexpr = expr |
264 endfunc | 299 endfunc |
265 | 300 |
266 " Handle the result of data-evaluate-expression | 301 " Handle the result of data-evaluate-expression |
267 func s:HandleEvaluate(msg) | 302 func s:HandleEvaluate(msg) |
283 | 318 |
284 " Handle stopping and running message from gdb. | 319 " Handle stopping and running message from gdb. |
285 " Will update the sign that shows the current position. | 320 " Will update the sign that shows the current position. |
286 func s:HandleCursor(msg) | 321 func s:HandleCursor(msg) |
287 let wid = win_getid(winnr()) | 322 let wid = win_getid(winnr()) |
323 | |
324 if a:msg =~ '^\*stopped' | |
325 let s:stopped = 1 | |
326 elseif a:msg =~ '^\*running' | |
327 let s:stopped = 0 | |
328 endif | |
288 | 329 |
289 if win_gotoid(s:startwin) | 330 if win_gotoid(s:startwin) |
290 let fname = substitute(a:msg, '.*fullname="\([^"]*\)".*', '\1', '') | 331 let fname = substitute(a:msg, '.*fullname="\([^"]*\)".*', '\1', '') |
291 if a:msg =~ '^\(\*stopped\|=thread-selected\)' && filereadable(fname) | 332 if a:msg =~ '^\(\*stopped\|=thread-selected\)' && filereadable(fname) |
292 let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\1', '') | 333 let lnum = substitute(a:msg, '.*line="\([^"]*\)".*', '\1', '') |