diff options
Diffstat (limited to 'runtime/pack/dist')
| -rw-r--r-- | runtime/pack/dist/opt/matchit/autoload/matchit.vim | 17 | ||||
| -rw-r--r-- | runtime/pack/dist/opt/matchit/doc/matchit.txt | 26 | ||||
| -rw-r--r-- | runtime/pack/dist/opt/matchit/plugin/matchit.vim | 105 | ||||
| -rw-r--r-- | runtime/pack/dist/opt/termdebug/plugin/termdebug.vim | 742 | ||||
| -rw-r--r-- | runtime/pack/dist/opt/vimball/autoload/vimball.vim | 775 | ||||
| -rw-r--r-- | runtime/pack/dist/opt/vimball/doc/vimball.txt | 273 | ||||
| -rw-r--r-- | runtime/pack/dist/opt/vimball/plugin/vimballPlugin.vim | 43 |
7 files changed, 608 insertions, 1373 deletions
diff --git a/runtime/pack/dist/opt/matchit/autoload/matchit.vim b/runtime/pack/dist/opt/matchit/autoload/matchit.vim index eafb7c0551..dc2aba696d 100644 --- a/runtime/pack/dist/opt/matchit/autoload/matchit.vim +++ b/runtime/pack/dist/opt/matchit/autoload/matchit.vim @@ -1,6 +1,6 @@ " matchit.vim: (global plugin) Extended "%" matching " autload script of matchit plugin, see ../plugin/matchit.vim -" Last Change: Jun 10, 2021 +" Last Change: Jan 24, 2022 " Neovim does not support scriptversion if has("vimscript-4") @@ -42,6 +42,10 @@ function s:RestoreOptions() let restore_options = " ve=" .. &ve .. restore_options set ve= endif + if &smartcase + let restore_options = " smartcase " .. restore_options + set nosmartcase + endif return restore_options endfunction @@ -134,9 +138,6 @@ function matchit#Match_wrapper(word, forward, mode) range let curcol = match(matchline, regexp) " If there is no match, give up. if curcol == -1 - " Make sure macros abort properly - "exe "norm! \<esc>" - call feedkeys("\e", 'tni') return s:CleanUp(restore_options, a:mode, startpos) endif let endcol = matchend(matchline, regexp) @@ -756,15 +757,15 @@ endfun fun! s:ParseSkip(str) let skip = a:str if skip[1] == ":" - if skip[0] == "s" + if skip[0] ==# "s" let skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '" .. \ strpart(skip,2) .. "'" - elseif skip[0] == "S" + elseif skip[0] ==# "S" let skip = "synIDattr(synID(line('.'),col('.'),1),'name') !~? '" .. \ strpart(skip,2) .. "'" - elseif skip[0] == "r" + elseif skip[0] ==# "r" let skip = "strpart(getline('.'),0,col('.'))=~'" .. strpart(skip,2) .. "'" - elseif skip[0] == "R" + elseif skip[0] ==# "R" let skip = "strpart(getline('.'),0,col('.'))!~'" .. strpart(skip,2) .. "'" endif endif diff --git a/runtime/pack/dist/opt/matchit/doc/matchit.txt b/runtime/pack/dist/opt/matchit/doc/matchit.txt index 45033ce3f1..88d0c38e4d 100644 --- a/runtime/pack/dist/opt/matchit/doc/matchit.txt +++ b/runtime/pack/dist/opt/matchit/doc/matchit.txt @@ -1,10 +1,10 @@ -*matchit.txt* Extended "%" matching +*matchit.txt* Extended |%| matching For instructions on installing this file, type `:help matchit-install` inside Vim. -For Vim version 8.2. Last change: 2021 Dec 24 +For Vim version 9.0. Last change: 2023 June 28 VIM REFERENCE MANUAL by Benji Fisher et al @@ -150,8 +150,7 @@ To use the matchit plugin add this line to your |vimrc|: > The script should start working the next time you start Vim. -To use the matchit plugin after startup, you can use this command (note the -omitted '!'): > +To use the matchit plugin after Vim has started, execute this command: > packadd matchit (Earlier versions of the script did nothing unless a |buffer-variable| named @@ -175,6 +174,22 @@ fail to skip matching groups in comments and strings. If the |filetype| mechanism is turned off, the |b:match_words| variable will probably not be defined automatically. +2.1 Temporarily disable the matchit plugin *matchit-disable* *:MatchDisable* + +To temporarily reset the plugins, that are setup you can run the following +command: > + :MatchDisable + +This will delete all the defined key mappings to the Vim default. +Now the "%" command will work like before loading the plugin |%| + +2.2 Re-enable the matchit plugin *:MatchEnable* + +To re-enable the plugin, after it was disabled, use the following command: > + :MatchEnable + +This will resetup the key mappings. + ============================================================================== 3. Configuration *matchit-configure* @@ -243,6 +258,9 @@ Examples: comment character) you can > :let b:match_skip = 'r:\(^\|[^\\]\)\(\\\\\)*%' < + See the $VIMRUNTIME/ftplugin/vim.vim for an example that uses both + syntax and a regular expression. + ============================================================================== 4. Supporting a New Language *matchit-newlang* *b:match_words* diff --git a/runtime/pack/dist/opt/matchit/plugin/matchit.vim b/runtime/pack/dist/opt/matchit/plugin/matchit.vim index 51ba3a7f51..d6c735d7b4 100644 --- a/runtime/pack/dist/opt/matchit/plugin/matchit.vim +++ b/runtime/pack/dist/opt/matchit/plugin/matchit.vim @@ -1,7 +1,7 @@ " matchit.vim: (global plugin) Extended "%" matching " Maintainer: Christian Brabandt -" Version: 1.18 -" Last Change: 2020 Dec 23 +" Version: 1.19 +" Last Change: 2023, June 28th " Repository: https://github.com/chrisbra/matchit " Previous URL:http://www.vim.org/script.php?script_id=39 " Previous Maintainer: Benji Fisher PhD <benji@member.AMS.org> @@ -46,44 +46,65 @@ let g:loaded_matchit = 1 let s:save_cpo = &cpo set cpo&vim -nnoremap <silent> <Plug>(MatchitNormalForward) :<C-U>call matchit#Match_wrapper('',1,'n')<CR> -nnoremap <silent> <Plug>(MatchitNormalBackward) :<C-U>call matchit#Match_wrapper('',0,'n')<CR> -xnoremap <silent> <Plug>(MatchitVisualForward) :<C-U>call matchit#Match_wrapper('',1,'v')<CR> - \:if col("''") != col("$") \| exe ":normal! m'" \| endif<cr>gv`` -xnoremap <silent> <Plug>(MatchitVisualBackward) :<C-U>call matchit#Match_wrapper('',0,'v')<CR>m'gv`` -onoremap <silent> <Plug>(MatchitOperationForward) :<C-U>call matchit#Match_wrapper('',1,'o')<CR> -onoremap <silent> <Plug>(MatchitOperationBackward) :<C-U>call matchit#Match_wrapper('',0,'o')<CR> - -" Analogues of [{ and ]} using matching patterns: -nnoremap <silent> <Plug>(MatchitNormalMultiBackward) :<C-U>call matchit#MultiMatch("bW", "n")<CR> -nnoremap <silent> <Plug>(MatchitNormalMultiForward) :<C-U>call matchit#MultiMatch("W", "n")<CR> -xnoremap <silent> <Plug>(MatchitVisualMultiBackward) :<C-U>call matchit#MultiMatch("bW", "n")<CR>m'gv`` -xnoremap <silent> <Plug>(MatchitVisualMultiForward) :<C-U>call matchit#MultiMatch("W", "n")<CR>m'gv`` -onoremap <silent> <Plug>(MatchitOperationMultiBackward) :<C-U>call matchit#MultiMatch("bW", "o")<CR> -onoremap <silent> <Plug>(MatchitOperationMultiForward) :<C-U>call matchit#MultiMatch("W", "o")<CR> - -" text object: -xmap <silent> <Plug>(MatchitVisualTextObject) <Plug>(MatchitVisualMultiBackward)o<Plug>(MatchitVisualMultiForward) - -if !exists("g:no_plugin_maps") - nmap <silent> % <Plug>(MatchitNormalForward) - nmap <silent> g% <Plug>(MatchitNormalBackward) - xmap <silent> % <Plug>(MatchitVisualForward) - xmap <silent> g% <Plug>(MatchitVisualBackward) - omap <silent> % <Plug>(MatchitOperationForward) - omap <silent> g% <Plug>(MatchitOperationBackward) +fun MatchEnable() + nnoremap <silent> <Plug>(MatchitNormalForward) :<C-U>call matchit#Match_wrapper('',1,'n')<CR> + nnoremap <silent> <Plug>(MatchitNormalBackward) :<C-U>call matchit#Match_wrapper('',0,'n')<CR> + xnoremap <silent> <Plug>(MatchitVisualForward) :<C-U>call matchit#Match_wrapper('',1,'v')<CR> + \:if col("''") != col("$") \| exe ":normal! m'" \| endif<cr>gv`` + xnoremap <silent> <Plug>(MatchitVisualBackward) :<C-U>call matchit#Match_wrapper('',0,'v')<CR>m'gv`` + onoremap <silent> <Plug>(MatchitOperationForward) :<C-U>call matchit#Match_wrapper('',1,'o')<CR> + onoremap <silent> <Plug>(MatchitOperationBackward) :<C-U>call matchit#Match_wrapper('',0,'o')<CR> " Analogues of [{ and ]} using matching patterns: - nmap <silent> [% <Plug>(MatchitNormalMultiBackward) - nmap <silent> ]% <Plug>(MatchitNormalMultiForward) - xmap <silent> [% <Plug>(MatchitVisualMultiBackward) - xmap <silent> ]% <Plug>(MatchitVisualMultiForward) - omap <silent> [% <Plug>(MatchitOperationMultiBackward) - omap <silent> ]% <Plug>(MatchitOperationMultiForward) - - " Text object - xmap a% <Plug>(MatchitVisualTextObject) -endif + nnoremap <silent> <Plug>(MatchitNormalMultiBackward) :<C-U>call matchit#MultiMatch("bW", "n")<CR> + nnoremap <silent> <Plug>(MatchitNormalMultiForward) :<C-U>call matchit#MultiMatch("W", "n")<CR> + xnoremap <silent> <Plug>(MatchitVisualMultiBackward) :<C-U>call matchit#MultiMatch("bW", "n")<CR>m'gv`` + xnoremap <silent> <Plug>(MatchitVisualMultiForward) :<C-U>call matchit#MultiMatch("W", "n")<CR>m'gv`` + onoremap <silent> <Plug>(MatchitOperationMultiBackward) :<C-U>call matchit#MultiMatch("bW", "o")<CR> + onoremap <silent> <Plug>(MatchitOperationMultiForward) :<C-U>call matchit#MultiMatch("W", "o")<CR> + + " text object: + xmap <silent> <Plug>(MatchitVisualTextObject) <Plug>(MatchitVisualMultiBackward)o<Plug>(MatchitVisualMultiForward) + + if !exists("g:no_plugin_maps") + nmap <silent> % <Plug>(MatchitNormalForward) + nmap <silent> g% <Plug>(MatchitNormalBackward) + xmap <silent> % <Plug>(MatchitVisualForward) + xmap <silent> g% <Plug>(MatchitVisualBackward) + omap <silent> % <Plug>(MatchitOperationForward) + omap <silent> g% <Plug>(MatchitOperationBackward) + + " Analogues of [{ and ]} using matching patterns: + nmap <silent> [% <Plug>(MatchitNormalMultiBackward) + nmap <silent> ]% <Plug>(MatchitNormalMultiForward) + xmap <silent> [% <Plug>(MatchitVisualMultiBackward) + xmap <silent> ]% <Plug>(MatchitVisualMultiForward) + omap <silent> [% <Plug>(MatchitOperationMultiBackward) + omap <silent> ]% <Plug>(MatchitOperationMultiForward) + + " Text object + xmap a% <Plug>(MatchitVisualTextObject) + endif +endfun + +fun MatchDisable() + " remove all the setup keymappings + nunmap % + nunmap g% + xunmap % + xunmap g% + ounmap % + ounmap g% + + nunmap [% + nunmap ]% + xunmap [% + xunmap ]% + ounmap [% + ounmap ]% + + xunmap a% +endfun " Call this function to turn on debugging information. Every time the main " script is run, buffer variables will be saved. These can be used directly @@ -91,6 +112,14 @@ endif if !exists(":MatchDebug") command! -nargs=0 MatchDebug call matchit#Match_debug() endif +if !exists(":MatchDisable") + command! -nargs=0 MatchDisable :call MatchDisable() +endif +if !exists(":MatchEnable") + command! -nargs=0 MatchEnable :call MatchEnable() +endif + +call MatchEnable() let &cpo = s:save_cpo unlet s:save_cpo diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim index 99fd7dba42..1b5baa9a8b 100644 --- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim +++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim @@ -2,7 +2,7 @@ " " Author: Bram Moolenaar " Copyright: Vim license applies, see ":help license" -" Last Change: 2022 Nov 10 +" 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 @@ -75,6 +75,7 @@ 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 = [] @@ -87,6 +88,8 @@ 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' @@ -96,9 +99,21 @@ func s:Highlight(init, old, new) endif endfunc -call s:Highlight(1, '', &background) -hi default debugBreakpoint term=reverse ctermbg=red guibg=red -hi default debugBreakpointDisabled term=reverse ctermbg=gray guibg=gray +" Define the default highlighting, using the current 'background' value. +func s:InitHighlight() + call s:Highlight(1, '', &background) + hi default debugBreakpoint term=reverse ctermbg=red guibg=red + hi default debugBreakpointDisabled term=reverse ctermbg=gray guibg=gray +endfunc + +" Setup an autocommand to redefine the default highlight when the colorscheme +" is changed. +func s:InitAutocmd() + augroup TermDebug + autocmd! + autocmd ColorScheme * call s:InitHighlight() + augroup END +endfunc " Get the command to execute the debugger as a list, defaults to ["gdb"]. func s:GetCommand() @@ -113,6 +128,10 @@ func s:GetCommand() return type(cmd) == v:t_list ? copy(cmd) : [cmd] endfunc +func s:Echoerr(msg) + echohl ErrorMsg | echom '[termdebug] ' .. a:msg | echohl None +endfunc + 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}) @@ -125,18 +144,21 @@ endfunc func s:StartDebug_internal(dict) if exists('s:gdbwin') - echoerr 'Terminal debugger already running, cannot run two' + call s:Echoerr('Terminal debugger already running, cannot run two') return endif let gdbcmd = s:GetCommand() if !executable(gdbcmd[0]) - echoerr 'Cannot execute debugger program "' .. gdbcmd[0] .. '"' + call s: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 @@ -145,7 +167,7 @@ func s:StartDebug_internal(dict) " Uncomment this line to write logging in "debuglog". " call ch_logfile('debuglog', 'w') - let s:sourcewin = win_getid(winnr()) + let s:sourcewin = win_getid() " Remember the old value of 'signcolumn' for each buffer that it's set in, so " that we can restore the value for all buffers. @@ -182,9 +204,9 @@ func s:StartDebug_internal(dict) endif if !has('win32') && !use_prompt let s:way = 'terminal' - else + else let s:way = 'prompt' - endif + endif if s:way == 'prompt' call s:StartDebug_prompt(a:dict) @@ -193,11 +215,17 @@ func s:StartDebug_internal(dict) endif if s:GetDisasmWindow() - let curwinid = win_getid(winnr()) + let curwinid = win_getid() call s:GotoAsmwinOrCreateIt() call win_gotoid(curwinid) endif + if s:GetVariablesWindow() + let curwinid = win_getid() + call s:GotoVariableswinOrCreateIt() + call win_gotoid(curwinid) + endif + if exists('#User#TermdebugStartPost') doauto <nomodeline> User TermdebugStartPost endif @@ -206,14 +234,21 @@ endfunc " Use when debugger didn't start or ended. func s:CloseBuffers() exe 'bwipe! ' . s:ptybuf + if s:asmbuf > 0 && bufexists(s:asmbuf) + exe 'bwipe! ' . s:asmbuf + endif + if s:varbuf > 0 && bufexists(s:varbuf) + exe 'bwipe! ' . s:varbuf + endif + let s:running = 0 unlet! s:gdbwin endfunc func s:CheckGdbRunning() - if !s:running - echoerr string(s:GetCommand()[0]) . ' exited unexpectedly' - call s:CloseBuffers() - return '' + if !s:gdb_running + call s:Echoerr(string(s:GetCommand()[0]) . ' exited unexpectedly') + call s:CloseBuffers() + return '' endif return 'ok' endfunc @@ -223,16 +258,16 @@ func s:StartDebug_term(dict) execute s:vertical ? 'vnew' : 'new' let s:pty_job_id = termopen('tail -f /dev/null;#gdb program') if s:pty_job_id == 0 - echoerr 'invalid argument (or job table is full) while opening terminal window' + call s:Echoerr('Invalid argument (or job table is full) while opening terminal window') return elseif s:pty_job_id == -1 - echoerr 'Failed to open the program terminal window' + call s:Echoerr('Failed to open the program terminal window') return endif let pty_job_info = nvim_get_chan_info(s:pty_job_id) let s:ptybuf = pty_job_info['buffer'] let pty = pty_job_info['pty'] - let s:ptywin = win_getid(winnr()) + 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. @@ -245,16 +280,16 @@ func s:StartDebug_term(dict) " Create a hidden terminal window to communicate with gdb let s:comm_job_id = jobstart('tail -f /dev/null;#gdb communication', { - \ 'on_stdout': function('s:CommOutput'), + \ 'on_stdout': function('s:JobOutCallback', {'last_line': '', 'real_cb': function('s:CommOutput')}), \ 'pty': v:true, \ }) " hide terminal buffer if s:comm_job_id == 0 - echoerr 'invalid argument (or job table is full) while opening communication terminal window' + call s:Echoerr('Invalid argument (or job table is full) while opening communication terminal window') exe 'bwipe! ' . s:ptybuf return elseif s:comm_job_id == -1 - echoerr 'Failed to open the communication terminal window' + call s:Echoerr('Failed to open the communication terminal window') exe 'bwipe! ' . s:ptybuf return endif @@ -295,19 +330,19 @@ func s:StartDebug_term(dict) " call ch_log('executing "' . join(gdb_cmd) . '"') let s:gdb_job_id = termopen(gdb_cmd, {'on_exit': function('s:EndTermDebug')}) if s:gdb_job_id == 0 - echoerr 'invalid argument (or job table is full) while opening gdb terminal window' + call s:Echoerr('Invalid argument (or job table is full) while opening gdb terminal window') exe 'bwipe! ' . s:ptybuf return elseif s:gdb_job_id == -1 - echoerr 'Failed to open the gdb terminal window' + call s:Echoerr('Failed to open the gdb terminal window') call s:CloseBuffers() return endif - let s:running = v:true + let s:gdb_running = v:true let s:starting = v:true let gdb_job_info = nvim_get_chan_info(s:gdb_job_id) let s:gdbbuf = gdb_job_info['buffer'] - let s:gdbwin = win_getid(winnr()) + let s:gdbwin = win_getid() " Wait for the "startupdone" message before sending any commands. let try_count = 0 @@ -355,7 +390,7 @@ func s:StartDebug_term(dict) " response can be in the same line or the next line let response = line1 . line2 if response =~ 'Undefined command' - echoerr 'Sorry, your gdb is too old, gdb 7.12 is required' + 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() return @@ -374,7 +409,7 @@ func s:StartDebug_term(dict) endif let try_count += 1 if try_count > 100 - echoerr 'Cannot check if your gdb works, continuing anyway' + call s:Echoerr('Cannot check if your gdb works, continuing anyway') break endif sleep 10m @@ -395,7 +430,7 @@ func s:StartDebug_prompt(dict) else new endif - let s:gdbwin = win_getid(winnr()) + let s:gdbwin = win_getid() let s:promptbuf = bufnr('') call prompt_setprompt(s:promptbuf, 'gdb> ') set buftype=prompt @@ -429,18 +464,19 @@ func s:StartDebug_prompt(dict) " call ch_log('executing "' . join(gdb_cmd) . '"') let s:gdbjob = jobstart(gdb_cmd, { - \ 'on_exit': function('s:EndPromptDebug'), - \ 'on_stdout': function('s:GdbOutCallback'), - \ }) + \ 'on_exit': function('s:EndPromptDebug'), + \ 'on_stdout': function('s:JobOutCallback', {'last_line': '', 'real_cb': function('s:GdbOutCallback')}), + \ }) if s:gdbjob == 0 - echoerr 'invalid argument (or job table is full) while starting gdb job' + call s:Echoerr('Invalid argument (or job table is full) while starting gdb job') exe 'bwipe! ' . s:ptybuf return elseif s:gdbjob == -1 - echoerr 'Failed to start the gdb job' + call s:Echoerr('Failed to start the gdb job') call s:CloseBuffers() return endif + exe $'au BufUnload <buffer={s:promptbuf}> ++once call jobstop(s:gdbjob)' let s:ptybuf = 0 if has('win32') @@ -449,20 +485,19 @@ func s:StartDebug_prompt(dict) else " Unix: Run the debugged program in a terminal window. Open it below the " gdb window. - execute 'new' - wincmd x | wincmd j - belowright let s:pty_job_id = termopen('tail -f /dev/null;#gdb program') + belowright new + let s:pty_job_id = termopen('tail -f /dev/null;#gdb program') if s:pty_job_id == 0 - echoerr 'invalid argument (or job table is full) while opening terminal window' + call s:Echoerr('Invalid argument (or job table is full) while opening terminal window') return elseif s:pty_job_id == -1 - echoerr 'Failed to open the program terminal window' + call s:Echoerr('Failed to open the program terminal window') return endif let pty_job_info = nvim_get_chan_info(s:pty_job_id) let s:ptybuf = pty_job_info['buffer'] let pty = pty_job_info['pty'] - let s:ptywin = win_getid(winnr()) + let s:ptywin = win_getid() call s:SendCommand('tty ' . pty) " Since GDB runs in a prompt window, the environment has not been set to @@ -585,46 +620,69 @@ func s:PromptInterrupt() " Using job_stop() does not work on MS-Windows, need to send SIGTRAP to " the debugger program so that gdb responds again. if s:pid == 0 - echoerr 'Cannot interrupt gdb, did not find a process ID' + call s:Echoerr('Cannot interrupt gdb, did not find a process ID') else call debugbreak(s:pid) endif else - call jobstop(s:gdbjob) + call v:lua.vim.uv.kill(jobpid(s:gdbjob), 'sigint') endif endfunc +" Wrapper around job callback that handles partial lines (:h channel-lines). +" It should be called from a Dictionary with the following keys: +" - last_line: the last (partial) line received +" - real_cb: a callback that assumes full lines +func s:JobOutCallback(jobid, data, event) dict + let eof = (a:data == ['']) + let msgs = a:data + let msgs[0] = self.last_line .. msgs[0] + if eof + let self.last_line = '' + else + let self.last_line = msgs[-1] + unlet msgs[-1] + endif + call self.real_cb(a:jobid, msgs, a:event) +endfunc + " Function called when gdb outputs text. func s:GdbOutCallback(job_id, msgs, event) "call ch_log('received from gdb: ' . a:text) - " Drop the gdb prompt, we have our own. - " Drop status and echo'd commands. - call filter(a:msgs, { index, val -> - \ val !=# '(gdb)' && val !=# '^done' && val[0] !=# '&'}) - + let comm_msgs = [] let lines = [] - let index = 0 for msg in a:msgs + " Disassembly messages need to be forwarded as-is. + if s:parsing_disasm_msg || msg =~ '^&"disassemble' + call s:CommOutput(a:job_id, [msg], a:event) + continue + endif + + " Drop the gdb prompt, we have our own. + " Drop status and echo'd commands. + if msg == '(gdb) ' || msg == '^done' || msg[0] == '&' + continue + endif + if msg =~ '^\^error,msg=' if exists('s:evalexpr') - \ && s:DecodeMessage(msg[11:]) + \ && s:DecodeMessage(msg[11:], v:false) \ =~ 'A syntax error in expression, near\|No symbol .* in current context' " Silently drop evaluation errors. - call remove(a:msgs, index) unlet s:evalexpr continue endif elseif msg[0] == '~' - call add(lines, s:DecodeMessage(msg[1:])) - call remove(a:msgs, index) + call add(lines, s:DecodeMessage(msg[1:], v:false)) continue endif - let index += 1 + + call add(comm_msgs, msg) endfor - let curwinid = win_getid(winnr()) + let curwinid = win_getid() call win_gotoid(s:gdbwin) " Add the output above the current prompt. @@ -636,35 +694,43 @@ func s:GdbOutCallback(job_id, msgs, event) endif call win_gotoid(curwinid) - call s:CommOutput(a:job_id, a:msgs, a:event) + call s:CommOutput(a:job_id, comm_msgs, a:event) endfunc -" Decode a message from gdb. quotedText starts with a ", return the text up -" to the next ", unescaping characters: -" - remove line breaks -" - change \\t to \t +" 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) +" - change \" to " +" - change \\t to \t (unless "literal" is v:true) " - change \0xhh to \xhh (disabled for now) " - change \ooo to octal " - change \\ to \ -func s:DecodeMessage(quotedText) +func s:DecodeMessage(quotedText, literal) if a:quotedText[0] != '"' - echoerr 'DecodeMessage(): missing quote in ' . a:quotedText + call s:Echoerr('DecodeMessage(): missing quote in ' . a:quotedText) return endif - return a:quotedText - \ ->substitute('^"\|".*\|\\n', '', 'g') - \ ->substitute('\\t', "\t", 'g') - " multi-byte characters arrive in octal form - " NULL-values must be kept encoded as those break the string otherwise + let msg = a:quotedText + \ ->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', s:NullRepl, 'g') \ ->substitute('\\\o\o\o', {-> eval('"' .. submatch(0) .. '"')}, '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', s:NullRepl, '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', s:NullRepl, 'g') \ ->substitute('\\\\', '\', 'g') \ ->substitute(s:NullRepl, '\\000', 'g') + if !a:literal + return msg + \ ->substitute('\\t', "\t", 'g') + \ ->substitute('\\n', '', 'g') + else + return msg + endif endfunc const s:NullRepl = 'XXXNULLXXX' @@ -673,7 +739,7 @@ func s:GetFullname(msg) if a:msg !~ 'fullname' return '' endif - let name = s:DecodeMessage(substitute(a:msg, '.*fullname=', '', '')) + let name = s:DecodeMessage(substitute(a:msg, '.*fullname=', '', ''), v:true) if has('win32') && name =~ ':\\\\' " sometimes the name arrives double-escaped let name = substitute(name, '\\\\', '\\', 'g') @@ -686,12 +752,12 @@ func s:GetAsmAddr(msg) if a:msg !~ 'addr=' return '' endif - let addr = s:DecodeMessage(substitute(a:msg, '.*addr=', '', '')) + let addr = s:DecodeMessage(substitute(a:msg, '.*addr=', '', ''), v:false) return addr endfunc -function s:EndTermDebug(job_id, exit_code, event) - let s:running = v:false +func s:EndTermDebug(job_id, exit_code, event) + let s:gdb_running = v:false if s:starting return endif @@ -701,16 +767,22 @@ function s:EndTermDebug(job_id, exit_code, event) endif unlet s:gdbwin - call s:EndDebugCommon() endfunc func s:EndDebugCommon() - let curwinid = win_getid(winnr()) + let curwinid = win_getid() if exists('s:ptybuf') && s:ptybuf exe 'bwipe! ' . s:ptybuf endif + if s:asmbuf > 0 && bufexists(s:asmbuf) + exe 'bwipe! ' . s:asmbuf + endif + if s:varbuf > 0 && bufexists(s:varbuf) + exe 'bwipe! ' . s:varbuf + endif + let s:running = 0 " Restore 'signcolumn' in all buffers for which it was set. call win_gotoid(s:sourcewin) @@ -748,11 +820,8 @@ func s:EndPromptDebug(job_id, exit_code, event) doauto <nomodeline> User TermdebugStopPre endif - let curwinid = win_getid(winnr()) - call win_gotoid(s:gdbwin) - close - if curwinid != s:gdbwin - call win_gotoid(curwinid) + if bufexists(s:promptbuf) + exe 'bwipe! ' . s:promptbuf endif call s:EndDebugCommon() @@ -760,7 +829,6 @@ func s:EndPromptDebug(job_id, exit_code, event) "call ch_log("Returning from EndPromptDebug()") endfunc -" - CommOutput: disassemble $pc " - CommOutput: &"disassemble $pc\n" " - CommOutput: ~"Dump of assembler code for function main(int, char**):\n" " - CommOutput: ~" 0x0000555556466f69 <+0>:\tpush rbp\n" @@ -770,15 +838,14 @@ endfunc " - CommOutput: ~"End of assembler dump.\n" " - CommOutput: ^done -" - CommOutput: disassemble $pc " - CommOutput: &"disassemble $pc\n" " - CommOutput: &"No function contains specified address.\n" " - CommOutput: ^error,msg="No function contains specified address." func s:HandleDisasmMsg(msg) if a:msg =~ '^\^done' - let curwinid = win_getid(winnr()) + let curwinid = win_getid() if win_gotoid(s:asmwin) - silent normal! gg0"_dG + silent! %delete _ call setline(1, s:asm_lines) set nomodified set filetype=asm @@ -802,15 +869,17 @@ func s:HandleDisasmMsg(msg) call s:SendCommand('disassemble $pc,+100') endif let s:parsing_disasm_msg = 0 - elseif a:msg =~ '\&\"disassemble \$pc' + elseif a:msg =~ '^&"disassemble \$pc' if a:msg =~ '+100' " This is our second disasm attempt let s:parsing_disasm_msg = 2 endif - else + elseif a:msg !~ '^&"disassemble' let value = substitute(a:msg, '^\~\"[ ]*', '', '') let value = substitute(value, '^=>[ ]*', '', '') - let value = substitute(value, '\\n\"\r$', '', '') + " Nvim already trims the final "\r" in s:CommOutput() + " let value = substitute(value, '\\n\"\r$', '', '') + let value = substitute(value, '\\n\"$', '', '') let value = substitute(value, '\r', '', '') let value = substitute(value, '\\t', ' ', 'g') @@ -820,12 +889,56 @@ func s:HandleDisasmMsg(msg) endif endfunc -func s:CommOutput(job_id, msgs, event) +func s:ParseVarinfo(varinfo) + let dict = {} + let nameIdx = matchstrpos(a:varinfo, '{name="\([^"]*\)"') + let dict['name'] = a:varinfo[nameIdx[1] + 7 : nameIdx[2] - 2] + let typeIdx = matchstrpos(a:varinfo, ',type="\([^"]*\)"') + " 'type' maybe is a url-like string, + " try to shorten it and show only the /tail + let dict['type'] = (a:varinfo[typeIdx[1] + 7 : typeIdx[2] - 2])->fnamemodify(':t') + let valueIdx = matchstrpos(a:varinfo, ',value="\(.*\)"}') + if valueIdx[1] == -1 + let dict['value'] = 'Complex value' + else + let dict['value'] = a:varinfo[valueIdx[1] + 8 : valueIdx[2] - 3] + endif + return dict +endfunc +func s:HandleVariablesMsg(msg) + let curwinid = win_getid() + if win_gotoid(s:varwin) + + silent! %delete _ + let spaceBuffer = 20 + call setline(1, 'Type' . + \ repeat(' ', 16) . + \ 'Name' . + \ repeat(' ', 16) . + \ 'Value') + let cnt = 1 + let capture = '{name=".\{-}",\%(arg=".\{-}",\)\{0,1\}type=".\{-}"\%(,value=".\{-}"\)\{0,1\}}' + let varinfo = matchstr(a:msg, capture, 0, cnt) + while varinfo != '' + let vardict = s:ParseVarinfo(varinfo) + call setline(cnt + 1, vardict['type'] . + \ repeat(' ', max([20 - len(vardict['type']), 1])) . + \ vardict['name'] . + \ repeat(' ', max([20 - len(vardict['name']), 1])) . + \ vardict['value']) + let cnt += 1 + let varinfo = matchstr(a:msg, capture, 0, cnt) + endwhile + endif + call win_gotoid(curwinid) +endfunc + +func s:CommOutput(job_id, msgs, event) for msg in a:msgs - " remove prefixed NL - if msg[0] == "\n" - let msg = msg[1:] + " Nvim job lines are split on "\n", so trim a suffixed CR. + if msg[-1:] == "\r" + let msg = msg[:-2] endif if s:parsing_disasm_msg @@ -845,9 +958,12 @@ func s:CommOutput(job_id, msgs, event) call s:HandleEvaluate(msg) elseif msg =~ '^\^error,msg=' call s:HandleError(msg) - elseif msg =~ '^disassemble' + elseif msg =~ '^&"disassemble' let s:parsing_disasm_msg = 1 let s:asm_lines = [] + call s:HandleDisasmMsg(msg) + elseif msg =~ '^\^done,variables=' + call s:HandleVariablesMsg(msg) endif endif endfor @@ -888,12 +1004,17 @@ func s:InstallCommands() command Continue call chansend(s:gdb_job_id, "continue\r") endif + command -nargs=* Frame call s:Frame(<q-args>) + command -count=1 Up call s:Up(<count>) + command -count=1 Down call s:Down(<count>) + command -range -nargs=* Evaluate call s:Evaluate(<range>, <q-args>) command Gdb call win_gotoid(s:gdbwin) command Program call s:GotoProgram() command Source call s:GotoSourcewinOrCreateIt() command Asm call s:GotoAsmwinOrCreateIt() - command Winbar call s:InstallWinbar() + command Var call s:GotoVariableswinOrCreateIt() + command Winbar call s:InstallWinbar(1) let map = 1 if exists('g:termdebug_config') @@ -902,26 +1023,37 @@ func s:InstallCommands() let map = g:termdebug_map_K endif if map - " let s:k_map_saved = maparg('K', 'n', 0, 1) - let s:k_map_saved = {} - for map in nvim_get_keymap('n') - if map.lhs ==# 'K' - let s:k_map_saved = map - break - endif - endfor - nnoremap K :Evaluate<CR> + let s:k_map_saved = maparg('K', 'n', 0, 1) + if !empty(s:k_map_saved) && !s:k_map_saved.buffer || empty(s:k_map_saved) + nnoremap K :Evaluate<CR> + endif endif - if has('menu') && &mouse != '' - " install the window toolbar by default, can be disabled in the config - let winbar = 1 - if exists('g:termdebug_config') - let winbar = get(g:termdebug_config, 'winbar', 1) + let map = 1 + if exists('g:termdebug_config') + let map = get(g:termdebug_config, 'map_plus', 1) + endif + if map + let s:plus_map_saved = maparg('+', 'n', 0, 1) + if !empty(s:plus_map_saved) && !s:plus_map_saved.buffer || empty(s:plus_map_saved) + nnoremap <expr> + $'<Cmd>{v:count1}Up<CR>' endif - if winbar - call s:InstallWinbar() + endif + + let map = 1 + if exists('g:termdebug_config') + let map = get(g:termdebug_config, 'map_minus', 1) + endif + if map + let s:minus_map_saved = maparg('-', 'n', 0, 1) + if !empty(s:minus_map_saved) && !s:minus_map_saved.buffer || empty(s:minus_map_saved) + nnoremap <expr> - $'<Cmd>{v:count1}Down<CR>' endif |