summaryrefslogtreecommitdiffstats
path: root/runtime/pack
diff options
context:
space:
mode:
authorUbaldo Tiberi <ubaldo.tiberi@volvo.com>2024-06-05 21:27:38 +0200
committerChristian Brabandt <cb@256bit.org>2024-06-05 21:37:53 +0200
commit23f29ffc64276dd790581f98b86a0a6435b7eb22 (patch)
treeb77405ee6ecc98b14ea0e111e7fc505250cbfc2b /runtime/pack
parent7cbed350f840b7ff96a5be6102f26ad57929b8b6 (diff)
runtime(termdebug): convert termdebug plugin to Vim9 script
closes: #14903 Signed-off-by: Ubaldo Tiberi <ubaldo.tiberi@volvo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
Diffstat (limited to 'runtime/pack')
-rw-r--r--runtime/pack/dist/opt/termdebug/plugin/termdebug.vim2432
1 files changed, 1254 insertions, 1178 deletions
diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
index 8eb3fff694..9d987e350a 100644
--- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
+++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
@@ -1,419 +1,480 @@
-" Debugger plugin using gdb.
-"
-" Author: Bram Moolenaar
-" Copyright: Vim license applies, see ":help license"
-" Last Change: 2023 Nov 02
-"
-" WORK IN PROGRESS - The basics works stable, more to come
-" Note: In general you need at least GDB 7.12 because this provides the
-" frame= response in MI thread-selected events we need to sync stack to file.
-" The one included with "old" MingW is too old (7.6.1), you may upgrade it or
-" use a newer version from http://www.equation.com/servlet/equation.cmd?fa=gdb
-"
-" There are two ways to run gdb:
-" - In a terminal window; used if possible, does not work on MS-Windows
-" Not used when g:termdebug_use_prompt is set to 1.
-" - Using a "prompt" buffer; may use a terminal window for the program
-"
-" For both the current window is used to view source code and shows the
-" current statement from gdb.
-"
-" USING A TERMINAL WINDOW
-"
-" Opens two visible terminal windows:
-" 1. runs a pty for the debugged program, as with ":term NONE"
-" 2. runs gdb, passing the pty of the debugged program
-" A third terminal window is hidden, it is used for communication with gdb.
-"
-" USING A PROMPT BUFFER
-"
-" Opens a window with a prompt buffer to communicate with gdb.
-" Gdb is run as a job with callbacks for I/O.
-" On Unix another terminal window is opened to run the debugged program
-" On MS-Windows a separate console is opened to run the debugged program
-"
-" The communication with gdb uses GDB/MI. See:
-" https://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI.html
-
-" In case this gets sourced twice.
-if exists(':Termdebug')
+vim9script
+
+# Debugger plugin using gdb.
+
+# Author: Bram Moolenaar
+# Copyright: Vim license applies, see ":help license"
+# Last Change: 2024 Jun 03
+# Converted to Vim9: Ubaldo Tiberi <ubaldo.tiberi@volvo.com>
+
+# WORK IN PROGRESS - The basics works stable, more to come
+# Note: In general you need at least GDB 7.12 because this provides the
+# frame= response in MI thread-selected events we need to sync stack to file.
+# The one included with "old" MingW is too old (7.6.1), you may upgrade it or
+# use a newer version from http://www.equation.com/servlet/equation.cmd?fa=gdb
+
+# There are two ways to run gdb:
+# - In a terminal window; used if possible, does not work on MS-Windows
+# Not used when g:termdebug_use_prompt is set to 1.
+# - Using a "prompt" buffer; may use a terminal window for the program
+
+# For both the current window is used to view source code and shows the
+# current statement from gdb.
+
+# USING A TERMINAL WINDOW
+
+# Opens two visible terminal windows:
+# 1. runs a pty for the debugged program, as with ":term NONE"
+# 2. runs gdb, passing the pty of the debugged program
+# A third terminal window is hidden, it is used for communication with gdb.
+
+# USING A PROMPT BUFFER
+
+# Opens a window with a prompt buffer to communicate with gdb.
+# Gdb is run as a job with callbacks for I/O.
+# On Unix another terminal window is opened to run the debugged program
+# On MS-Windows a separate console is opened to run the debugged program
+
+# The communication with gdb uses GDB/MI. See:
+# https://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI.html
+
+# In case this gets sourced twice.
+if exists('g:termdebug_loaded')
finish
endif
-
-" Need either the +terminal feature or +channel and the prompt buffer.
-" The terminal feature does not work with gdb on win32.
+g:termdebug_loaded = true
+
+var way = 'terminal'
+var err = 'no errors'
+
+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 parsing_disasm_msg = 0
+var asm_lines = []
+var asm_addr = ''
+
+# 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
+# This is for the "debugged program" thing
+var ptybuf = 0
+var commbuf = 0
+
+var gdbjob = null_job
+var gdb_channel = null_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
+
+# 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}}
+var breakpoints = {}
+
+# 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 evalFromBalloonExpr = 0
+var evalFromBalloonExprResult = ''
+var ignoreEvalError = 0
+var 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.
+var signcolumn_buflist = [bufnr()]
+var save_columns = 0
+
+var allleft = 0
+# 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 = ''
+
+
+# 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')
- let s:way = 'terminal'
+ way = 'terminal'
elseif has('channel') && exists('*prompt_setprompt')
- let s:way = 'prompt'
+ way = 'prompt'
else
if has('terminal')
- let s:err = 'Cannot debug, missing prompt buffer support'
+ err = 'Cannot debug, missing prompt buffer support'
else
- let s:err = 'Cannot debug, +channel feature is not supported'
+ err = 'Cannot debug, +channel feature is not supported'
endif
- command -nargs=* -complete=file -bang Termdebug echoerr s:err
- command -nargs=+ -complete=file -bang TermdebugCommand echoerr s:err
+ command -nargs=* -complete=file -bang Termdebug echoerr err
+ command -nargs=+ -complete=file -bang TermdebugCommand echoerr err
finish
endif
-let s:keepcpo = &cpo
-set cpo&vim
-
-" The command that starts debugging, e.g. ":Termdebug vim".
-" To end type "quit" in the gdb window.
-command -nargs=* -complete=file -bang Termdebug call s:StartDebug(<bang>0, <f-args>)
-command -nargs=+ -complete=file -bang TermdebugCommand call s:StartDebugCommand(<bang>0, <f-args>)
-
-let s:pc_id = 12
-let s:asm_id = 13
-let s:break_id = 14 " breakpoint number is added to this
-let s:stopped = 1
-let s:running = 0
-
-let s:parsing_disasm_msg = 0
-let s:asm_lines = []
-let s:asm_addr = ''
-
-" Take a breakpoint number as used by GDB and turn it into an integer.
-" The breakpoint may contain a dot: 123.4 -> 123004
-" The main breakpoint has a zero subid.
-func s:Breakpoint2SignNumber(id, subid)
- return s:break_id + a:id * 1000 + a:subid
-endfunction
-
-" Define or adjust the default highlighting, using background "new".
-" When the 'background' option is set then "old" has the old value.
-func s:Highlight(init, old, new)
- let default = a:init ? 'default ' : ''
- if a:new ==# 'light' && a:old !=# 'light'
- exe "hi " . default . "debugPC term=reverse ctermbg=lightblue guibg=lightblue"
- elseif a:new ==# 'dark' && a:old !=# 'dark'
- exe "hi " . default . "debugPC term=reverse ctermbg=darkblue guibg=darkblue"
- endif
-endfunc
-
-" Define the default highlighting, using the current 'background' value.
-func s:InitHighlight()
- call s:Highlight(1, '', &background)
+
+# 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>)
+command -nargs=+ -complete=file -bang TermdebugCommand StartDebugCommand(<bang>0, <f-args>)
+
+
+# Take a breakpoint number as used by GDB and turn it into an integer.
+# The breakpoint may contain a dot: 123.4 -> 123004
+# The main breakpoint has a zero subid.
+def Breakpoint2SignNumber(id: number, subid: number): number
+ return break_id + id * 1000 + subid
+enddef
+
+# Define or adjust the default highlighting, using background "new".
+# When the 'background' option is set then "old" has the old value.
+def Highlight(init: bool, old: string, new: string)
+ var default = init ? 'default ' : ''
+ if new ==# 'light' && old !=# 'light'
+ exe "hi " .. default .. "debugPC term=reverse ctermbg=lightblue guibg=lightblue"
+ elseif new ==# 'dark' && old !=# 'dark'
+ exe "hi " .. default .. "debugPC term=reverse ctermbg=darkblue guibg=darkblue"
+ endif
+enddef
+
+# Define the default highlighting, using the current 'background' value.
+def InitHighlight()
+ Highlight(1, '', &background)
hi default debugBreakpoint term=reverse ctermbg=red guibg=red
hi default debugBreakpointDisabled term=reverse ctermbg=gray guibg=gray
-endfunc
+enddef
-" Setup an autocommand to redefine the default highlight when the colorscheme
-" is changed.
-func s:InitAutocmd()
+# Setup an autocommand to redefine the default highlight when the colorscheme
+# is changed.
+def InitAutocmd()
augroup TermDebug
autocmd!
- autocmd ColorScheme * call s:InitHighlight()
+ autocmd ColorScheme * InitHighlight()
augroup END
-endfunc
+enddef
-" Get the command to execute the debugger as a list, defaults to ["gdb"].
-func s:GetCommand()
+# Get the command to execute the debugger as a list, defaults to ["gdb"].
+def GetCommand(): list<string>
+ var cmd = 'gdb'
if exists('g:termdebug_config')
- let cmd = get(g:termdebug_config, 'command', 'gdb')
+ cmd = get(g:termdebug_config, 'command', 'gdb')
elseif exists('g:termdebugger')
- let cmd = g:termdebugger
- else
- let cmd = 'gdb'
+ cmd = g:termdebugger
endif
return type(cmd) == v:t_list ? copy(cmd) : [cmd]
-endfunc
+enddef
+
+def Echoerr(msg: string)
+ echohl ErrorMsg | echom '[termdebug] ' .. msg | echohl None
+enddef
-func s:Echoerr(msg)
- echohl ErrorMsg | echom '[termdebug] ' .. a:msg | echohl None
-endfunc
+def StartDebug(bang: bool, ...gdb_args: list<string>)
+ # First argument is the command to debug, second core file or process ID.
+ StartDebug_internal({'gdb_args': gdb_args, 'bang': bang})
+enddef
-func s:StartDebug(bang, ...)
- " First argument is the command to debug, second core file or process ID.
- call s:StartDebug_internal({'gdb_args': a:000, 'bang': a:bang})
-endfunc
+def StartDebugCommand(bang: bool, ...args: list<string>)
+ # First argument is the command to debug, rest are run arguments.
+ StartDebug_internal({'gdb_args': [args[0]], 'proc_args': args[1:], 'bang': bang})
+enddef
-func s:StartDebugCommand(bang, ...)
- " First argument is the command to debug, rest are run arguments.
- call s:StartDebug_internal({'gdb_args': [a:1], 'proc_args': a:000[1:], 'bang': a:bang})
-endfunc
-func s:StartDebug_internal(dict)
- if exists('s:gdbwin')
- call s:Echoerr('Terminal debugger already running, cannot run two')
+def StartDebug_internal(dict: dict<any>)
+ if gdbwin > 0
+ Echoerr('Terminal debugger already running, cannot run two')
return
endif
- let gdbcmd = s:GetCommand()
+ var gdbcmd = GetCommand()
if !executable(gdbcmd[0])
- call s:Echoerr('Cannot execute debugger program "' .. gdbcmd[0] .. '"')
+ Echoerr('Cannot execute debugger program "' .. gdbcmd[0] .. '"')
return
endif
- let s:ptywin = 0
- let s:pid = 0
- let s:asmwin = 0
- let s:asmbuf = 0
- let s:varwin = 0
- let s:varbuf = 0
-
if exists('#User#TermdebugStartPre')
doauto <nomodeline> User TermdebugStartPre
endif
- " Uncomment this line to write logging in "debuglog".
- " call ch_logfile('debuglog', 'w')
-
- let s:sourcewin = win_getid()
+ # Assume current window is the source code window
+ sourcewin = win_getid()
+ var wide = 0
- " Remember the old value of 'signcolumn' for each buffer that it's set in, so
- " that we can restore the value for all buffers.
- let b:save_signcolumn = &signcolumn
- let s:signcolumn_buflist = [bufnr()]
-
- let s:save_columns = 0
- let s:allleft = 0
- let wide = 0
if exists('g:termdebug_config')
- let wide = get(g:termdebug_config, 'wide', 0)
+ wide = get(g:termdebug_config, 'wide', 0)
elseif exists('g:termdebug_wide')
- let wide = g:termdebug_wide
+ wide = g:termdebug_wide
endif
if wide > 0
if &columns < wide
- let s:save_columns = &columns
- let &columns = wide
- " If we make the Vim window wider, use the whole left half for the debug
- " windows.
- let s:allleft = 1
+ save_columns = &columns
+ &columns = wide
+ # If we make the Vim window wider, use the whole left half for the debug
+ # windows.
+ allleft = 1
endif
- let s:vertical = 1
+ vvertical = 1
else
- let s:vertical = 0
+ vvertical = 0
endif
- " Override using a terminal window by setting g:termdebug_use_prompt to 1.
- let use_prompt = 0
+ # Override using a terminal window by setting g:termdebug_use_prompt to 1.
+ var use_prompt = 0
if exists('g:termdebug_config')
- let use_prompt = get(g:termdebug_config, 'use_prompt', 0)
+ use_prompt = get(g:termdebug_config, 'use_prompt', 0)
elseif exists('g:termdebug_use_prompt')
- let use_prompt = g:termdebug_use_prompt
+ use_prompt = g:termdebug_use_prompt
endif
if has('terminal') && !has('win32') && !use_prompt
- let s:way = 'terminal'
+ way = 'terminal'
else
- let s:way = 'prompt'
+ way = 'prompt'
endif
- if s:way == 'prompt'
- call s:StartDebug_prompt(a:dict)
+ if way == 'prompt'
+ StartDebug_prompt(dict)
else
- call s:StartDebug_term(a:dict)
+ StartDebug_term(dict)
endif
- if s:GetDisasmWindow()
- let curwinid = win_getid()
- call s:GotoAsmwinOrCreateIt()
- call win_gotoid(curwinid)
+ if GetDisasmWindow()
+ var curwinid = win_getid()
+ GotoAsmwinOrCreateIt()
+ win_gotoid(curwinid)
endif
- if s:GetVariablesWindow()
- let curwinid = win_getid()
- call s:GotoVariableswinOrCreateIt()
- call win_gotoid(curwinid)
+ if GetVariablesWindow()
+ var curwinid = win_getid()
+ GotoVariableswinOrCreateIt()
+ win_gotoid(curwinid)
endif
if exists('#User#TermdebugStartPost')
doauto <nomodeline> User TermdebugStartPost
endif
-endfunc
+enddef
-" Use when debugger didn't start or ended.
-func s:CloseBuffers()
- exe 'bwipe! ' . s:ptybuf
- exe 'bwipe! ' . s:commbuf
- if s:asmbuf > 0 && bufexists(s:asmbuf)
- exe 'bwipe! ' . s:asmbuf
+# Use when debugger didn't start or ended.
+def CloseBuffers()
+ exe 'bwipe! ' .. ptybuf
+ exe 'bwipe! ' .. commbuf
+ if asmbuf > 0 && bufexists(asmbuf)
+ exe 'bwipe! ' .. asmbuf
endif
- if s:varbuf > 0 && bufexists(s:varbuf)
- exe 'bwipe! ' . s:varbuf
+ if varbuf > 0 && bufexists(varbuf)
+ exe 'bwipe! ' .. varbuf
endif
- let s:running = 0
- unlet! s:gdbwin
-endfunc
+ running = 0
+ gdbwin = 0
+enddef
-func s:CheckGdbRunning()
- let gdbproc = term_getjob(s:gdbbuf)
- if gdbproc == v:null || job_status(gdbproc) !=# 'run'
- call s:Echoerr(string(s:GetCommand()[0]) . ' exited unexpectedly')
- call s:CloseBuffers()
+# 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'
+ Echoerr(string(GetCommand()[0]) .. ' exited unexpectedly')
+ CloseBuffers()
return ''
endif
return 'ok'
-endfunc
-
-" Open a terminal window without a job, to run the debugged program in.
-func s:StartDebug_term(dict)
- let s:ptybuf = term_start('NONE', {
- \ 'term_name': 'debugged program',
- \ 'vertical': s:vertical,
- \ })
- if s:ptybuf == 0
- call s:Echoerr('Failed to open the program terminal window')
+enddef
+
+# Open a terminal window without a job, to run the debugged program in.
+def StartDebug_term(dict: dict<any>)
+ ptybuf = term_start('NONE', {
+ \ 'term_name': 'debugged program',
+ \ 'vertical': vvertical,
+ \ })
+ if ptybuf == 0
+ Echoerr('Failed to open the program terminal window')
return
endif
- let pty = job_info(term_getjob(s:ptybuf))['tty_out']
- let s:ptywin = win_getid()
- if s:vertical
- " Assuming the source code window will get a signcolumn, use two more
- " columns for that, thus one less for the terminal window.
- exe (&columns / 2 - 1) . "wincmd |"
- if s:allleft
- " use the whole left column
+ var pty = job_info(term_getjob(ptybuf))['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.
+ exe ":" .. (&columns / 2 - 1) .. "wincmd |"
+ if allleft
+ # use the whole left column
wincmd H
endif
endif
- " Create a hidden terminal window to communicate with gdb
- let s:commbuf = term_start('NONE', {
- \ 'term_name': 'gdb communication',
- \ 'out_cb': function('s:CommOutput'),
- \ 'hidden': 1,
- \ })
- if s:commbuf == 0
- call s:Echoerr('Failed to open the communication terminal window')
- exe 'bwipe! ' . s:ptybuf
+ # Create a hidden terminal window to communicate with gdb
+ commbuf = term_start('NONE', {
+ \ 'term_name': 'gdb communication',
+ \ 'out_cb': function('CommOutput'),
+ \ 'hidden': 1,
+ \ })
+ if commbuf == 0
+ Echoerr('Failed to open the communication terminal window')
+ exe 'bwipe! ' .. ptybuf
return
endif
- let commpty = job_info(term_getjob(s:commbuf))['tty_out']
+ var commpty = job_info(term_getjob(commbuf))['tty_out']
- let gdb_args = get(a:dict, 'gdb_args', [])
- let proc_args = get(a:dict, 'proc_args', [])
+ var gdb_args = get(dict, 'gdb_args', [])
+ var proc_args = get(dict, 'proc_args', [])
- let gdb_cmd = s:GetCommand()
+ var gdb_cmd = GetCommand()
if exists('g:termdebug_config') && has_key(g:termdebug_config, 'command_add_args')
- let gdb_cmd = g:termdebug_config.command_add_args(gdb_cmd, pty)
+ gdb_cmd = g:termdebug_config.command_add_args(gdb_cmd, pty)
else
- " Add -quiet to avoid the intro message causing a hit-enter prompt.
- let gdb_cmd += ['-quiet']
- " Disable pagination, it causes everything to stop at the gdb
- let gdb_cmd += ['-iex', 'set pagination off']
- " Interpret commands while the target is running. This should usually only
- " be exec-interrupt, since many commands don't work properly while the
- " target is running (so execute during startup).
- let gdb_cmd += ['-iex', 'set mi-async on']
- " Open a terminal window to run the debugger.
- let gdb_cmd += ['-tty', pty]
- " Command executed _after_ startup is done, provides us with the necessary
- " feedback
- let gdb_cmd += ['-ex', 'echo startupdone\n']
+ # Add -quiet to avoid the intro message causing a hit-enter prompt.
+ gdb_cmd += ['-quiet']
+ # Disable pagination, it causes everything to stop at the gdb
+ gdb_cmd += ['-iex', 'set pagination off']
+ # Interpret commands while the target is running. This should usually only
+ # be exec-interrupt, since many commands don't work properly while the
+ # target is running (so execute during startup).
+ gdb_cmd += ['-iex', 'set mi-async on']
+ # Open a terminal window to run the debugger.
+ gdb_cmd += ['-tty', pty]
+ # Command executed _after_ startup is done, provides us with the necessary
+ # feedback
+ gdb_cmd += ['-ex', 'echo startupdone\n']
endif
if exists('g:termdebug_config') && has_key(g:termdebug_config, 'command_filter')
- let gdb_cmd = g:termdebug_config.command_filter(gdb_cmd)
+ gdb_cmd = g:termdebug_config.command_filter(gdb_cmd)
endif
- " Adding arguments requested by the user
- let gdb_cmd += gdb_args
+ # Adding arguments requested by the user
+ gdb_cmd += gdb_args
- call ch_log('executing "' . join(gdb_cmd) . '"')
- let s:gdbbuf = term_start(gdb_cmd, {
- \ 'term_finish': 'close',
- \ })
- if s:gdbbuf == 0
- call s:Echoerr('Failed to open the gdb terminal window')
- call s:CloseBuffers()
+ ch_log('executing "' .. join(gdb_cmd) .. '"')
+ gdbbuf = term_start(gdb_cmd, {
+ \ 'term_name': 'gdb',
+ \ 'term_finish': 'close',
+ \ })
+ if gdbbuf == 0
+ Echoerr('Failed to open the gdb terminal window')
+ CloseBuffers()
return
endif
- let s:gdbwin = win_getid()
+ gdbwin = win_getid()
- " Wait for the "startupdone" message before sending any commands.
- let try_count = 0
- while 1
- if s:CheckGdbRunning() != 'ok'
+ # Wait for the "startupdone" message before sending any commands.
+ var counter = 0
+ var counter_max = 300
+ var success = false
+ while success == false && counter < counter_max
+ if CheckGdbRunning() != 'ok'
+ # Failure. If NOK just return.
return
endif
for lnum in range(1, 200)
- if term_getline(s:gdbbuf, lnum) =~ 'startupdone'
- let try_count = 9999
- break
+ if term_getline(gdbbuf, lnum) =~ 'startupdone'
+ success = true
endif
endfor
- let try_count += 1
- if try_count > 300
- " done or give up after five seconds
- break
- endif
+
+ # Each count is 10ms
+ counter += 1
sleep 10m
endwhile
- " Set arguments to be run.
+ if success == false
+ Echoerr('Failed to startup the gdb program.')
+ CloseBuffers()
+ return
+ endif
+
+ # ---- gdb started. Next, let's set the MI interface. ---
+ # Set arguments to be run.
if len(proc_args)
- call term_sendkeys(s:gdbbuf, 'server set args ' . join(proc_args) . "\r")
+ term_sendkeys(gdbbuf, '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.
- call term_sendkeys(s:gdbbuf, 'server new-ui mi ' . commpty . "\r")
+ # 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")
- " Wait for the response to show up, users may not notice the error and wonder
- " why the debugger doesn't work.
- let try_count = 0
- while 1
- if s:CheckGdbRunning() != 'ok'
+ # 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'
return
endif
- let response = ''
+ var response = ''
for lnum in range(1, 200)
- let line1 = term_getline(s:gdbbuf, lnum)
- let line2 = term_getline(s:gdbbuf, lnum + 1)
+ var line1 = term_getline(gdbbuf, lnum)
+ var line2 = term_getline(gdbbuf, lnum + 1)
if line1 =~ 'new-ui mi '
- " response can be in the same line or the next line
- let response = line1 . line2
+ # response can be in the same line or the next line
+ response = line1 .. line2
if response =~ 'Undefined command'
- call s:Echoerr('Sorry, your gdb is too old, gdb 7.12 is required')
- " CHECKME: possibly send a "server show version" here
- call s:CloseBuffers()
+ Echoerr('Sorry, your gdb is too old, gdb 7.12 is required')
+ # CHECKME: possibly send a "server show version" here
+ CloseBuffers()
return
endif
if response =~ 'New UI allocated'
- " Success!
- break
+ # Success!
+ success = true
endif
elseif line1 =~ 'Reading symbols from' && line2 !~ 'new-ui mi '
- " Reading symbols might take a while, try more times
- let try_count -= 1
+ # Reading symbols might take a while, try more times
+ counter -= 1
endif
endfor
if response =~ 'New UI allocated'
break
endif
- let try_count += 1
- if try_count > 100
- call s:Echoerr('Cannot check if your gdb works, continuing anyway')
- break
- endif
+ counter += 1
sleep 10m
endwhile
- call job_setoptions(term_getjob(s:gdbbuf), {'exit_cb': function('s:EndTermDebug')})
+ if success == false
+ Echoerr('Cannot check if your gdb works, continuing anyway')
+ return
+ endif
+
+ job_setoptions(term_getjob(gdbbuf), {'exit_cb': function('EndTermDebug')})
- " Set the filetype, this can be used to add mappings.
+ # Set the filetype, this can be used to add mappings.
set filetype=termdebug
- call s:StartDebugCommon(a:dict)
-endfunc
+ StartDebugCommon(dict)
+enddef
-" Open a window with a prompt buffer to run gdb in.
-func s:StartDebug_prompt(dict)
- if s:vertical
+# Open a window with a prompt buffer to run gdb in.
+def StartDebug_prompt(dict: dict<any>)
+ if vvertical
vertical new
else
new
endif
- let s:gdbwin = win_getid()
- let s:promptbuf = bufnr('')
- call prompt_setprompt(s:promptbuf, 'gdb> ')
+ gdbwin = win_getid()
+ promptbuf = bufnr('')
+ prompt_setprompt(promptbuf, 'gdb> ')
set buftype=prompt
if empty(glob('gdb'))
@@ -421,108 +482,108 @@ func s:StartDebug_prompt(dict)
elseif empty(glob('Termdebug-gdb-console'))
file Termdebug-gdb-console
else
- call s:Echoerr("You have a file/folder named 'gdb'
+ Echoerr("You have a file/folder named 'gdb'
\ or 'Termdebug-gdb-console'.
\ Please exit and rename them because Termdebug may not work as expected.")
endif
- call prompt_setcallback(s:promptbuf, function('s:PromptCallback'))
- call prompt_setinterrupt(s:promptbuf, function('s:PromptInterrupt'))
-
- if s:vertical
- " Assuming the source code window will get a signcolumn, use two more
- " columns for that, thus one less for the terminal window.
- exe (&columns / 2 - 1) . "wincmd |"
- endif
-
- let gdb_args = get(a:dict, 'gdb_args', [])
- let proc_args = get(a:dict, 'proc_args', [])
-
- let gdb_cmd = s:GetCommand()
- " Add -quiet to avoid the intro message causing a hit-enter prompt.
- let gdb_cmd += ['-quiet']
- " Disable pagination, it causes everything to stop at the gdb, needs to be run early
- let gdb_cmd += ['-iex', 'set pagination off']
- " Interpret commands while the target is running. This should usually only
- " be exec-interrupt, since many commands don't work properly while the
- " target is running (so execute during startup).
- let gdb_cmd += ['-iex', 'set mi-async on']
- " directly communicate via mi2
- let gdb_cmd += ['--interpreter=mi2']
-
- " Adding arguments requested by the user
- let gdb_cmd += gdb_args
-
- call ch_log('executing "' . join(gdb_cmd) . '"')
- let s:gdbjob = job_start(gdb_cmd, {
- \ 'exit_cb': function('s:EndPromptDebug'),
- \ 'out_cb': function('s:GdbOutCallback'),
- \ })
- if job_status(s:gdbjob) != "run"
- call s:Echoerr('Failed to start gdb')
- exe 'bwipe! ' . s:promptbuf
+ prompt_setcallback(promptbuf, function('PromptCallback'))
+ prompt_setinterrupt(promptbuf, function('PromptInterrupt'))
+
+ if vvertical
+ # Assuming the source code window will get a signcolumn, use two more
+ # columns for that, thus one less for the terminal window.
+ exe ":" .. (&columns / 2 - 1) .. "wincmd |"
+ endif
+
+ var gdb_args = get(dict, 'gdb_args', [])
+ var proc_args = get(dict, 'proc_args', [])
+
+ var gdb_cmd = GetCommand()
+ # Add -quiet to avoid the intro message causing a hit-enter prompt.
+ gdb_cmd += ['-quiet']
+ # Disable pagination, it causes everything to stop at the gdb, needs to be run early
+ gdb_cmd += ['-iex', 'set pagination off']
+ # Interpret commands while the target is running. This should usually only
+ # be exec-interrupt, since many commands don't work properly while the
+ # target is running (so execute during startup).
+ gdb_cmd += ['-iex', 'set mi-async on']
+ # directly communicate via mi2
+ gdb_cmd += ['--interpreter=mi2']
+
+ # Adding arguments requested by the user
+ gdb_cmd += gdb_args
+
+ ch_log('executing "' .. join(gdb_cmd) .. '"')
+ gdbjob = job_start(gdb_cmd, {
+ \ 'exit_cb': function('EndPromptDebug'),
+ \ 'out_cb': function('GdbOutCallback'),
+ \ })
+ if job_status(gdbjob) != "run"
+ Echoerr('Failed to start gdb')
+ exe 'bwipe! ' .. promptbuf
return
endif
- exe $'au BufUnload <buffer={s:promptbuf}> ++once ' ..
- \ 'call job_stop(s:gdbjob, ''kill'')'
- " Mark the buffer modified so that it's not easy to close.
+ exe $'au BufUnload <buffer={promptbuf}> ++once ' ..
+ \ 'call job_stop(gdbjob, ''kill'')'
+ # Mark the buffer modified so that it's not easy to close.
set modified
- let s:gdb_channel = job_getchannel(s:gdbjob)
+ gdb_channel = job_getchannel(gdbjob)
- let s:ptybuf = 0
+ ptybuf = 0
if has('win32')
- " MS-Windows: run in a new console window for maximum compatibility
- call s:SendCommand('set new-console on')
+ # 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 let s:ptybuf = term_start('NONE', {
- \ 'term_name': 'debugged program',
- \ })
- if s:ptybuf == 0
- call s:Echoerr('Failed to open the program terminal window')
- call job_stop(s:gdbjob)
+ # Unix: Run the debugged program in a terminal window. Open it below the
+ # gdb window.
+ belowright ptybuf = term_start('NONE', {
+ \ 'term_name': 'debugged program',
+ \ })
+ if ptybuf == 0
+ Echoerr('Failed to open the program terminal window')
+ job_stop(gdbjob)
return
endif
- let s:ptywin = win_getid()
- let pty = job_info(term_getjob(s:ptybuf))['tty_out']
- call s:SendCommand('tty ' . pty)
-
- " Since GDB runs in a prompt window, the environment has not been set to
- " match a terminal window, need to do that now.
- call s:SendCommand('set env TERM = xterm-color')
- call s:SendCommand('set env ROWS = ' . winheight(s:ptywin))
- call s:SendCommand('set env LINES = ' . winheight(s:ptywin))
- call s:SendCommand('set env COLUMNS = ' . winwidth(s:ptywin))
- call s:SendCommand('set env COLORS = ' . &t_Co)
- call s:SendCommand('set env VIM_TERMINAL = ' . v:version)
+ ptywin = win_getid()
+ var pty = job_info(term_getjob(ptybuf))['tty_out']
+ SendCommand('tty ' .. pty)
+
+ # Since GDB runs in a prompt window, the environment has not been set to
+ # match a terminal window, need to do that now.
+ SendCommand('set env TERM = xterm-color')
+ SendCommand('set env ROWS = ' .. winheight(ptywin))
+ SendCommand('set env LINES = ' .. winheight(ptywin))
+ SendCommand('set env COLUMNS = ' .. winwidth(ptywin))
+ SendCommand('set env COLORS = ' .. &t_Co)
+ SendCommand('set env VIM_TERMINAL = ' .. v:version)
else
- " TODO: open a new terminal, get the tty name, pass on to gdb
- call s:SendCommand('show inferior-tty')
+ # TODO: open a new terminal, get the tty name, pass on to gdb
+ SendCommand('show inferior-tty')
endif
- call s:SendCommand('set print pretty on')
- call s:SendCommand('set breakpoint pending on')
+ SendCommand('set print pretty on')
+ SendCommand('set breakpoint pending on')
- " Set arguments to be run
+ # Set arguments to be run
if len(proc_args)
- call s:SendCommand('set args ' . join(proc_args))
+ SendCommand('set args ' .. join(proc_args))
endif
- call s:StartDebugCommon(a:dict)
+ StartDebugCommon(dict)
startinsert
-endfunc
+enddef
-func s:StartDebugCommon(dict)
- " Sign used to highlight the line where the program has stopped.
- " There can be only one.
- call sign_define('debugPC', #{linehl: 'debugPC'})
+def StartDebugCommon(dict: dict<any>)
+ # Sign used to highlight the line where the program has stopped.
+ # There can be only one.
+ sign_define('debugPC', {'linehl': 'debugPC'})
- " Install debugger commands in the text window.
- call win_gotoid(s:sourcewin)
- call s:InstallCommands()
- call win_gotoid(s:gdbwin)
+ # Install debugger commands in the text window.
+ win_gotoid(sourcewin)
+ InstallCommands()
+ win_gotoid(gdbwin)
- " Enable showing a balloon with eval info
+ # Enable showing a balloon with eval info
if has("balloon_eval") || has("balloon_eval_term")
set balloonexpr=TermDebugBalloonExpr()
if has("balloon_eval")
@@ -533,243 +594,238 @@ func s:StartDebugCommon(dict)
endif
endif
- " 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}}
- let s:breakpoints = {}
-
- " Contains breakpoints by file/lnum. The key is "fname:lnum".
- " Each entry is a list of breakpoint IDs at that position.
- let s:breakpoint_locations = {}
-
augroup TermDebug
- au BufRead * call s:BufRead()
- au BufUnload * call s:BufUnloaded()
- au OptionSet background call s:Highlight(0, v:option_old, v:option_new)
+ au BufRead * BufRead()
+ au BufUnload * BufUnloaded()
+ au OptionSet background Highlight(0, v:option_old, v:option_new)
augroup END
- " Run the command if the bang attribute was given and got to the debug
- " window.
- if get(a:dict, 'bang', 0)
- call s:SendResumingCommand('-exec-run')
- call win_gotoid(s:ptywin)
+ # Run the command if the bang attribute was given and got to the debug
+ # window.
+ if get(dict, 'bang', 0)
+ SendResumingCommand('-exec-run')
+ win_gotoid(ptywin)
endif
-endfunc
+enddef
-" Send a command to gdb. "cmd" is the string without line terminator.
-func s:SendCommand(cmd)
- call ch_log('sending to gdb: ' . a:cmd)
- if s:way == 'prompt'
- call ch_sendraw(s:gdb_channel, a:cmd . "\n")
+# Send a command to gdb. "cmd" is the string without line terminator.
+def SendCommand(cmd: string)
+ ch_log('sending to gdb: ' .. cmd)
+ if way == 'prompt'
+ ch_sendraw(gdb_channel, cmd .. "\n")
else
- call term_sendkeys(s:commbuf, a:cmd . "\r")
+ term_sendkeys(commbuf, cmd .. "\r")
endif
-endfunc
+enddef
-" This is global so that a user can create their mappings with this.
-func TermDebugSendCommand(cmd)
- if s:way == 'prompt'
- call ch_sendraw(s:gdb_channel, a:cmd . "\n")
+# This is global so that a user can create their mappings with this.
+def TermDebugSendCommand(cmd: string)
+ if way == 'prompt'
+ ch_sendraw(gdb_channel, cmd .. "\n")
else
- let do_continue = 0
- if !s:stopped
- let do_continue = 1
+ var do_continue = 0
+ if !stopped
+