diff options
-rw-r--r-- | runtime/pack/dist/opt/termdebug/plugin/termdebug.vim | 421 | ||||
-rw-r--r-- | src/testdir/test_termdebug.vim | 11 | ||||
-rw-r--r-- | src/version.c | 2 |
3 files changed, 252 insertions, 182 deletions
diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim index 0a40164b7a..15d0397198 100644 --- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim +++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim @@ -4,7 +4,7 @@ vim9script # Author: Bram Moolenaar # Copyright: Vim license applies, see ":help license" -# Last Change: 2024 Jun 03 +# Last Change: 2024 Jun 13 # Converted to Vim9: Ubaldo Tiberi <ubaldo.tiberi@gmail.com> # WORK IN PROGRESS - The basics works stable, more to come @@ -38,44 +38,56 @@ vim9script # The communication with gdb uses GDB/MI. See: # https://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI.html -# In case this gets sourced twice. +def Echoerr(msg: string) + echohl ErrorMsg | echom $'[termdebug] {msg}' | echohl None +enddef + + +# Variables to keep their status among multiple instances of Termdebug +# Avoid to source the script twice. if exists('g:termdebug_loaded') - finish + Echoerr('Termdebug already loaded.') + finish endif g:termdebug_loaded = true -var way = 'terminal' -var err = 'no errors' +# Script variables declaration. These variables are re-initialized at every +# Termdebug instance +var way: string +var err: string -var pc_id = 12 -var asm_id = 13 -var break_id = 14 # breakpoint number is added to this -var stopped = 1 -var running = 0 +var pc_id: number +var asm_id: number +var break_id: number +var stopped: bool +var running: bool -var parsing_disasm_msg = 0 -var asm_lines = [] -var asm_addr = '' +var parsing_disasm_msg: number +var asm_lines: list<string> +var asm_addr: string # These shall be constants but cannot be initialized here # They indicate the buffer numbers of the main buffers used -var gdbbuf = 0 -var varbuf = 0 -var asmbuf = 0 -var promptbuf = 0 +var gdbbufnr: number +var gdbbufname: string +var varbufnr: number +var varbufname: string +var asmbufnr: number +var asmbufname: string +var promptbuf: number # This is for the "debugged program" thing -var ptybuf = 0 -var commbuf = 0 +var ptybufnr: number +var commbufnr: number -var gdbjob = null_job -var gdb_channel = null_channel +var gdbjob: job +var gdb_channel: channel # These changes because they relate to windows -var pid = 0 -var gdbwin = 0 -var varwin = 0 -var asmwin = 0 -var ptywin = 0 -var sourcewin = 0 +var pid: number +var gdbwin: number +var varwin: number +var asmwin: number +var ptywin: number +var sourcewin: number # Contains breakpoints that have been placed, key is a string with the GDB # breakpoint number. @@ -84,52 +96,112 @@ var sourcewin = 0 # For a breakpoint "123.4" the id is "123" and subid is "4". # Example, when breakpoint "44", "123", "123.1" and "123.2" exist: # {'44': {'0': entry}, '123': {'0': entry, '1': entry, '2': entry}} -var breakpoints = {} +var breakpoints: dict<any> # Contains breakpoints by file/lnum. The key is "fname:lnum". # Each entry is a list of breakpoint IDs at that position. -var breakpoint_locations = {} -var BreakpointSigns: list<string> = [] - +var breakpoint_locations: dict<any> +var BreakpointSigns: list<string> -var evalFromBalloonExpr = 0 -var evalFromBalloonExprResult = '' -var ignoreEvalError = 0 -var evalexpr = '' +var evalFromBalloonExpr: bool +var evalFromBalloonExprResult: string +var ignoreEvalError: bool +var evalexpr: string # Remember the old value of 'signcolumn' for each buffer that it's set in, so # that we can restore the value for all buffers. -var signcolumn_buflist = [bufnr()] -var save_columns = 0 +var signcolumn_buflist: list<number> +var save_columns: number -var allleft = 0 +var allleft: bool # This was s:vertical but I cannot use vertical as variable name -var vvertical = 0 - -var winbar_winids = [] -var plus_map_saved = {} -var minus_map_saved = {} -var k_map_saved = {} -var saved_mousemodel = null_string - - -# Need either the +terminal feature or +channel and the prompt buffer. -# The terminal feature does not work with gdb on win32. -if has('terminal') && !has('win32') - way = 'terminal' -elseif has('channel') && exists('*prompt_setprompt') - way = 'prompt' -else - if has('terminal') - err = 'Cannot debug, missing prompt buffer support' +var vvertical: bool + +var winbar_winids: list<number> + +var saved_mousemodel: string + +var k_map_saved: dict<any> +var plus_map_saved: dict<any> +var minus_map_saved: dict<any> + + +def InitScriptVariables() + if exists('g:termdebug_config') && has_key(g:termdebug_config, 'use_prompt') + way = g:termdebug_config['use_prompt'] ? 'prompt' : 'terminal' + elseif exists('g:termdebug_use_prompt') + way = g:termdebug_use_prompt + elseif has('terminal') && !has('win32') + way = 'terminal' else - err = 'Cannot debug, +channel feature is not supported' + way = 'prompt' endif - command -nargs=* -complete=file -bang Termdebug echoerr err - command -nargs=+ -complete=file -bang TermdebugCommand echoerr err - finish -endif + err = '' + + pc_id = 12 + asm_id = 13 + break_id = 14 # breakpoint number is added to this + stopped = true + running = false + + parsing_disasm_msg = 0 + asm_lines = [] + asm_addr = '' + + # They indicate the buffer numbers of the main buffers used + gdbbufnr = 0 + gdbbufname = 'gdb' + varbufnr = 0 + varbufname = 'Termdebug-variables-listing' + asmbufnr = 0 + asmbufname = 'Termdebug-asm-listing' + promptbuf = 0 + # This is for the "debugged program" thing + ptybufnr = 0 + commbufnr = 0 + + gdbjob = null_job + gdb_channel = null_channel + # These changes because they relate to windows + pid = 0 + gdbwin = 0 + varwin = 0 + asmwin = 0 + ptywin = 0 + sourcewin = 0 + + # Contains breakpoints that have been placed, key is a string with the GDB + # breakpoint number. + # Each entry is a dict, containing the sub-breakpoints. Key is the subid. + # For a breakpoint that is just a number the subid is zero. + # For a breakpoint "123.4" the id is "123" and subid is "4". + # Example, when breakpoint "44", "123", "123.1" and "123.2" exist: + # {'44': {'0': entry}, '123': {'0': entry, '1': entry, '2': entry}} + breakpoints = {} + + # Contains breakpoints by file/lnum. The key is "fname:lnum". + # Each entry is a list of breakpoint IDs at that position. + breakpoint_locations = {} + BreakpointSigns = [] + + evalFromBalloonExpr = false + evalFromBalloonExprResult = '' + ignoreEvalError = false + evalexpr = '' + # Remember the old value of 'signcolumn' for each buffer that it's set in, so + # that we can restore the value for all buffers. + signcolumn_buflist = [bufnr()] + save_columns = 0 + winbar_winids = [] + k_map_saved = {} + plus_map_saved = {} + minus_map_saved = {} + + if has('menu') + saved_mousemodel = null_string + endif +enddef # The command that starts debugging, e.g. ":Termdebug vim". # To end type "quit" in the gdb window. command -nargs=* -complete=file -bang Termdebug StartDebug(<bang>0, <f-args>) @@ -182,11 +254,8 @@ def GetCommand(): list<string> return type(cmd) == v:t_list ? copy(cmd) : [cmd] enddef -def Echoerr(msg: string) - echohl ErrorMsg | echom $'[termdebug] {msg}' | echohl None -enddef - def StartDebug(bang: bool, ...gdb_args: list<string>) + InitScriptVariables() # First argument is the command to debug, second core file or process ID. StartDebug_internal({gdb_args: gdb_args, bang: bang}) enddef @@ -227,24 +296,11 @@ def StartDebug_internal(dict: dict<any>) &columns = wide # If we make the Vim window wider, use the whole left half for the debug # windows. - allleft = 1 + allleft = true endif - vvertical = 1 - else - vvertical = 0 - endif - - # Override using a terminal window by setting g:termdebug_use_prompt to 1. - var use_prompt = 0 - if exists('g:termdebug_config') - use_prompt = get(g:termdebug_config, 'use_prompt', 0) - elseif exists('g:termdebug_use_prompt') - use_prompt = g:termdebug_use_prompt - endif - if has('terminal') && !has('win32') && !use_prompt - way = 'terminal' + vvertical = true else - way = 'prompt' + vvertical = false endif if way == 'prompt' @@ -272,45 +328,42 @@ enddef # Use when debugger didn't start or ended. def CloseBuffers() - exe $'bwipe! {ptybuf}' - exe $'bwipe! {commbuf}' - if asmbuf > 0 && bufexists(asmbuf) - exe $'bwipe! {asmbuf}' + exe $'bwipe! {ptybufnr}' + exe $'bwipe! {commbufnr}' + if asmbufnr > 0 && bufexists(asmbufnr) + exe $'bwipe! {asmbufnr}' endif - if varbuf > 0 && bufexists(varbuf) - exe $'bwipe! {varbuf}' + if varbufnr > 0 && bufexists(varbufnr) + exe $'bwipe! {varbufnr}' endif running = 0 gdbwin = 0 enddef # IsGdbRunning(): bool may be a better name? -def CheckGdbRunning(): string - var gdbproc = term_getjob(gdbbuf) - var gdbproc_status = 'unknown' - if type(gdbproc) == v:t_job - gdbproc_status = job_status(gdbproc) - endif - if gdbproc == v:null || gdbproc_status !=# 'run' +def IsGdbStarted(): bool + var gdbproc_status = job_status(term_getjob(gdbbufnr)) + if gdbproc_status !=# 'run' var cmd_name = string(GetCommand()[0]) Echoerr($'{cmd_name} exited unexpectedly') CloseBuffers() - return '' + return false endif - return 'ok' + return true enddef # Open a terminal window without a job, to run the debugged program in. def StartDebug_term(dict: dict<any>) - ptybuf = term_start('NONE', { + ptybufnr = term_start('NONE', { term_name: 'debugged program', vertical: vvertical}) - if ptybuf == 0 + if ptybufnr == 0 Echoerr('Failed to open the program terminal window') return endif - var pty = job_info(term_getjob(ptybuf))['tty_out'] + var pty = job_info(term_getjob(ptybufnr))['tty_out'] ptywin = win_getid() + if vvertical # Assuming the source code window will get a signcolumn, use two more # columns for that, thus one less for the terminal window. @@ -322,23 +375,26 @@ def StartDebug_term(dict: dict<any>) endif # Create a hidden terminal window to communicate with gdb - commbuf = term_start('NONE', { + commbufnr = term_start('NONE', { term_name: 'gdb communication', out_cb: function('CommOutput'), hidden: 1 }) - if commbuf == 0 + if commbufnr == 0 Echoerr('Failed to open the communication terminal window') - exe $'bwipe! {ptybuf}' + exe $'bwipe! {ptybufnr}' return endif - var commpty = job_info(term_getjob(commbuf))['tty_out'] + var commpty = job_info(term_getjob(commbufnr))['tty_out'] + # Start the gdb buffer var gdb_args = get(dict, 'gdb_args', []) var proc_args = get(dict, 'proc_args', []) var gdb_cmd = GetCommand() + gdbbufname = gdb_cmd[0] + if exists('g:termdebug_config') && has_key(g:termdebug_config, 'command_add_args') gdb_cmd = g:termdebug_config.command_add_args(gdb_cmd, pty) else @@ -365,11 +421,11 @@ def StartDebug_term(dict: dict<any>) gdb_cmd += gdb_args ch_log($'executing "{join(gdb_cmd)}"') - gdbbuf = term_start(gdb_cmd, { - term_name: 'gdb', - term_finish: 'close', - }) - if gdbbuf == 0 + gdbbufnr = term_start(gdb_cmd, { + term_name: gdbbufname, + term_finish: 'close', + }) + if gdbbufnr == 0 Echoerr('Failed to open the gdb terminal window') CloseBuffers() return @@ -380,14 +436,14 @@ def StartDebug_term(dict: dict<any>) var counter = 0 var counter_max = 300 var success = false - while success == false && counter < counter_max - if CheckGdbRunning() != 'ok' - # Failure. If NOK just return. + while !success && counter < counter_max + if !IsGdbStarted() + CloseBuffers() return endif for lnum in range(1, 200) - if term_getline(gdbbuf, lnum) =~ 'startupdone' + if term_getline(gdbbufnr, lnum) =~ 'startupdone' success = true endif endfor @@ -397,7 +453,7 @@ def StartDebug_term(dict: dict<any>) sleep 10m endwhile - if success == false + if !success Echoerr('Failed to startup the gdb program.') CloseBuffers() return @@ -406,30 +462,30 @@ def StartDebug_term(dict: dict<any>) # ---- gdb started. Next, let's set the MI interface. --- # Set arguments to be run. if len(proc_args) - term_sendkeys(gdbbuf, $"server set args {join(proc_args)}\r") + term_sendkeys(gdbbufnr, $"server set args {join(proc_args)}\r") endif # Connect gdb to the communication pty, using the GDB/MI interface. # Prefix "server" to avoid adding this to the history. - term_sendkeys(gdbbuf, $"server new-ui mi {commpty}\r") + term_sendkeys(gdbbufnr, $"server new-ui mi {commpty}\r") # Wait for the response to show up, users may not notice the error and wonder # why the debugger doesn't work. counter = 0 counter_max = 300 success = false - while success == false && counter < counter_max - if CheckGdbRunning() != 'ok' + while !success && counter < counter_max + if !IsGdbStarted() return endif var response = '' for lnum in range(1, 200) - var line1 = term_getline(gdbbuf, lnum) - var line2 = term_getline(gdbbuf, lnum + 1) + var line1 = term_getline(gdbbufnr, lnum) + var line2 = term_getline(gdbbufnr, lnum + 1) if line1 =~ 'new-ui mi ' # response can be in the same line or the next line - response = line1 .. line2 + response = $"{line1}{line2}" if response =~ 'Undefined command' Echoerr('Sorry, your gdb is too old, gdb 7.12 is required') # CHECKME: possibly send a "server show version" here @@ -452,12 +508,12 @@ def StartDebug_term(dict: dict<any>) sleep 10m endwhile - if success == false + if !success Echoerr('Cannot check if your gdb works, continuing anyway') return endif - job_setoptions(term_getjob(gdbbuf), {exit_cb: function('EndTermDebug')}) + job_setoptions(term_getjob(gdbbufnr), {exit_cb: function('EndTermDebug')}) # Set the filetype, this can be used to add mappings. set filetype=termdebug @@ -531,23 +587,24 @@ def StartDebug_prompt(dict: dict<any>) set modified gdb_channel = job_getchannel(gdbjob) - ptybuf = 0 + ptybufnr = 0 if has('win32') # MS-Windows: run in a new console window for maximum compatibility SendCommand('set new-console on') elseif has('terminal') # Unix: Run the debugged program in a terminal window. Open it below the # gdb window. - belowright ptybuf = term_start('NONE', { + belowright ptybufnr = term_start('NONE', { term_name: 'debugged program', + vertical: vvertical }) - if ptybuf == 0 + if ptybufnr == 0 Echoerr('Failed to open the program terminal window') job_stop(gdbjob) return endif ptywin = win_getid() - var pty = job_info(term_getjob(ptybuf))['tty_out'] + var pty = job_info(term_getjob(ptybufnr))['tty_out'] SendCommand($'tty {pty}') # Since GDB runs in a prompt window, the environment has not been set to @@ -615,7 +672,7 @@ def SendCommand(cmd: string) if way == 'prompt' ch_sendraw(gdb_channel, $"{cmd}\n") else - term_sendkeys(commbuf, $"{cmd}\r") + term_sendkeys(commbufnr, $"{cmd}\r") endif enddef @@ -652,7 +709,7 @@ def TermDebugSendCommand(cmd: string) sleep 10m endif # TODO: should we prepend CTRL-U to clear the command? - term_sendkeys(gdbbuf, $"{cmd}\r") + term_sendkeys(gdbbufnr, $"{cmd}\r") if do_continue ContinueCommand() endif @@ -665,7 +722,7 @@ enddef def SendResumingCommand(cmd: string) if stopped # reset stopped here, it may take a bit of time before we get a response - stopped = 0 + stopped = false ch_log('assume that program is running after this command') SendCommand(cmd) else @@ -715,9 +772,9 @@ def GdbOutCallback(channel: channel, text: string) var decoded_text = '' if text =~ '^\^error,msg=' decoded_text = DecodeMessage(text[11 : ], false) - if exists('evalexpr') && decoded_text =~ 'A syntax error in expression, near\|No symbol .* in current context' + if !empty(evalexpr) && decoded_text =~ 'A syntax error in expression, near\|No symbol .* in current context' # Silently drop evaluation errors. - evalexpr = null_string + evalexpr = '' return endif elseif text[0] == '~' @@ -739,9 +796,9 @@ enddef # Decode a message from gdb. "quotedText" starts with a ", return the text up # to the next unescaped ", unescaping characters: -# - remove line breaks (unless "literal" is v:true) +# - remove line breaks (unless "literal" is true) # - change \" to " -# - change \\t to \t (unless "literal" is v:true) +# - change \\t to \t (unless "literal" is true) # - change \0xhh to \xhh (disabled for now) # - change \ooo to octal # - change \\ to \ @@ -751,19 +808,20 @@ def DecodeMessage(quotedText: string, literal: bool): string return '' endif var msg = quotedText - \ ->substitute('^"\|[^\\]\zs".*', '', 'g') - \ ->substitute('\\"', '"', 'g') + ->substitute('^"\|[^\\]\zs".*', '', 'g') + ->substitute('\\"', '"', 'g') #\ multi-byte characters arrive in octal form #\ NULL-values must be kept encoded as those break the string otherwise - \ ->substitute('\\000', NullRepl, 'g') - \ ->substitute('\\\(\o\o\o\)', (m) => nr2char(str2nr(m[1], 8)), 'g') + ->substitute('\\000', NullRepl, 'g') + ->substitute('\\\(\o\o\o\)', (m) => nr2char(str2nr(m[1], 8)), 'g') + # You could also use ->substitute('\\\\\(\o\o\o\)', '\=nr2char(str2nr(submatch(1), 8))', "g") #\ Note: GDB docs also mention hex encodings - the translations below work #\ but we keep them out for performance-reasons until we actually see #\ those in mi-returns #\ \ ->substitute('\\0x\(\x\x\)', {-> eval('"\x' .. submatch(1) .. '"')}, 'g') #\ \ ->substitute('\\0x00', NullRepl, 'g') - \ ->substitute('\\\\', '\', 'g') - \ ->substitute(NullRepl, '\\000', 'g') + ->substitute('\\\\', '\', 'g') + ->substitute(NullRepl, '\\000', 'g') if !literal return msg ->substitute('\\t', "\t", 'g') @@ -805,8 +863,8 @@ def EndTermDebug(job: any, status: any) doauto <nomodeline> User TermdebugStopPre endif - if bufexists(commbuf) - exe $'bwipe! {commbuf}' + if commbufnr > 0 && bufexists(commbufnr) + exe $'bwipe! {commbufnr}' endif gdbwin = 0 EndDebugCommon() @@ -815,16 +873,16 @@ enddef def EndDebugCommon() var curwinid = win_getid() - if bufexists(ptybuf) - exe $'bwipe! {ptybuf}' + if ptybufnr > 0 && bufexists(ptybufnr) + exe $'bwipe! {ptybufnr}' endif - if bufexists(asmbuf) - exe $'bwipe! {asmbuf}' + if asmbufnr > 0 && bufexists(asmbufnr) + exe $'bwipe! {asmbufnr}' endif - if bufexists(varbuf) - exe $'bwipe! {varbuf}' + if varbufnr > 0 && bufexists(varbufnr) + exe $'bwipe! {varbufnr}' endif - running = 0 + running = false # Restore 'signcolumn' in all buffers for which it was set. win_gotoid(sourcewin) @@ -932,11 +990,11 @@ def HandleDisasmMsg(msg: string) endif elseif msg !~ '^&"disassemble' var value = substitute(msg, '^\~\"[ ]*', '', '') - value = substitute(value, '^=>[ ]*', '', '') - value = substitute(value, '\\n\"\r$', '', '') - value = substitute(value, '\\n\"$', '', '') - value = substitute(value, '\r', '', '') - value = substitute(value, '\\t', ' ', 'g') + ->substitute('^=>[ ]*', '', '') + ->substitute('\\n\"\r$', '', '') + ->substitute('\\n\"$', '', '') + ->substitute('\r', '', '') + ->substitute('\\t', ' ', 'g') if value != '' || !empty(asm_lines) add(asm_lines, value) @@ -1248,7 +1306,7 @@ def Until(at: string) if stopped # reset stopped here, it may take a bit of time before we get a response - stopped = 0 + stopped = false ch_log('assume that program is running after this command') # Use the fname:lnum format @@ -1379,8 +1437,8 @@ enddef # :Evaluate - evaluate what is specified / under the cursor def Evaluate(range: number, arg: string) var expr = GetEvaluationExpression(range, arg) - #echom $"expr: {expr}" - ignoreEvalError = 0 + echom $"expr: {expr}" + ignoreEvalError = false SendEval(expr) enddef @@ -1435,21 +1493,20 @@ enddef def HandleEvaluate(msg: string) var value = msg - \ ->substitute('.*value="\(.*\)"', '\1', '') - \ ->substitute('\\"', '"', 'g') - \ ->substitute('\\\\', '\\', 'g') + ->substitute('.*value="\(.*\)"', '\1', '') + ->substitute('\\"', '"', 'g') + ->substitute('\\\\', '\\', 'g') #\ multi-byte characters arrive in octal form, replace everything but NULL values - \ ->substitute('\\000', NullRepl, 'g') - # \ ->substitute('\\\o\o\o', {-> eval('"' .. submatch(0) .. '"')}, 'g') - \ ->substitute('\\\(\o\o\o\)', (m) => nr2char(str2nr(m[1], 8)), 'g') + ->substitute('\\000', NullRepl, 'g') + ->substitute('\\\(\o\o\o\)', (m) => nr2char(str2nr(m[1], 8)), 'g') #\ Note: GDB docs also mention hex encodings - the translations below work #\ but we keep them out for performance-reasons until we actually see #\ those in mi-returns #\ ->substitute('\\0x00', NullRep, 'g') #\ ->substitute('\\0x\(\x\x\)', {-> eval('"\x' .. submatch(1) .. '"')}, 'g') - \ ->substitute(NullRepl, '\\000', 'g') + ->substitute(NullRepl, '\\000', 'g') if evalFromBalloonExpr - if evalFromBalloonExprResult == '' + if empty(evalFromBalloonExprResult) evalFromBalloonExprResult = $'{evalexpr}: {value}' else evalFromBalloonExprResult ..= $' = {value}' @@ -1461,10 +1518,10 @@ def HandleEvaluate(msg: string) if evalexpr[0] != '*' && value =~ '^0x' && value != '0x0' && value !~ '"$' # Looks like a pointer, also display what it points to. - ignoreEvalError = 1 + ignoreEvalError = true SendEval($'*{evalexpr}') else - evalFromBalloonExpr = 0 + evalFromBalloonExpr = false endif enddef @@ -1480,9 +1537,9 @@ def TermDebugBalloonExpr(): string # mouse triggers a balloon. return '' endif - evalFromBalloonExpr = 1 + evalFromBalloonExpr = true evalFromBalloonExprResult = '' - ignoreEvalError = 1 + ignoreEvalError = true var expr = CleanupExpr(v:beval_text) SendEval(expr) return '' @@ -1492,8 +1549,8 @@ enddef def HandleError(msg: string) if ignoreEvalError # Result of SendEval() failed, ignore. - ignoreEvalError = 0 - evalFromBalloonExpr = 0 + ignoreEvalError = false + evalFromBalloonExpr = true return endif var msgVal = substitute(msg, '.*msg="\(.*\)"', '\1', '') @@ -1554,11 +1611,11 @@ def GotoAsmwinOrCreateIt() setlocal signcolumn=no setlocal modifiable - if asmbuf > 0 && bufexists(asmbuf) - exe $'buffer {asmbuf}' + if asmbufnr > 0 && bufexists(asmbufnr) + exe $'buffer {asmbufnr}' elseif empty(glob('Termdebug-asm-listing')) silent file Termdebug-asm-listing - asmbuf = bufnr('Termdebug-asm-listing') + asmbufnr = bufnr('Termdebug-asm-listing') else Echoerr("You have a file/folder named 'Termdebug-asm-listing'. " .. "Please exit and rename it because Termdebug may not work " .. @@ -1628,11 +1685,11 @@ def GotoVariableswinOrCreateIt() setlocal signcolumn=no setlocal modifiable - if varbuf > 0 && bufexists(varbuf) - exe $'buffer {varbuf}' + if varbufnr > 0 && bufexists(varbufnr) + exe $'buffer {varbufnr}' elseif empty(glob('Termdebug-variables-listing')) silent file Termdebug-variables-listing - varbuf = bufnr('Termdebug-variables-listing') + varbufnr = bufnr('Termdebug-variables-listing') else Echoerr("You have a file/folder named 'Termdebug-variables-listing'. " .. "Please exit and rename it because Termdebug may not work " .. @@ -1658,12 +1715,12 @@ def HandleCursor(msg: string) ch_log('program stopped') stopped = 1 if msg =~ '^\*stopped,reason="exited-normally"' - running = 0 + running = false endif elseif msg =~ '^\*running' ch_log('program running') - stopped = 0 - running = 1 + stopped = false + running = true endif var fname = '' @@ -1692,7 +1749,7 @@ def HandleCursor(msg: string) endif endif - if running && stopped && bufwinnr('Termdebug-variables-listing') != -1 + if running && stopped && bufwinnr(varbufname) != -1 SendCommand('-stack-list-variables 2') endif @@ -1709,13 +1766,13 @@ def HandleCursor(msg: string) au SwapExists * echohl WarningMsg | echo 'Warning: file is being edited elsewhere' | echohl None - | let v:swapchoice = 'o' + | v:swapchoice = 'o' augroup END if &modified # TODO: find existing window exe $'split {fnameescape(fname)}' sourcewin = win_getid() - call InstallWinbar(0) + InstallWinbar(0) else exe $'edit {fnameescape(fname)}' endif diff --git a/src/testdir/test_termdebug.vim b/src/testdir/test_termdebug.vim index 62cafccb69..a9762df8a2 100644 --- a/src/testdir/test_termdebug.vim +++ b/src/testdir/test_termdebug.vim @@ -338,5 +338,16 @@ func Test_termdebug_bufnames() unlet g:termdebug_config endfunc +function Test_termdebug_save_restore_variables() + let &mousemodel='' + Termdebug + call WaitForAssert({-> assert_equal(3, winnr('$'))}) + call WaitForAssert({-> assert_match(&mousemodel, 'popup_setpos')}) + wincmd t + quit! + call WaitForAssert({-> assert_equal(1, winnr('$'))}) + call WaitForAssert({-> assert_true(empty(&mousemodel))}) +endfunction + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 1360d1cfc3..43a09d308b 100644 --- a/src/version.c +++ b/src/version.c @@ -705,6 +705,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 482, +/**/ 481, /**/ 480, |