From 940af913be2a54e786e6553e7b27435bbe016d0a Mon Sep 17 00:00:00 2001 From: Reuben D'Netto Date: Sun, 15 Feb 2015 16:45:00 +1100 Subject: [PATCH 01/47] "Added 'con' option to vebugger#gdb#start" --- autoload/vebugger/gdb.vim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/vebugger/gdb.vim b/autoload/vebugger/gdb.vim index e9985b6..4915fc4 100644 --- a/autoload/vebugger/gdb.vim +++ b/autoload/vebugger/gdb.vim @@ -17,6 +17,8 @@ function! vebugger#gdb#start(binaryFile,args) if get(a:args,'pid') "Attach to process call l:debugger.writeLine('attach '.string(a:args.pid)) + elseif has_key(a:args,'con') "Attach to gdbserver + call l:debugger.writeLine('target remote '.a:args.con) else call l:debugger.writeLine('set args '.vebugger#util#commandLineArgsForProgram(a:args).' 1>&2') if !has('win32') From a97d06519ac1a6e4976ab313b2bc9e4c5b805c0c Mon Sep 17 00:00:00 2001 From: IdanArye Date: Mon, 16 Feb 2015 00:41:08 +0200 Subject: [PATCH 02/47] Add docs for the 'con' flag for gdb Also expand :VBGattachGDB to support either 'pid' or 'con' as second command argument. --- autoload/vebugger/gdb.vim | 7 ------- autoload/vebugger/util.vim | 3 ++- doc/vebugger.txt | 7 ++++++- plugin/vebugger.vim | 18 +++++++++++++++++- 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/autoload/vebugger/gdb.vim b/autoload/vebugger/gdb.vim index 4915fc4..8fa8d6d 100644 --- a/autoload/vebugger/gdb.vim +++ b/autoload/vebugger/gdb.vim @@ -1,10 +1,3 @@ -function! vebugger#gdb#searchAndAttach(binaryFile) - let l:processId=vebugger#util#selectProcessOfFile(a:binaryFile) - if 0 License: Same terms as Vim itself (see |license|) -Version: 1.2.2 +Version: 1.2.2+ INTRODUCTION *vebugger* @@ -117,6 +117,7 @@ GDB can be launched with *vebugger#gdb#start* The supported extra arguments are: * "args": Command line arguments for the debugged program * "pid": Process id to attach to +* "con": URL of GDB-server to connect to * "entry": The entry point for starting the debugging(default "main") * "version": The version of the debugger to run You can't specify both ("args" and/or "entry") and "pid". @@ -130,6 +131,10 @@ attach to, and attaches to them: > VBGattachGDB a.out < + +VBGattachGDB accepts as a second argument the process ID of the process to +attach to or the URL for a GDB-server to connect to. + The *VBGstartGDBForD* command is the same as VBGstartGDB but for Dlang programs. diff --git a/plugin/vebugger.vim b/plugin/vebugger.vim index 6ea2076..6f9449d 100644 --- a/plugin/vebugger.vim +++ b/plugin/vebugger.vim @@ -22,7 +22,23 @@ command! -range -nargs=0 VBGexecuteSelectedText call vebugger#std#execute(vebugg command! -range -nargs=0 VBGrawWriteSelectedText call vebugger#writeLine(vebugger#util#get_visual_selection()) command! -nargs=+ -complete=file VBGstartGDB call vebugger#gdb#start([][0],{'args':[][1:]}) -command! -nargs=1 -complete=file VBGattachGDB call vebugger#gdb#searchAndAttach() +function! s:attachGDB(...) + if 1 == a:0 + let l:processId=vebugger#util#selectProcessOfFile(a:1) + if 0 < l:processId + call vebugger#gdb#start(a:1, {'pid': l:processId}) + endif + elseif 2 == a:0 + if a:2 =~ '\v^\d+$' + call vebugger#gdb#start(a:1,{'pid': str2nr(a:2)}) + else + call vebugger#gdb#start(a:1, {'con': a:2}) + endif + else + throw "Can't call VBGattachGDB with ".a:0." arguments" + endif +endfunction +command! -nargs=+ -complete=file VBGattachGDB call s:attachGDB() command! -nargs=+ -complete=file VBGstartRDebug call vebugger#rdebug#start([][0],{'args':[][1:]}) command! -nargs=+ -complete=file VBGstartPDB call vebugger#pdb#start([][0],{'args':[][1:]}) command! -nargs=+ -complete=file VBGstartPDB2 call vebugger#pdb#start([][0],{'args':[][1:],'version':'2'}) From 2914f5a116b5b3202eb66ba0f4e626e3473395b6 Mon Sep 17 00:00:00 2001 From: Reuben D'Netto Date: Sun, 15 Feb 2015 18:12:08 +1100 Subject: [PATCH 03/47] Added configuration option g:vebugger_edit_cmd --- autoload/vebugger/std.vim | 2 +- doc/vebugger.txt | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/autoload/vebugger/std.vim b/autoload/vebugger/std.vim index d227081..f5e171d 100644 --- a/autoload/vebugger/std.vim +++ b/autoload/vebugger/std.vim @@ -169,7 +169,7 @@ function! s:standardThinkHandlers.moveToCurrentLine(readResult,debugger) dict endif let a:debugger.state.std.location=deepcopy(a:readResult.std.location) if !bufexists(a:readResult.std.location.file) - exe 'new '.(a:readResult.std.location.file) + exe get(g:, 'vebugger_view_source_cmd', 'new').' '.(a:readResult.std.location.file) endif call vebugger#std#updateMarksForFile(a:debugger.state,a:readResult.std.location.file) exe 'sign jump 1 file='.fnameescape(fnamemodify(a:readResult.std.location.file,':p')) diff --git a/doc/vebugger.txt b/doc/vebugger.txt index db8088d..01ef741 100644 --- a/doc/vebugger.txt +++ b/doc/vebugger.txt @@ -94,6 +94,13 @@ argument is supplied when running the debugger: *g:vebugger_path_mdbg_32* No default - use it for the 32bit version of Mdbg *g:vebugger_path_mdbg_64* No default - use it for the 64bit version of Mdbg +When stepping into functions in unopened files, they are opened with :new by +default. This can be configured by setting *g:vebugger_view_source_cmd* + +Example: > + let g:vebugger_view_source_cmd='edit' +< + LAUNCHING DEBUGGERS *vebugger-launching* A debugger's implementation is responsible for starting it. The standard is to From 4567ad166bfc18f23183c35bdc2adc7bdbc00a0a Mon Sep 17 00:00:00 2001 From: IdanArye Date: Sat, 28 Feb 2015 19:16:25 +0200 Subject: [PATCH 04/47] Change the code path of user actions Most user actions now go through vebugger#userAction, which calls the user action on the active debugger object. The exceptions are: - Starting the debugger - because we don't have an active debugger yet - Stopping the debugger - because we'll need to clear the active debugger after that - Altering breakpoints - because we want to be able to do it even without an active debugger(e.g. - setting breakpoints before starting the debugger) --- autoload/vebugger.vim | 408 ++++++++++++++++++------------------- autoload/vebugger/std.vim | 414 +++++++++++++++++++------------------- plugin/vebugger.vim | 24 +-- 3 files changed, 410 insertions(+), 436 deletions(-) diff --git a/autoload/vebugger.vim b/autoload/vebugger.vim index e1ec249..1cd80c1 100644 --- a/autoload/vebugger.vim +++ b/autoload/vebugger.vim @@ -1,199 +1,199 @@ "Read and return all new lines from a Vebugger pipe object. function! s:readNewLinesFromPipe(pipeObject) - "read - let l:text=a:pipeObject.pipe.read(1000,0) - while 0 if exists('b:debugger') | call b:debugger.kill() | endif - setlocal buftype=nofile - setlocal bufhidden=wipe - let a:debugger.shellBuffer=bufnr('') - silent file Vebugger:Shell - wincmd p + if has_key(a:debugger,'shellBuffer') + if -1 if exists('b:debugger') | call b:debugger.kill() | endif + setlocal buftype=nofile + setlocal bufhidden=wipe + let a:debugger.shellBuffer=bufnr('') + silent file Vebugger:Shell + wincmd p endfunction let s:standardFunctions={} "Write a line to the shell buffer function! s:standardFunctions.addLineToShellBuffer(line) dict - if has_key(self,'shellBuffer') - let l:bufwin=bufwinnr(self.shellBuffer) - if -1 @@ -240,83 +240,75 @@ sign define vebugger_breakpoint text=** linehl=ColorColumn "Update all the marks(currently executed line and breakpoints) for a file function! vebugger#std#updateMarksForFile(state,filename) - let l:filename=fnamemodify(a:filename,":p") - if bufexists(l:filename) - exe 'sign unplace 1 file='.fnameescape(fnamemodify(l:filename,':p')) - exe 'sign unplace 2 file='.fnameescape(fnamemodify(l:filename,':p')) + let l:filename=fnamemodify(a:filename,":p") + if bufexists(l:filename) + exe 'sign unplace 1 file='.fnameescape(fnamemodify(l:filename,':p')) + exe 'sign unplace 2 file='.fnameescape(fnamemodify(l:filename,':p')) - for l:breakpoint in g:vebugger_breakpoints - if fnamemodify(l:breakpoint.file,':p')==fnamemodify(a:filename,':p') - exe 'sign place 2 name=vebugger_breakpoint line='.l:breakpoint.line.' file='.fnameescape(fnamemodify(l:breakpoint.file,':p')) - endif - endfor + for l:breakpoint in g:vebugger_breakpoints + if fnamemodify(l:breakpoint.file,':p')==fnamemodify(a:filename,':p') + exe 'sign place 2 name=vebugger_breakpoint line='.l:breakpoint.line.' file='.fnameescape(fnamemodify(l:breakpoint.file,':p')) + endif + endfor - if !empty(a:state) - if !empty(a:state.std.location) - if fnamemodify(a:state.std.location.file,':p')==fnamemodify(a:filename,':p') - exe 'sign place 1 name=vebugger_current line='.a:state.std.location.line.' file='.fnameescape(fnamemodify(l:filename,':p')) - endif - endif - endif - endif + if !empty(a:state) + if !empty(a:state.std.location) + if fnamemodify(a:state.std.location.file,':p')==fnamemodify(a:filename,':p') + exe 'sign place 1 name=vebugger_current line='.a:state.std.location.line.' file='.fnameescape(fnamemodify(l:filename,':p')) + endif + endif + endif + endif endfunction "Toggle a breakpoint on and off function! vebugger#std#toggleBreakpoint(file,line) - let l:debugger=vebugger#getActiveDebugger() - let l:debuggerState=empty(l:debugger) - \? {} - \: l:debugger.state - for l:i in range(len(g:vebugger_breakpoints)) - let l:breakpoint=g:vebugger_breakpoints[l:i] - if l:breakpoint.file==a:file && l:breakpoint.line==a:line - call remove(g:vebugger_breakpoints,l:i) - call vebugger#addWriteActionAndPerform('std','breakpoints',{ - \'action':'remove', - \'file':(a:file), - \'line':(a:line)}) - call vebugger#std#updateMarksForFile(l:debuggerState,a:file) - return - endif - endfor - call add(g:vebugger_breakpoints,{'file':(a:file),'line':(a:line)}) - call vebugger#addWriteActionAndPerform('std','breakpoints',{ - \'action':'add', - \'file':(a:file), - \'line':(a:line)}) - call vebugger#std#updateMarksForFile(l:debuggerState,a:file) + let l:debugger=vebugger#getActiveDebugger() + let l:debuggerState=empty(l:debugger) + \? {} + \: l:debugger.state + for l:i in range(len(g:vebugger_breakpoints)) + let l:breakpoint=g:vebugger_breakpoints[l:i] + if l:breakpoint.file==a:file && l:breakpoint.line==a:line + call remove(g:vebugger_breakpoints,l:i) + if !empty(l:debugger) + call l:debugger.addWriteActionAndPerform('std','breakpoints',{ + \'action':'remove', + \'file':(a:file), + \'line':(a:line)}) + endif + call vebugger#std#updateMarksForFile(l:debuggerState,a:file) + return + endif + endfor + call add(g:vebugger_breakpoints,{'file':(a:file),'line':(a:line)}) + if !empty(l:debugger) + call l:debugger.addWriteActionAndPerform('std','breakpoints',{ + \'action':'add', + \'file':(a:file), + \'line':(a:line)}) + endif + call vebugger#std#updateMarksForFile(l:debuggerState,a:file) endfunction "Clear all breakpoints function! vebugger#std#clearBreakpoints() - let l:debugger=vebugger#getActiveDebugger() - let l:debuggerState=empty(l:debugger) ? {} : l:debugger.state - let l:files=[] - for l:breakpoint in g:vebugger_breakpoints - if index(l:files,l:breakpoint.file)<0 - call add(l:files,l:breakpoint.file) - endif - call vebugger#addWriteAction('std','breakpoints',extend({'action':'remove'},l:breakpoint)) - endfor - call vebugger#performWriteActions() - let g:vebugger_breakpoints=[] - for l:file in l:files - call vebugger#std#updateMarksForFile(l:debuggerState,l:file) - endfor -endfunction - -"Ask the active debugger to evaluate an expression -function! vebugger#std#eval(expression) - let l:debugger=vebugger#getActiveDebugger() - if !empty(l:debugger) && !empty(l:debugger.std_eval) - call l:debugger.std_eval(a:expression) - endif -endfunction - -"Ask the active debugger to execute a statement -function! vebugger#std#execute(statement) - let l:debugger=vebugger#getActiveDebugger() - if !empty(l:debugger) && !empty(l:debugger.std_eval) - call l:debugger.std_execute(a:statement) - endif + let l:debugger=vebugger#getActiveDebugger() + let l:debuggerState=empty(l:debugger) ? {} : l:debugger.state + let l:files=[] + for l:breakpoint in g:vebugger_breakpoints + if index(l:files,l:breakpoint.file)<0 + call add(l:files,l:breakpoint.file) + endif + if !empty(l:debugger) + call l:debugger.addWriteAction('std','breakpoints',extend({'action':'remove'},l:breakpoint)) + endif + endfor + if !empty(l:debugger) + call l:debugger.performWriteActions() + endif + let g:vebugger_breakpoints=[] + for l:file in l:files + call vebugger#std#updateMarksForFile(l:debuggerState,l:file) + endfor endfunction diff --git a/plugin/vebugger.vim b/plugin/vebugger.vim index 6f9449d..b78bcb5 100644 --- a/plugin/vebugger.vim +++ b/plugin/vebugger.vim @@ -1,25 +1,25 @@ -command! -nargs=1 VBGrawWrite call vebugger#writeLine() +command! -nargs=1 VBGrawWrite call vebugger#userAction('writeLine', ) command! -nargs=0 VBGkill call vebugger#killDebugger() -command! -nargs=0 VBGstepIn call vebugger#setWriteActionAndPerform('std','flow','stepin') -command! -nargs=0 VBGstepOver call vebugger#setWriteActionAndPerform('std','flow','stepover') -command! -nargs=0 VBGstepOut call vebugger#setWriteActionAndPerform('std','flow','stepout') -command! -nargs=0 VBGcontinue call vebugger#setWriteActionAndPerform('std','flow','continue') +command! -nargs=0 VBGstepIn call vebugger#userAction('setWriteActionAndPerform', 'std', 'flow', 'stepin') +command! -nargs=0 VBGstepOver call vebugger#userAction('setWriteActionAndPerform', 'std', 'flow', 'stepover') +command! -nargs=0 VBGstepOut call vebugger#userAction('setWriteActionAndPerform', 'std', 'flow', 'stepout') +command! -nargs=0 VBGcontinue call vebugger#userAction('setWriteActionAndPerform', 'std', 'flow', 'continue') -command! -nargs=0 VBGtoggleTerminalBuffer call vebugger#toggleTerminalBuffer() +command! -nargs=0 VBGtoggleTerminalBuffer call vebugger#userAction('toggleTerminalBuffer') command! -nargs=+ -complete=file VBGtoggleBreakpoint call vebugger#std#toggleBreakpoint() command! -nargs=0 VBGtoggleBreakpointThisLine call vebugger#std#toggleBreakpoint(expand('%:~:.'),line('.')) command! -nargs=0 VBGclearBreakpints call vebugger#std#clearBreakpoints() -command! -nargs=1 VBGeval call vebugger#std#eval() -command! -nargs=0 VBGevalWordUnderCursor call vebugger#std#eval(expand('')) -command! -nargs=1 VBGexecute call vebugger#std#execute() +command! -nargs=1 VBGeval call vebugger#userAction('std_eval', ) +command! -nargs=0 VBGevalWordUnderCursor call vebugger#userAction('std_eval', expand('')) +command! -nargs=1 VBGexecute call vebugger#userAction('std_execute', ) -command! -range -nargs=0 VBGevalSelectedText call vebugger#std#eval(vebugger#util#get_visual_selection()) -command! -range -nargs=0 VBGexecuteSelectedText call vebugger#std#execute(vebugger#util#get_visual_selection()) -command! -range -nargs=0 VBGrawWriteSelectedText call vebugger#writeLine(vebugger#util#get_visual_selection()) +command! -range -nargs=0 VBGevalSelectedText call vebugger#userAction('std_eval', vebugger#util#get_visual_selection()) +command! -range -nargs=0 VBGexecuteSelectedText call vebugger#userAction('std_execute', vebugger#util#get_visual_selection()) +command! -range -nargs=0 VBGrawWriteSelectedText call vebugger#userAction('writeLine', vebugger#util#get_visual_selection()) command! -nargs=+ -complete=file VBGstartGDB call vebugger#gdb#start([][0],{'args':[][1:]}) function! s:attachGDB(...) From e3c069b5b604455d9d4f27b375bd016fa1dbd095 Mon Sep 17 00:00:00 2001 From: IdanArye Date: Sat, 28 Feb 2015 19:37:54 +0200 Subject: [PATCH 05/47] Add hook for pre&post user actions --- autoload/vebugger.vim | 31 +++++++++++++++++++++++++++++++ plugin/vebugger.vim | 2 ++ 2 files changed, 33 insertions(+) diff --git a/autoload/vebugger.vim b/autoload/vebugger.vim index 1cd80c1..5831629 100644 --- a/autoload/vebugger.vim +++ b/autoload/vebugger.vim @@ -295,16 +295,47 @@ function! vebugger#killDebugger() endif endfunction +"Perform an action on the actvie debugger, and register that action function! vebugger#userAction(action, ...) if exists('s:debugger') if has_key(s:debugger, a:action) + let s:debugger.lastUserAction = { + \'action': a:action, + \'args': a:000} + + try + doautocmd User Vebugger_PreUserAction + catch + endtry + call call(s:debugger[a:action], a:000, s:debugger) + + try + doautocmd User Vebugger_PostUserAction + catch + endtry else throw 'Current debugger does not support action '.a:action endif endif endfunction +augroup vebugger_hooks + autocmd! + "Make a blank action hook to prevent 'No matching autocommands" warning + autocmd User Vebugger_* echo +augroup END + +"Repeat the last action performed on the active debugger +function! vebugger#repeatLastUserAction() + if exists('s:debugger') + if has_key(s:debugger, 'lastUserAction') + let l:lastUserAction = s:debugger.lastUserAction + call call(s:debugger[l:lastUserAction.action], l:lastUserAction.args, s:debugger) + endif + endif +endfunction + "Write a line to the currently active debugger function! vebugger#writeLine(line) if exists('s:debugger') diff --git a/plugin/vebugger.vim b/plugin/vebugger.vim index b78bcb5..1ef8746 100644 --- a/plugin/vebugger.vim +++ b/plugin/vebugger.vim @@ -1,5 +1,7 @@ +command! -nargs=0 VBGrepeat call vebugger#repeatLastUserAction() + command! -nargs=1 VBGrawWrite call vebugger#userAction('writeLine', ) command! -nargs=0 VBGkill call vebugger#killDebugger() From f98c830b8282fac2ffd7008c42076fbb9bf516ba Mon Sep 17 00:00:00 2001 From: IdanArye Date: Sun, 1 Mar 2015 21:32:20 +0200 Subject: [PATCH 06/47] Changed the Vebugger_*UserAction activation to use try...finally That way, errors in the event listeners will neither be swallowed nor will they prevent the user action from happening. --- autoload/vebugger.vim | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/autoload/vebugger.vim b/autoload/vebugger.vim index 5831629..422d99c 100644 --- a/autoload/vebugger.vim +++ b/autoload/vebugger.vim @@ -305,14 +305,9 @@ function! vebugger#userAction(action, ...) try doautocmd User Vebugger_PreUserAction - catch - endtry - - call call(s:debugger[a:action], a:000, s:debugger) - - try + finally + call call(s:debugger[a:action], a:000, s:debugger) doautocmd User Vebugger_PostUserAction - catch endtry else throw 'Current debugger does not support action '.a:action From bc0c05713dd79efec1e2b637a85555922a19a00a Mon Sep 17 00:00:00 2001 From: Kevin Brandon Date: Sat, 11 Apr 2015 02:10:03 -0700 Subject: [PATCH 07/47] Fixes issue #13 by defining a color group called BreakPoint. By default it reverses the color scheme for term, cterm, and gui --- autoload/vebugger/std.vim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/autoload/vebugger/std.vim b/autoload/vebugger/std.vim index d3e7364..d98758e 100644 --- a/autoload/vebugger/std.vim +++ b/autoload/vebugger/std.vim @@ -235,8 +235,10 @@ function! s:standardCloseHandlers.removeCurrentMarker(debugger) dict sign unplace 1 endfunction +highlight BreakPoint term=reverse cterm=reverse gui=reverse + sign define vebugger_current text=-> -sign define vebugger_breakpoint text=** linehl=ColorColumn +sign define vebugger_breakpoint text=** linehl=BreakPoint "Update all the marks(currently executed line and breakpoints) for a file function! vebugger#std#updateMarksForFile(state,filename) From df8e4ddbc9d8fc1156b83ceba6ce39e859df35d4 Mon Sep 17 00:00:00 2001 From: IdanArye Date: Sat, 11 Apr 2015 17:59:02 +0300 Subject: [PATCH 08/47] Check that the `BreakPoint` highlight style doesn't exist before redfining it --- autoload/vebugger/std.vim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/autoload/vebugger/std.vim b/autoload/vebugger/std.vim index d98758e..ef3c9e7 100644 --- a/autoload/vebugger/std.vim +++ b/autoload/vebugger/std.vim @@ -235,7 +235,9 @@ function! s:standardCloseHandlers.removeCurrentMarker(debugger) dict sign unplace 1 endfunction -highlight BreakPoint term=reverse cterm=reverse gui=reverse +if !hlexists('BreakPoint') + highlight BreakPoint term=reverse cterm=reverse gui=reverse +endif sign define vebugger_current text=-> sign define vebugger_breakpoint text=** linehl=BreakPoint From fe8685ad842591d151030c6e79d6f9ae5e48aba3 Mon Sep 17 00:00:00 2001 From: IdanArye Date: Wed, 15 Apr 2015 23:00:02 +0300 Subject: [PATCH 09/47] Close #13 only use BreakPoint highlight only if it's predefined --- autoload/vebugger/std.vim | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/autoload/vebugger/std.vim b/autoload/vebugger/std.vim index ef3c9e7..f14973c 100644 --- a/autoload/vebugger/std.vim +++ b/autoload/vebugger/std.vim @@ -235,12 +235,13 @@ function! s:standardCloseHandlers.removeCurrentMarker(debugger) dict sign unplace 1 endfunction -if !hlexists('BreakPoint') - highlight BreakPoint term=reverse cterm=reverse gui=reverse -endif - sign define vebugger_current text=-> -sign define vebugger_breakpoint text=** linehl=BreakPoint + +if hlexists('BreakPoint') + sign define vebugger_breakpoint text=** linehl=BreakPoint texthl=BreakPoint +else + sign define vebugger_breakpoint text=** linehl=ColorColumn texthl=ColorColumn +endif "Update all the marks(currently executed line and breakpoints) for a file function! vebugger#std#updateMarksForFile(state,filename) From d016e6aec0e171e9ae5978ca5ad29d48f7bce9c1 Mon Sep 17 00:00:00 2001 From: David Nguyen Date: Sat, 27 Jun 2015 13:03:59 +0200 Subject: [PATCH 10/47] Rename VBGclearBreakpints to VBGclearBreakpoints --- doc/vebugger.txt | 4 ++-- plugin/vebugger.vim | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/vebugger.txt b/doc/vebugger.txt index d5ba8d3..e60673a 100644 --- a/doc/vebugger.txt +++ b/doc/vebugger.txt @@ -253,7 +253,7 @@ MANAGE BREAKPOINTS *vebugger-breakpoints* *:VBGtoggleBreakpoint* Toggle a breakpoint. The file and line should be supplied as arguments. *:VBGtoggleBreakpointThisLine* Toggle a breakpoint for the current line. -*:VBGclearBreakpints* Clear all breakpoints. +*:VBGclearBreakpoints* Clear all breakpoints. EVALUATE EXPRESSIONS *vebugger-evalutate* @@ -294,7 +294,7 @@ O |:VBGstepOut| c |:VBGcontinue| b |:VBGtoggleBreakpointThisLine| -B |:VBGclearBreakpints| +B |:VBGclearBreakpoints| e |:VBGevalWordUnderCursor| in normal mode |:VBGevalSelectedText| in select mode diff --git a/plugin/vebugger.vim b/plugin/vebugger.vim index 1ef8746..ab51944 100644 --- a/plugin/vebugger.vim +++ b/plugin/vebugger.vim @@ -13,7 +13,7 @@ command! -nargs=0 VBGcontinue call vebugger#userAction('setWriteActionAndPerform command! -nargs=0 VBGtoggleTerminalBuffer call vebugger#userAction('toggleTerminalBuffer') command! -nargs=+ -complete=file VBGtoggleBreakpoint call vebugger#std#toggleBreakpoint() command! -nargs=0 VBGtoggleBreakpointThisLine call vebugger#std#toggleBreakpoint(expand('%:~:.'),line('.')) -command! -nargs=0 VBGclearBreakpints call vebugger#std#clearBreakpoints() +command! -nargs=0 VBGclearBreakpoints call vebugger#std#clearBreakpoints() command! -nargs=1 VBGeval call vebugger#userAction('std_eval', ) command! -nargs=0 VBGevalWordUnderCursor call vebugger#userAction('std_eval', expand('')) @@ -56,7 +56,7 @@ if exists('g:vebugger_leader') \'c':'VBGcontinue', \'t':'VBGtoggleTerminalBuffer', \'b':'VBGtoggleBreakpointThisLine', - \'B':'VBGclearBreakpints', + \'B':'VBGclearBreakpoints', \'e':'VBGevalWordUnderCursor', \'E':'exe "VBGeval ".input("VBG-Eval> ")', \'x':'exe "VBGexecute ".getline(".")', From 806d6228cc8d0eb3334e33669c0f4d5f41ab14bc Mon Sep 17 00:00:00 2001 From: David Nguyen Date: Sat, 27 Jun 2015 14:03:03 +0200 Subject: [PATCH 11/47] Close shell buffer when killing the debugger --- autoload/vebugger.vim | 1 + autoload/vebugger/std.vim | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/autoload/vebugger.vim b/autoload/vebugger.vim index c9d127e..d7b0938 100644 --- a/autoload/vebugger.vim +++ b/autoload/vebugger.vim @@ -289,6 +289,7 @@ function! vebugger#killDebugger() autocmd! augroup END if exists('s:debugger') + call vebugger#std#closeShellBuffer(s:debugger) call s:debugger.closeTerminalBuffer() call s:debugger.kill() unlet s:debugger diff --git a/autoload/vebugger/std.vim b/autoload/vebugger/std.vim index f14973c..e72ad15 100644 --- a/autoload/vebugger/std.vim +++ b/autoload/vebugger/std.vim @@ -101,6 +101,18 @@ function! vebugger#std#openShellBuffer(debugger) wincmd p endfunction +"Closes the shell buffer +function! vebugger#std#closeShellBuffer(debugger) + if has_key(a:debugger,'shellBuffer') + if -1 Date: Sat, 5 Sep 2015 12:45:04 +0700 Subject: [PATCH 12/47] Make package parsing work for groovy --- autoload/vebugger/jdb.vim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/autoload/vebugger/jdb.vim b/autoload/vebugger/jdb.vim index 612336c..2279c8b 100644 --- a/autoload/vebugger/jdb.vim +++ b/autoload/vebugger/jdb.vim @@ -114,7 +114,8 @@ endfunction function! s:getClassNameFromFile(filename) let l:className=fnamemodify(a:filename,':t:r') " Get only the name of the file, without path or extension for l:line in readfile(a:filename) - let l:matches=matchlist(l:line,'\vpackage\s+(%(\w|\.)+)\s*;') + " trailing ; is optional to make it work for groovy as well + let l:matches=matchlist(l:line,'\vpackage\s+(%(\w|\.)+)\s*;?') if 1 Date: Sat, 5 Sep 2015 22:15:14 +0700 Subject: [PATCH 13/47] Use tags when searching for a source file for jdb --- autoload/vebugger/jdb.vim | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/autoload/vebugger/jdb.vim b/autoload/vebugger/jdb.vim index 612336c..c763f75 100644 --- a/autoload/vebugger/jdb.vim +++ b/autoload/vebugger/jdb.vim @@ -56,7 +56,33 @@ function! vebugger#jdb#_readProgramOutput(pipeName,line,readResult,debugger) dic endif endfunction +function! s:getTagContainingString(tag, str) + let l:tags = taglist(a:tag) + if (len(l:tags) > 0) + for l:tag in l:tags + if (filereadable(l:tag.filename) && (len(a:str) == 0 || match(readfile(l:tag.filename), a:str))) + return l:tag + endif + endfor + endif + return {} +endfunction + function! s:findFolderFromStackTrace(src,nameFromStackTrace) + " Remove method name. + let l:canonicalClassName = strpart(a:nameFromStackTrace, 0, strridx(a:nameFromStackTrace, ".")) + " Remove package name. + let l:simpleClassName = strridx(l:canonicalClassName, ".") >= 0 ? strpart(l:canonicalClassName, strridx(l:canonicalClassName, ".")) : l:canonicalClassName + " Remove class name. + let l:package = strridx(l:canonicalClassName, ".") >= 0 ? strpart(l:canonicalClassName, 0, strridx(l:canonicalClassName, ".")) : "" + + " Now first try to find a tag for the class from the required package. + let l:classTag = s:getTagContainingString(l:simpleClassName, l:package) + if (has_key(l:classTag, "filename")) + return fnamemodify(l:classTag.filename, ":h") + endif + + " If no such tag was found, try to find it using the src path. let l:path=a:src for l:dirname in split(a:nameFromStackTrace,'\.') let l:nextPath=l:path.'/'.fnameescape(l:dirname) From a1027767d4fffc9bdb08912577854606e2162bfa Mon Sep 17 00:00:00 2001 From: Alexey Balchunas Date: Sat, 5 Sep 2015 22:15:14 +0700 Subject: [PATCH 14/47] The simple class name was calculated with prefixed '.' character --- autoload/vebugger/jdb.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/vebugger/jdb.vim b/autoload/vebugger/jdb.vim index d1daf3e..78ffed8 100644 --- a/autoload/vebugger/jdb.vim +++ b/autoload/vebugger/jdb.vim @@ -72,7 +72,7 @@ function! s:findFolderFromStackTrace(src,nameFromStackTrace) " Remove method name. let l:canonicalClassName = strpart(a:nameFromStackTrace, 0, strridx(a:nameFromStackTrace, ".")) " Remove package name. - let l:simpleClassName = strridx(l:canonicalClassName, ".") >= 0 ? strpart(l:canonicalClassName, strridx(l:canonicalClassName, ".")) : l:canonicalClassName + let l:simpleClassName = strridx(l:canonicalClassName, ".") >= 0 ? strpart(l:canonicalClassName, strridx(l:canonicalClassName, ".") + 1) : l:canonicalClassName " Remove class name. let l:package = strridx(l:canonicalClassName, ".") >= 0 ? strpart(l:canonicalClassName, 0, strridx(l:canonicalClassName, ".")) : "" From 30218447f83101171b046ef7191339ccf830d232 Mon Sep 17 00:00:00 2001 From: Alexey Balchunas Date: Sat, 5 Sep 2015 23:08:29 +0700 Subject: [PATCH 15/47] added an option to enable usage of tags --- autoload/vebugger/jdb.vim | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/autoload/vebugger/jdb.vim b/autoload/vebugger/jdb.vim index 78ffed8..a674a02 100644 --- a/autoload/vebugger/jdb.vim +++ b/autoload/vebugger/jdb.vim @@ -76,10 +76,12 @@ function! s:findFolderFromStackTrace(src,nameFromStackTrace) " Remove class name. let l:package = strridx(l:canonicalClassName, ".") >= 0 ? strpart(l:canonicalClassName, 0, strridx(l:canonicalClassName, ".")) : "" - " Now first try to find a tag for the class from the required package. - let l:classTag = s:getTagContainingString(l:simpleClassName, l:package) - if (has_key(l:classTag, "filename")) - return fnamemodify(l:classTag.filename, ":h") + if exists('g:vebugger_use_tags') && g:vebugger_use_tags + " Now first try to find a tag for the class from the required package. + let l:classTag = s:getTagContainingString(l:simpleClassName, l:package) + if (has_key(l:classTag, "filename")) + return fnamemodify(l:classTag.filename, ":h") + endif endif " If no such tag was found, try to find it using the src path. From d6513dfb880101e1ff275ab75904ef1049ad2c1c Mon Sep 17 00:00:00 2001 From: Alexey Balchunas Date: Sat, 5 Sep 2015 23:38:24 +0700 Subject: [PATCH 16/47] Fixed a critical bug in source searching using tags --- autoload/vebugger/jdb.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/vebugger/jdb.vim b/autoload/vebugger/jdb.vim index a674a02..432f7dd 100644 --- a/autoload/vebugger/jdb.vim +++ b/autoload/vebugger/jdb.vim @@ -60,7 +60,7 @@ function! s:getTagContainingString(tag, str) let l:tags = taglist(a:tag) if (len(l:tags) > 0) for l:tag in l:tags - if (filereadable(l:tag.filename) && (len(a:str) == 0 || match(readfile(l:tag.filename), a:str))) + if (filereadable(l:tag.filename) && match(readfile(l:tag.filename), a:str) >= 0) return l:tag endif endfor From 08b7b5dabdf491ecf4fa38db3c9fd1cd4f9540ca Mon Sep 17 00:00:00 2001 From: Alexey Balchunas Date: Sun, 6 Sep 2015 09:49:47 +0700 Subject: [PATCH 17/47] added documentation about the 'g:vebugger_use_tags' option --- doc/vebugger.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/vebugger.txt b/doc/vebugger.txt index e60673a..d3738d4 100644 --- a/doc/vebugger.txt +++ b/doc/vebugger.txt @@ -101,6 +101,14 @@ Example: > let g:vebugger_view_source_cmd='edit' < +Some debuggers (currently jdb only) may use vim tags to find required source +files. This is disabled by default, to enable this set *g:vebugger_use_tags* +option: + +Example: > + let g:vebugger_use_tags=1 +< + LAUNCHING DEBUGGERS *vebugger-launching* A debugger's implementation is responsible for starting it. The standard is to From b9517ade8c5b556a6aa3d35c256e61e37085d9d8 Mon Sep 17 00:00:00 2001 From: Alexey Balchunas Date: Sun, 6 Sep 2015 10:53:44 +0700 Subject: [PATCH 18/47] Do not use tags for callstack, only for current location. Otherwise, it's unusably slow. --- autoload/vebugger/jdb.vim | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/autoload/vebugger/jdb.vim b/autoload/vebugger/jdb.vim index 432f7dd..a2c9ed2 100644 --- a/autoload/vebugger/jdb.vim +++ b/autoload/vebugger/jdb.vim @@ -68,7 +68,7 @@ function! s:getTagContainingString(tag, str) return {} endfunction -function! s:findFolderFromStackTrace(src,nameFromStackTrace) +function! s:findFolderFromStackTrace(src,nameFromStackTrace,frameNumber) " Remove method name. let l:canonicalClassName = strpart(a:nameFromStackTrace, 0, strridx(a:nameFromStackTrace, ".")) " Remove package name. @@ -76,7 +76,9 @@ function! s:findFolderFromStackTrace(src,nameFromStackTrace) " Remove class name. let l:package = strridx(l:canonicalClassName, ".") >= 0 ? strpart(l:canonicalClassName, 0, strridx(l:canonicalClassName, ".")) : "" - if exists('g:vebugger_use_tags') && g:vebugger_use_tags + " We don't really use callstack, so we use tags only for the current location. + " Otherwise it makes everything too slow. + if exists('g:vebugger_use_tags') && g:vebugger_use_tags && a:frameNumber == 1 " Now first try to find a tag for the class from the required package. let l:classTag = s:getTagContainingString(l:simpleClassName, l:package) if (has_key(l:classTag, "filename")) @@ -100,9 +102,9 @@ function! vebugger#jdb#_readWhere(pipeName,line,readResult,debugger) if 'out'==a:pipeName let l:matches=matchlist(a:line,'\v\s*\[(\d+)]\s*(\S+)\s*\(([^:]*):(\d*)\)') if 4 Date: Fri, 6 Nov 2015 22:30:02 +0200 Subject: [PATCH 19/47] Fix #23 - Remove usage of `bufexists` `bufexists` can't handle the home directory(`~`). Instead use `bufnr` and `bufwinnr`, which are more appropriate. Also, I've decided to use `bufwinnr` instead of `bufnr` for checking if the file exists before loading it with `g:vebugger_view_source_cmd`, so it'll use `g:vebugger_view_source_cmd` if no window displays the buffer - even if the buffer is loaded. This fixes an inconsistency that was before, that `g:vebugger_view_source_cmd` would get invoked only if the file has no buffer loaded, if there is a buffer loaded it'll jump to it from the current window. --- autoload/vebugger/std.vim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/vebugger/std.vim b/autoload/vebugger/std.vim index e72ad15..724ec4d 100644 --- a/autoload/vebugger/std.vim +++ b/autoload/vebugger/std.vim @@ -180,7 +180,7 @@ function! s:standardThinkHandlers.moveToCurrentLine(readResult,debugger) dict exe 'sign unplace 1 file='.fnameescape(fnamemodify(a:debugger.state.std.location.file,':p')) endif let a:debugger.state.std.location=deepcopy(a:readResult.std.location) - if !bufexists(a:readResult.std.location.file) + if -1 == bufwinnr(a:readResult.std.location.file) exe get(g:, 'vebugger_view_source_cmd', 'new').' '.(a:readResult.std.location.file) endif call vebugger#std#updateMarksForFile(a:debugger.state,a:readResult.std.location.file) @@ -258,7 +258,7 @@ endif "Update all the marks(currently executed line and breakpoints) for a file function! vebugger#std#updateMarksForFile(state,filename) let l:filename=fnamemodify(a:filename,":p") - if bufexists(l:filename) + if -1 < bufnr(l:filename) exe 'sign unplace 1 file='.fnameescape(fnamemodify(l:filename,':p')) exe 'sign unplace 2 file='.fnameescape(fnamemodify(l:filename,':p')) From fa84d5c0a55edf20b96e2fa1d47f45b8df4bc34a Mon Sep 17 00:00:00 2001 From: Idan Arye Date: Tue, 26 Jan 2016 19:21:19 +0200 Subject: [PATCH 20/47] Fix #24 - typo: `Ternimal` -> `Terminal` --- autoload/vebugger.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/vebugger.vim b/autoload/vebugger.vim index d7b0938..d859d57 100644 --- a/autoload/vebugger.vim +++ b/autoload/vebugger.vim @@ -108,7 +108,7 @@ function! s:f_debugger.showTerminalBuffer() dict setlocal buftype=nofile setlocal bufhidden=wipe let self.terminalBuffer=bufnr('') - silent file Vebugger:Ternimal + silent file Vebugger:Terminal wincmd p endfunction From 3ef3f45016773a9d7bfbb5cd90975db4a6fd938d Mon Sep 17 00:00:00 2001 From: IdanArye Date: Wed, 17 Feb 2016 00:32:15 +0200 Subject: [PATCH 21/47] Fix #25 - pre-process GDB's MI output --- autoload/vebugger.vim | 50 ++++++++++++++--------------- autoload/vebugger/gdb.vim | 67 +++++++++++++++++++++++++++++++++++---- autoload/vebugger/std.vim | 21 ++++++++++++ doc/vebugger.txt | 23 ++++++++++++++ 4 files changed, 130 insertions(+), 31 deletions(-) diff --git a/autoload/vebugger.vim b/autoload/vebugger.vim index d859d57..bc863df 100644 --- a/autoload/vebugger.vim +++ b/autoload/vebugger.vim @@ -1,21 +1,13 @@ -"Read and return all new lines from a Vebugger pipe object. -function! s:readNewLinesFromPipe(pipeObject) - "read - let l:text=a:pipeObject.pipe.read(1000,0) - while 0 + let l:debugger.pipes.out.bufferer = function('g:myCustomBufferer') +< From 78893b6e5f65e93bca200ff698061601dabe04d6 Mon Sep 17 00:00:00 2001 From: IdanArye Date: Sat, 20 Feb 2016 18:02:00 +0200 Subject: [PATCH 22/47] Fix #25 set `print pretty off` and `print array off` in GDB --- autoload/vebugger/gdb.vim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/vebugger/gdb.vim b/autoload/vebugger/gdb.vim index f9584cb..f94ddce 100644 --- a/autoload/vebugger/gdb.vim +++ b/autoload/vebugger/gdb.vim @@ -7,6 +7,8 @@ function! vebugger#gdb#start(binaryFile,args) let l:debugger.pipes.err.annotation = "err&prg\t\t" call l:debugger.writeLine("set width 0") + call l:debugger.writeLine("set print pretty off") + call l:debugger.writeLine("set print array off") call l:debugger.writeLine("define hook-stop\nwhere\nend") if get(a:args,'pid') "Attach to process From c1913b39940f78b6a04f13346e675c2c993ded31 Mon Sep 17 00:00:00 2001 From: Ingo Heimbach Date: Fri, 4 Nov 2016 17:42:15 +0100 Subject: [PATCH 23/47] Bugfix: The PDB where function is not aware of step outs --- autoload/vebugger/pdb.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/vebugger/pdb.vim b/autoload/vebugger/pdb.vim index 54f4cf5..119cd68 100644 --- a/autoload/vebugger/pdb.vim +++ b/autoload/vebugger/pdb.vim @@ -56,7 +56,7 @@ endfunction function! vebugger#pdb#_readWhere(pipeName,line,readResult,debugger) if 'out'==a:pipeName - let l:matches=matchlist(a:line,'\v^\> (.+)\((\d+)\).*\(\)$') + let l:matches=matchlist(a:line,'\v^\> (.+)\((\d+)\).*\(\)%(-\>.*)?$') if 2 Date: Tue, 1 Nov 2016 15:19:49 +0100 Subject: [PATCH 24/47] Added the lldb debugger via the lldb python api --- autoload/vebugger/lldb.vim | 139 +++++++++++++++++++++++++ autoload/vebugger/lldb_wrapper.py | 165 ++++++++++++++++++++++++++++++ plugin/vebugger.vim | 18 ++++ 3 files changed, 322 insertions(+) create mode 100644 autoload/vebugger/lldb.vim create mode 100755 autoload/vebugger/lldb_wrapper.py diff --git a/autoload/vebugger/lldb.vim b/autoload/vebugger/lldb.vim new file mode 100644 index 0000000..c97aa1c --- /dev/null +++ b/autoload/vebugger/lldb.vim @@ -0,0 +1,139 @@ +let s:script_dir_path=expand(':p:h') + +function! vebugger#lldb#start(binaryFile,args) + let l:debuggerExe=vebugger#util#getToolFullPath('python2',get(a:args,'version'),'python2') + let l:debugger=vebugger#std#startDebugger(shellescape(l:debuggerExe) + \.' '.s:script_dir_path.'/lldb_wrapper.py '.fnameescape(a:binaryFile)) + + let l:debugger.state.lldb={} + + if get(a:args,'pid') "Attach to process + call l:debugger.writeLine('process attach --pid '.string(a:args.pid)) + elseif has_key(a:args,'con') "Attach to lldbserver + call l:debugger.writeLine('platform connect connect://'.a:args.con) + else + call l:debugger.writeLine('settings set target.run-args '.vebugger#util#commandLineArgsForProgram(a:args)) + if !has('win32') + call vebugger#std#openShellBuffer(l:debugger) + endif + + " TODO: remove 'and false'; add a temporary breakpoint to lldb + if has_key(a:args,'entry') && 0 + " call l:debugger.writeLine('tbreak '.a:args.entry) + " call l:debugger.writeLine('run') + else + call l:debugger.writeLine('breakpoint set --name main') + call l:debugger.writeLine('process launch') + endif + endif + + + call l:debugger.addReadHandler(function('vebugger#lldb#_readProgramOutput')) + call l:debugger.addReadHandler(function('vebugger#lldb#_readWhere')) + call l:debugger.addReadHandler(function('vebugger#lldb#_readFinish')) + call l:debugger.addReadHandler(function('vebugger#lldb#_readEvaluatedExpressions')) + + call l:debugger.setWriteHandler('std','flow',function('vebugger#lldb#_writeFlow')) + call l:debugger.setWriteHandler('std','breakpoints',function('vebugger#lldb#_writeBreakpoints')) + call l:debugger.setWriteHandler('std','closeDebugger',function('vebugger#lldb#_closeDebugger')) + call l:debugger.setWriteHandler('std','evaluateExpressions',function('vebugger#lldb#_requestEvaluateExpression')) + call l:debugger.setWriteHandler('std','executeStatements',function('vebugger#lldb#_executeStatements')) + + call l:debugger.generateWriteActionsFromTemplate() + + call l:debugger.std_addAllBreakpointActions(g:vebugger_breakpoints) + + return l:debugger +endfunction + +function! vebugger#lldb#_readProgramOutput(pipeName,line,readResult,debugger) + if 'out'==a:pipeName + \&&(a:line=~'\v^program_stdout:' + \||a:line=~'\v^program_stderr:') + let a:readResult.std.programOutput={'line':strpart(a:line, 16)} + endif +endfunction + +function! vebugger#lldb#_readWhere(pipeName,line,readResult,debugger) + if 'out'==a:pipeName + \&&a:line=~'\v^debugger_output:' + let l:matches=matchlist(a:line,'\v^debugger_output:\s\*\s([^:]+):(\d+)') + if 2) +command! -nargs=+ -complete=file VBGstartLLDB call vebugger#lldb#start([][0],{'args':[][1:]}) +function! s:attachLLDB(...) + if 1 == a:0 + let l:processId=vebugger#util#selectProcessOfFile(a:1) + if 0 < l:processId + call vebugger#lldb#start(a:1, {'pid': l:processId}) + endif + elseif 2 == a:0 + if a:2 =~ '\v^\d+$' + call vebugger#lldb#start(a:1,{'pid': str2nr(a:2)}) + else + call vebugger#lldb#start(a:1, {'con': a:2}) + endif + else + throw "Can't call VBGattachLLDB with ".a:0." arguments" + endif +endfunction +command! -nargs=+ -complete=file VBGattachLLDB call s:attachLLDB() command! -nargs=+ -complete=file VBGstartRDebug call vebugger#rdebug#start([][0],{'args':[][1:]}) command! -nargs=+ -complete=file VBGstartPDB call vebugger#pdb#start([][0],{'args':[][1:]}) command! -nargs=+ -complete=file VBGstartPDB2 call vebugger#pdb#start([][0],{'args':[][1:],'version':'2'}) From cd82aea8207dca024604611c2b947e42b8bee5cb Mon Sep 17 00:00:00 2001 From: Ingo Heimbach Date: Wed, 2 Nov 2016 13:43:16 +0100 Subject: [PATCH 25/47] Added macOS compatibility for the lldb extension --- autoload/vebugger/lldb.vim | 2 +- autoload/vebugger/lldb_wrapper.py | 62 +++++++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/autoload/vebugger/lldb.vim b/autoload/vebugger/lldb.vim index c97aa1c..252e613 100644 --- a/autoload/vebugger/lldb.vim +++ b/autoload/vebugger/lldb.vim @@ -1,7 +1,7 @@ let s:script_dir_path=expand(':p:h') function! vebugger#lldb#start(binaryFile,args) - let l:debuggerExe=vebugger#util#getToolFullPath('python2',get(a:args,'version'),'python2') + let l:debuggerExe=vebugger#util#getToolFullPath('python',get(a:args,'version'),'python2') let l:debugger=vebugger#std#startDebugger(shellescape(l:debuggerExe) \.' '.s:script_dir_path.'/lldb_wrapper.py '.fnameescape(a:binaryFile)) diff --git a/autoload/vebugger/lldb_wrapper.py b/autoload/vebugger/lldb_wrapper.py index a44e66d..b69cfab 100755 --- a/autoload/vebugger/lldb_wrapper.py +++ b/autoload/vebugger/lldb_wrapper.py @@ -7,9 +7,47 @@ from __future__ import print_function from __future__ import unicode_literals -import lldb +import os.path +import platform +import subprocess import sys +try: + # Just try for LLDB in case PYTHONPATH is already correctly setup + import lldb +except ImportError: + lldb_python_dirs = [] + # lldb is not in the PYTHONPATH, try some defaults for the current platform + platform_system = platform.system() + if platform_system == 'Darwin': + # On Darwin, try the currently selected Xcode directory + try: + xcode_dir = subprocess.check_output(['xcode-select', '--print-path']) + except subprocess.CalledProcessError: + xcode_dir = None + if xcode_dir: + lldb_python_dirs.append( + os.path.realpath( + os.path.join(xcode_dir, '../SharedFrameworks/LLDB.framework/Versions/A/Resources/Python') + ) + ) + lldb_python_dirs.append( + '/Library/Developer/CommandLineTools/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python' + ) + for lldb_python_dir in lldb_python_dirs: + if os.path.exists(lldb_python_dir): + if lldb_python_dir not in sys.path: + sys.path.append(lldb_python_dir) + try: + import lldb + except ImportError: + pass + else: + break + else: + sys.stderr.write('Error: could not locate the "lldb" module, please set PYTHONPATH correctly\n') + sys.exit(1) + class NoCustomCommandError(Exception): pass @@ -98,16 +136,26 @@ class Debugger(object): @property def program_stdout(self): - stdout = [self._process.GetSTDOUT(1024)] - while stdout[-1]: - stdout.append(self._process.GetSTDOUT(1024)) + stdout = [] + has_text = True + while has_text: + text = self._process.GetSTDOUT(1024) + if text: + stdout.append(text) + else: + has_text = False return ''.join(stdout) @property def program_stderr(self): - stderr = [self._process.GetSTDERR(1024)] - while stderr[-1]: - stderr.append(self._process.GetSTDERR(1024)) + stderr = [] + has_text = True + while has_text: + text = self._process.GetSTDERR(1024) + if text: + stderr.append(text) + else: + has_text = False return ''.join(stderr) @property From 5187166c443a7437fd27e8b16a8a501b7917d2f4 Mon Sep 17 00:00:00 2001 From: Ingo Heimbach Date: Wed, 2 Nov 2016 13:49:14 +0100 Subject: [PATCH 26/47] ~/.lldbinit is executed --- autoload/vebugger/lldb_wrapper.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/autoload/vebugger/lldb_wrapper.py b/autoload/vebugger/lldb_wrapper.py index b69cfab..075c379 100755 --- a/autoload/vebugger/lldb_wrapper.py +++ b/autoload/vebugger/lldb_wrapper.py @@ -7,7 +7,7 @@ from __future__ import print_function from __future__ import unicode_literals -import os.path +import os import platform import subprocess import sys @@ -187,6 +187,13 @@ def main(): debugger = Debugger(executable) # set debugger options + # -> first read lldbinit + try: + with open(os.path.expanduser('~/.lldbinit')) as f: + for line in f: + debugger.run_command(line) + except IOError: + pass debugger.run_command('settings set thread-format ${file.fullpath}:${line.number}') debugger.run_command('settings set auto-confirm 1') From f5682be0e028da2272675d52f5cdf4f1163c4c0a Mon Sep 17 00:00:00 2001 From: Ingo Heimbach Date: Wed, 2 Nov 2016 15:21:36 +0100 Subject: [PATCH 27/47] Updated the documentation for LLDB --- README.md | 1 + doc/vebugger.txt | 45 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 6c3589a..77afe82 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Vebugger is built as a generic framework for building frontends for interactive shell debugger, and comes with implementations for: * GDB - doesn't need introdcution... + * LLDB - debugger based on LLVM for C-family languages * JDB - a Java debugger * Mdbg - a .NET debugger(Windows only) * PDB - a Python module for debugging Python scripts diff --git a/doc/vebugger.txt b/doc/vebugger.txt index 7f781a5..73aa505 100644 --- a/doc/vebugger.txt +++ b/doc/vebugger.txt @@ -20,6 +20,7 @@ supports: Vebugger is built as a generic framework for building frontends for interactive shell debugger, and comes with implementations for: * GDB - doesn't need introdcution... +* LLDB - debugger based on LLVM for C-family languages * JDB - a Java debugger * Mdbg - a .NET debugger(Windows only) * PDB - a Python module for debugging Python scripts @@ -76,14 +77,17 @@ Example: > If a debugger is not in the PATH you can set the direct path to it by setting g:vebugger_path_XXX, where XXX is the executable used for the debugger: -*g:vebugger_path_gdb* defaults to "gdb" -*g:vebugger_path_jdb* defaults to "jdb" -*g:vebugger_path_mdbg* defaults to "Mdbg.exe" -*g:vebugger_path_python* defaults to "python" -*g:vebugger_path_ruby* defaults to "ruby" +*g:vebugger_path_gdb* defaults to "gdb" +*g:vebugger_path_python_lldb* defaults to "python2" +*g:vebugger_path_jdb* defaults to "jdb" +*g:vebugger_path_mdbg* defaults to "Mdbg.exe" +*g:vebugger_path_python* defaults to "python" +*g:vebugger_path_ruby* defaults to "ruby" -Notice that for PDB and RDebug you use "python" and "ruby", since the debugger -is actually a module bundled in the interpreter. +Notice that for LLDB, PDB and RDebug you use "python_lldb", "python" and +"ruby", since the debugger is actually a module bundled in the interpreter +(LLDB is called by a python wrapper because the LLDB executable has no +machine interface like GDB to interact with). You can set multiple versions for each debugger, by appending the version name to the debugger name with "_". These versions will be used when the "version" @@ -153,6 +157,33 @@ attach to or the URL for a GDB-server to connect to. The *VBGstartGDBForD* command is the same as VBGstartGDB but for Dlang programs. + +LAUNCHING LLDB *vebugger-lldb* + +LLDB can be launched with *vebugger#lldb#start* +> + call vebugger#lldb#start('a.out',{'args':['hello','world']}) +< + +The supported extra arguments are: +* "args": Command line arguments for the debugged program +* "pid": Process id to attach to +You can't specify both "args" and "pid". + +LLDB can also be launched with the *VBGstartLLDB* command: +> + VBGstartLLDB a.out hello world +< +The *VBGattachLLDB* command searches for processes launched from the EXE to +attach to, and attaches to them: +> + VBGattachLLDB a.out +< + +VBGattachLLDB accepts as a second argument the process ID of the process to +attach to. + + LAUNCHING JDB *vebugger-jdb* JDB is launched with *vebugger#jdb#start* From c7304dc1f1fcea98f211f50cbafe30f6f97bf81a Mon Sep 17 00:00:00 2001 From: Ingo Heimbach Date: Wed, 2 Nov 2016 21:35:00 +0100 Subject: [PATCH 28/47] LLDB only uses the python interpreter stored in "g:vebugger_path_python_lldb" Updated the documentation to explain why a special python variable is needed for LLDB --- autoload/vebugger/lldb.vim | 2 +- doc/vebugger.txt | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/autoload/vebugger/lldb.vim b/autoload/vebugger/lldb.vim index 252e613..5ad50a6 100644 --- a/autoload/vebugger/lldb.vim +++ b/autoload/vebugger/lldb.vim @@ -1,7 +1,7 @@ let s:script_dir_path=expand(':p:h') function! vebugger#lldb#start(binaryFile,args) - let l:debuggerExe=vebugger#util#getToolFullPath('python',get(a:args,'version'),'python2') + let l:debuggerExe=vebugger#util#getToolFullPath('python','lldb','python2') let l:debugger=vebugger#std#startDebugger(shellescape(l:debuggerExe) \.' '.s:script_dir_path.'/lldb_wrapper.py '.fnameescape(a:binaryFile)) diff --git a/doc/vebugger.txt b/doc/vebugger.txt index 73aa505..5a7eeb5 100644 --- a/doc/vebugger.txt +++ b/doc/vebugger.txt @@ -89,15 +89,20 @@ Notice that for LLDB, PDB and RDebug you use "python_lldb", "python" and (LLDB is called by a python wrapper because the LLDB executable has no machine interface like GDB to interact with). -You can set multiple versions for each debugger, by appending the version name -to the debugger name with "_". These versions will be used when the "version" -argument is supplied when running the debugger: +You can set multiple versions for each debugger (except LLDB), by appending +the version name to the debugger name with "_". These versions will be used +when the "version" argument is supplied when running the debugger: *g:vebugger_path_python_2* defaults to "python2" *g:vebugger_path_python_3* defaults to "python3" *g:vebugger_path_mdbg_32* No default - use it for the 32bit version of Mdbg *g:vebugger_path_mdbg_64* No default - use it for the 64bit version of Mdbg +For LLDB a special python variable is needed ("g:vebugger_path_python_lldb") +since the lldb python api is only python 2 compatible. So, it is possible to +use a python 2 interpreter for LLDB and another python version for PDB at +the same time. + When stepping into functions in unopened files, they are opened with :new by default. This can be configured by setting *g:vebugger_view_source_cmd* From d78fa68a723e57a1eba6f4863461074c90553400 Mon Sep 17 00:00:00 2001 From: Ingo Heimbach Date: Fri, 4 Nov 2016 16:55:34 +0100 Subject: [PATCH 29/47] Improved locating the currently debugged program position (the old algorithm had problems with double frees for example) --- autoload/vebugger/lldb.vim | 4 +-- autoload/vebugger/lldb_wrapper.py | 55 ++++++++++++++++++++++++------- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/autoload/vebugger/lldb.vim b/autoload/vebugger/lldb.vim index 5ad50a6..da77faa 100644 --- a/autoload/vebugger/lldb.vim +++ b/autoload/vebugger/lldb.vim @@ -56,8 +56,8 @@ endfunction function! vebugger#lldb#_readWhere(pipeName,line,readResult,debugger) if 'out'==a:pipeName - \&&a:line=~'\v^debugger_output:' - let l:matches=matchlist(a:line,'\v^debugger_output:\s\*\s([^:]+):(\d+)') + \&&a:line=~'\v^where:' + let l:matches=matchlist(a:line,'\v^where:\s([^:]+):(\d+)') if 2 first read lldbinit + try: + with open(os.path.expanduser('~/.lldbinit')) as f: + for line in f: + self.run_command(line) + except IOError: + pass + self.run_command('settings set frame-format frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{ at:${line.file.fullpath}:${line.number}}\n') + self.run_command('settings set auto-confirm 1') def run_command(self, commandline): if self._is_custom_command(commandline): @@ -134,6 +152,29 @@ class Debugger(object): else: return '' + @property + def where(self): + def extract_where(backtrace): + where = None + pattern = re.compile('at:([^:]+):(\d+)') + backtrace_lines = backtrace.split('\n') + for line in backtrace_lines: + match_obj = pattern.search(line) + if match_obj: + filepath = match_obj.group(1) + linenumber = int(match_obj.group(2)) + if os.access(filepath, os.R_OK): + where = FilePosition(filepath, linenumber) + break + return where + + where = None + self.run_command('bt') + debugger_output = self.debugger_output + if debugger_output is not None: + where = extract_where(debugger_output) + return where + @property def program_stdout(self): stdout = [] @@ -186,17 +227,6 @@ def main(): executable = sys.argv[1] debugger = Debugger(executable) - # set debugger options - # -> first read lldbinit - try: - with open(os.path.expanduser('~/.lldbinit')) as f: - for line in f: - debugger.run_command(line) - except IOError: - pass - debugger.run_command('settings set thread-format ${file.fullpath}:${line.number}') - debugger.run_command('settings set auto-confirm 1') - try: while True: line = raw_input() @@ -211,6 +241,9 @@ def main(): if program_stderr: print(prefix_output(program_stderr, 'program_stderr: ')) print(prefix_output(debugger.debugger_output, 'debugger_output: ')) + where = debugger.where + if where: + print(prefix_output('{:s}:{:d}'.format(where.filepath, where.linenumber), 'where: ')) print(prefix_output(debugger.program_state, 'program_state: ')) except EOFError: print('Exiting') From e684fdffd951215dd80e16eb625f01d802548e64 Mon Sep 17 00:00:00 2001 From: Ingo Heimbach Date: Fri, 6 Jan 2017 23:01:30 +0100 Subject: [PATCH 30/47] Use vim 8 timers for continuous checking of debugger output --- autoload/vebugger.vim | 44 ++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/autoload/vebugger.vim b/autoload/vebugger.vim index bc863df..1c3871a 100644 --- a/autoload/vebugger.vim +++ b/autoload/vebugger.vim @@ -17,7 +17,9 @@ function! s:f_debugger.kill() dict if self.shell.is_valid call self.addLineToTerminal('','== DEBUGGER TERMINATED ==') endif - let &updatetime=self.prevUpdateTime + if !has('timers') + let &updatetime=self.prevUpdateTime + endif call self.shell.kill(15) if exists('s:debugger') for l:closeHandler in s:debugger.closeHandlers @@ -54,7 +56,9 @@ function! s:f_debugger.invokeReading() dict \|| 'error'==l:checkpid[0] call self.kill() endif - call feedkeys("f\e", '\n') " Make sure the CursorHold event is refired even if the user does nothing + if !has('timers') + call feedkeys("f\e", '\n') " Make sure the CursorHold event is refired even if the user does nothing + endif endfunction "Handle a single line from the debugger's interactive shell @@ -262,12 +266,19 @@ function! vebugger#createDebugger(command) let l:debugger.writeHandlers={} let l:debugger.closeHandlers=[] - let l:debugger.prevUpdateTime=&updatetime + if !has('timers') + let l:debugger.prevUpdateTime=&updatetime + set updatetime=500 + endif - set updatetime=500 return l:debugger endfunction +if has('timers') + function! s:readingTimerCallback(timerId) + call s:debugger.invokeReading() + endfunction +endif "Create a debugger and set it as the currently active debugger function! vebugger#startDebugger(command) @@ -275,19 +286,30 @@ function! vebugger#startDebugger(command) let s:debugger=vebugger#createDebugger(a:command) - augroup vebugger_shell - autocmd! - autocmd CursorHold * call s:debugger.invokeReading() - augroup END + if has('timers') + let s:timerId = timer_start(500, function('s:readingTimerCallback'), {'repeat': -1}) + else + augroup vebugger_shell + autocmd! + autocmd CursorHold * call s:debugger.invokeReading() + augroup END + endif return s:debugger endfunction "Terminate the currently active debugger function! vebugger#killDebugger() - augroup vebugger_shell - autocmd! - augroup END + if has('timers') + if exists('s:timerId') + call timer_stop(s:timerId) + unlet s:timerId + endif + else + augroup vebugger_shell + autocmd! + augroup END + endif if exists('s:debugger') call vebugger#std#closeShellBuffer(s:debugger) call s:debugger.closeTerminalBuffer() From a2e2dcd612621c3b35dc2f0fb6d4b9c8f60acd16 Mon Sep 17 00:00:00 2001 From: Ingo Heimbach Date: Sun, 22 Jan 2017 12:39:06 +0100 Subject: [PATCH 31/47] Use feedkeys for echoing evaluated expressions Echo commands in vim 8 timer handlers do not wait for the user to confirm. Echoing via feedkeys circumvents this problem. --- autoload/vebugger/std.vim | 42 ++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/autoload/vebugger/std.vim b/autoload/vebugger/std.vim index a3273ed..284bb7a 100644 --- a/autoload/vebugger/std.vim +++ b/autoload/vebugger/std.vim @@ -226,20 +226,52 @@ function! s:standardThinkHandlers.updateCallStack(readResult,debugger) dict endif endfunction +"Helper print function; when using vim timers feedkeys ensures that messages +"can be confirmend by the user. +function! s:printWithFeedKeys(evaluatedExpression) + if empty(get(a:evaluatedExpression,'expression')) + let l:echo = a:evaluatedExpression.value + else + let l:echo = a:evaluatedExpression.expression.': '.a:evaluatedExpression.value + endif + let l:echoLines = split(l:echo, '\r\n\|\n\|\r') + if len(l:echoLines) == 1 + call add(l:echoLines, '') + endif + + if has('timers') + " Convert to an expression we can use with feedkeys. + " string(l:echo) won't do because it uses single-quotes which + " do not escape newlines + let l:echoJoinExpr = 'join('.string(l:echoLines).', "\n")' + + let l:echoKeys = ':echo '.l:echoJoinExpr."\" + if mode() == 'n' + " Call echo normaly + call feedkeys(l:echoKeys) + elseif mode() == 'i' + " Execute command in insert mode + call feedkeys("\".l:echoKeys) + endif + " NOTE: Other modes are not supported + else + " Without timer support, feedkeys won't work and we have + " to echo directly + echo join(l:echoLines, "\n") + endif +endfunction + "Print an expression that it's evaluation was previously requested function! s:standardThinkHandlers.printEvaluatedExpression(readResult,debugger) dict let l:evaluatedExpression=a:readResult.std.evaluatedExpression if !empty(l:evaluatedExpression) - if empty(get(l:evaluatedExpression,'expression')) - echo l:evaluatedExpression.value."\n" - else + if !empty(get(l:evaluatedExpression,'expression')) let l:index=index(a:debugger.state.std.evaluateExpressions,l:evaluatedExpression.expression) if 0<=l:index call remove(a:debugger.state.std.evaluateExpressions,l:index) - echo l:evaluatedExpression.expression.': '.l:evaluatedExpression.value."\n" - let g:echo=l:evaluatedExpression.expression.': '.l:evaluatedExpression.value."\n" endif endif + call s:printWithFeedKeys(l:evaluatedExpression) call a:debugger.addWriteAction('std','removeAfterDisplayed',a:readResult) endif endfunction From cc43abe32327f95601138bf893717231c85feb4a Mon Sep 17 00:00:00 2001 From: IdanArye Date: Mon, 5 Jun 2017 01:27:18 +0300 Subject: [PATCH 32/47] Fix #39 - make non-relative paths not use `~` --- plugin/vebugger.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/vebugger.vim b/plugin/vebugger.vim index 451b428..23d7dd5 100644 --- a/plugin/vebugger.vim +++ b/plugin/vebugger.vim @@ -12,7 +12,7 @@ command! -nargs=0 VBGcontinue call vebugger#userAction('setWriteActionAndPerform command! -nargs=0 VBGtoggleTerminalBuffer call vebugger#userAction('toggleTerminalBuffer') command! -nargs=+ -complete=file VBGtoggleBreakpoint call vebugger#std#toggleBreakpoint() -command! -nargs=0 VBGtoggleBreakpointThisLine call vebugger#std#toggleBreakpoint(expand('%:~:.'),line('.')) +command! -nargs=0 VBGtoggleBreakpointThisLine call vebugger#std#toggleBreakpoint(expand('%:p:.'),line('.')) command! -nargs=0 VBGclearBreakpoints call vebugger#std#clearBreakpoints() command! -nargs=1 VBGeval call vebugger#userAction('std_eval', ) From c15cbf053683db6257b02cebfe9a1a0cdf97fa9a Mon Sep 17 00:00:00 2001 From: Benjamin Doherty Date: Wed, 2 Aug 2017 18:25:48 -0400 Subject: [PATCH 33/47] Typo fix! --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 77afe82..9674305 100644 --- a/README.md +++ b/README.md @@ -11,12 +11,12 @@ supports: * Debugger flow commands - step-in, set-over, set-out and continue * Breakpoints management * Evaluating expressions in the current executed scope - * Messing with the program's state(changing values, calling functions) + * Messing with the program's state (changing values, calling functions) Vebugger is built as a generic framework for building frontends for interactive shell debugger, and comes with implementations for: - * GDB - doesn't need introdcution... + * GDB - doesn't need introduction... * LLDB - debugger based on LLVM for C-family languages * JDB - a Java debugger * Mdbg - a .NET debugger(Windows only) From 4230773e7e7537247acb21fa771fa891c64545d6 Mon Sep 17 00:00:00 2001 From: Dalton Barreto Date: Wed, 17 May 2017 22:19:56 -0300 Subject: [PATCH 34/47] Add support for multi-srcpath Now Vebugger can search for a sourcecode in multiple srcpath locations. The first match is returned and it's the file Vebugger will show. --- autoload/vebugger/jdb.vim | 18 ++++++++++-------- doc/vebugger.txt | 6 +++++- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/autoload/vebugger/jdb.vim b/autoload/vebugger/jdb.vim index a2c9ed2..64a7622 100644 --- a/autoload/vebugger/jdb.vim +++ b/autoload/vebugger/jdb.vim @@ -87,14 +87,16 @@ function! s:findFolderFromStackTrace(src,nameFromStackTrace,frameNumber) endif " If no such tag was found, try to find it using the src path. - let l:path=a:src - for l:dirname in split(a:nameFromStackTrace,'\.') - let l:nextPath=l:path.'/'.fnameescape(l:dirname) - if empty(glob(l:nextPath)) - return l:path - endif - let l:path=l:nextPath - endfor + for l:one_path in split(a:src, ':') + let l:path=l:one_path + for l:dirname in split(a:nameFromStackTrace,'\.') + let l:nextPath=l:path.'/'.fnameescape(l:dirname) + if empty(glob(l:nextPath)) + return l:path + endif + let l:path=l:nextPath + endfor + endfor return l:path endfunction diff --git a/doc/vebugger.txt b/doc/vebugger.txt index 5a7eeb5..b6a3f74 100644 --- a/doc/vebugger.txt +++ b/doc/vebugger.txt @@ -202,7 +202,7 @@ Unlike in the other debuggers, the first argument here is not the name of a file - it's the name of the class to run. The supported extra arguments are: * "args": Command line arguments for the debugged program * "classpath": Where to look for class files -* "srcpath": Where to look for source files +* "srcpath": Where to look for source files. You can have multiple srcpaths, separated by ':' * "version": The version of the debugger to run If you don't supply "classpath" and "srcpath", Vebugger will assume you are using the current directory for source files and class files. @@ -210,6 +210,10 @@ using the current directory for source files and class files. JDB does not have a command for starting it, since you usually want to supply "classpath" and "srcpath". +If you need Vebugger to search for the source files in multiple locations, you can +specify `srcpath` as a ':' separated string. Vebugger will search on all these folders +and the first match will be returned as the Source file to be shown. + LAUNCHING RDEBUG *vebugger-rdebug* From 5865e3b28e1f079c16c45437a6eb1dc773439a05 Mon Sep 17 00:00:00 2001 From: Dalton Barreto Date: Mon, 16 Oct 2017 20:11:15 -0200 Subject: [PATCH 35/47] Adding support for srcpath as string or list --- autoload/vebugger/jdb.vim | 2 +- autoload/vebugger/util.vim | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/autoload/vebugger/jdb.vim b/autoload/vebugger/jdb.vim index 64a7622..bd4adc7 100644 --- a/autoload/vebugger/jdb.vim +++ b/autoload/vebugger/jdb.vim @@ -87,7 +87,7 @@ function! s:findFolderFromStackTrace(src,nameFromStackTrace,frameNumber) endif " If no such tag was found, try to find it using the src path. - for l:one_path in split(a:src, ':') + for l:one_path in vebugger#util#listify(a:src) let l:path=l:one_path for l:dirname in split(a:nameFromStackTrace,'\.') let l:nextPath=l:path.'/'.fnameescape(l:dirname) diff --git a/autoload/vebugger/util.vim b/autoload/vebugger/util.vim index 2db1d12..b05ab50 100644 --- a/autoload/vebugger/util.vim +++ b/autoload/vebugger/util.vim @@ -115,3 +115,12 @@ function! vebugger#util#isPathAbsolute(path) return a:path[0]=~'\v^[/~$]' "Absolute paths in Linux start with ~(home),/(root dir) or $(environment variable) endif endfunction + +function! vebugger#util#listify(stringOrList) + if type(a:stringOrList) == type([]) + return copy(a:stringOrList) " so it could safely be modified by map&filter + else + return [a:stringOrList] + endif +endfunction + From 01326cc9bec515972dc55759c51376f64e5a8631 Mon Sep 17 00:00:00 2001 From: Dalton Barreto Date: Mon, 16 Oct 2017 20:36:12 -0200 Subject: [PATCH 36/47] Removing redundant variable l:one_path --- autoload/vebugger/jdb.vim | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/autoload/vebugger/jdb.vim b/autoload/vebugger/jdb.vim index bd4adc7..319fe3a 100644 --- a/autoload/vebugger/jdb.vim +++ b/autoload/vebugger/jdb.vim @@ -87,8 +87,7 @@ function! s:findFolderFromStackTrace(src,nameFromStackTrace,frameNumber) endif " If no such tag was found, try to find it using the src path. - for l:one_path in vebugger#util#listify(a:src) - let l:path=l:one_path + for l:path in vebugger#util#listify(a:src) for l:dirname in split(a:nameFromStackTrace,'\.') let l:nextPath=l:path.'/'.fnameescape(l:dirname) if empty(glob(l:nextPath)) From 6a6faec69b3b65d4155e07437f84621f13c9a2f0 Mon Sep 17 00:00:00 2001 From: Dalton Barreto Date: Mon, 16 Oct 2017 20:37:39 -0200 Subject: [PATCH 37/47] Updating docs --- doc/vebugger.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/vebugger.txt b/doc/vebugger.txt index b6a3f74..9202029 100644 --- a/doc/vebugger.txt +++ b/doc/vebugger.txt @@ -202,7 +202,7 @@ Unlike in the other debuggers, the first argument here is not the name of a file - it's the name of the class to run. The supported extra arguments are: * "args": Command line arguments for the debugged program * "classpath": Where to look for class files -* "srcpath": Where to look for source files. You can have multiple srcpaths, separated by ':' +* "srcpath": Where to look for source files. You can have multiple srcpaths, passed as a list * "version": The version of the debugger to run If you don't supply "classpath" and "srcpath", Vebugger will assume you are using the current directory for source files and class files. @@ -211,7 +211,7 @@ JDB does not have a command for starting it, since you usually want to supply "classpath" and "srcpath". If you need Vebugger to search for the source files in multiple locations, you can -specify `srcpath` as a ':' separated string. Vebugger will search on all these folders +specify `srcpath` as a list. Vebugger will search on all these folders and the first match will be returned as the Source file to be shown. From 5fedcab0097c8e1f6862112893f7312267427583 Mon Sep 17 00:00:00 2001 From: Dalton Barreto Date: Tue, 17 Oct 2017 16:28:20 -0200 Subject: [PATCH 38/47] Highlight current debugged line with DebuggedLine If the `DebuggedLine` highlight-group exist, highlight the current debugged line with it. --- autoload/vebugger/std.vim | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/autoload/vebugger/std.vim b/autoload/vebugger/std.vim index 284bb7a..5d8c8c6 100644 --- a/autoload/vebugger/std.vim +++ b/autoload/vebugger/std.vim @@ -300,7 +300,12 @@ function! s:standardCloseHandlers.removeCurrentMarker(debugger) dict sign unplace 1 endfunction -sign define vebugger_current text=-> + +if hlexists("DebuggedLine") + sign define vebugger_current linehl=DebuggedLine +else + sign define vebugger_current text=-> +endif if hlexists('BreakPoint') sign define vebugger_breakpoint text=** linehl=BreakPoint texthl=BreakPoint From cd61f1029c8b83db07ff35579057da6614e7e0d9 Mon Sep 17 00:00:00 2001 From: wsdjeg Date: Wed, 13 Dec 2017 21:23:28 +0800 Subject: [PATCH 39/47] Add filetype --- autoload/vebugger.vim | 1 + autoload/vebugger/std.vim | 1 + 2 files changed, 2 insertions(+) diff --git a/autoload/vebugger.vim b/autoload/vebugger.vim index 1c3871a..4ff724b 100644 --- a/autoload/vebugger.vim +++ b/autoload/vebugger.vim @@ -106,6 +106,7 @@ function! s:f_debugger.showTerminalBuffer() dict new setlocal buftype=nofile setlocal bufhidden=wipe + setlocal filetype=VebuggerTerminal let self.terminalBuffer=bufnr('') silent file Vebugger:Terminal wincmd p diff --git a/autoload/vebugger/std.vim b/autoload/vebugger/std.vim index 5d8c8c6..ac8275b 100644 --- a/autoload/vebugger/std.vim +++ b/autoload/vebugger/std.vim @@ -116,6 +116,7 @@ function! vebugger#std#openShellBuffer(debugger) let b:debugger=a:debugger autocmd BufDelete if exists('b:debugger') | call b:debugger.kill() | endif setlocal buftype=nofile + setlocal filetype=VebuggerShell setlocal bufhidden=wipe let a:debugger.shellBuffer=bufnr('') silent file Vebugger:Shell From 9c47e1b243aff19d8243f536872e7b33556e15ff Mon Sep 17 00:00:00 2001 From: wsdjeg Date: Mon, 18 Dec 2017 22:18:09 +0800 Subject: [PATCH 40/47] Add options for set sign text --- autoload/vebugger/std.vim | 8 +++++--- doc/vebugger.txt | 8 ++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/autoload/vebugger/std.vim b/autoload/vebugger/std.vim index ac8275b..490b12d 100644 --- a/autoload/vebugger/std.vim +++ b/autoload/vebugger/std.vim @@ -301,17 +301,19 @@ function! s:standardCloseHandlers.removeCurrentMarker(debugger) dict sign unplace 1 endfunction +let s:breakpoint_text = get(g:, 'vebugger_breakpoint_text', '->') +let s:currentline_text = get(g:, 'vebugger_currentline_text', '**') if hlexists("DebuggedLine") sign define vebugger_current linehl=DebuggedLine else - sign define vebugger_current text=-> + exe 'sign define vebugger_current text=' . s:currentline_text endif if hlexists('BreakPoint') - sign define vebugger_breakpoint text=** linehl=BreakPoint texthl=BreakPoint + exe 'sign define vebugger_breakpoint text=' . s:breakpoint_text . ' linehl=BreakPoint texthl=BreakPoint' else - sign define vebugger_breakpoint text=** linehl=ColorColumn texthl=ColorColumn + exe 'sign define vebugger_breakpoint text=' . s:breakpoint_text . ' linehl=ColorColumn texthl=ColorColumn' endif "Update all the marks(currently executed line and breakpoints) for a file diff --git a/doc/vebugger.txt b/doc/vebugger.txt index 9202029..697c3c6 100644 --- a/doc/vebugger.txt +++ b/doc/vebugger.txt @@ -110,6 +110,14 @@ Example: > let g:vebugger_view_source_cmd='edit' < +If you want to change the sign text of current line and breakpoint, use +*g:vebugger_breakpoint_text* and *g:vebugger_currentline_text* + +Example: > + let g:vebugger_breakpoint_text='->' + let g:vebugger_currentline_text='**' +< + Some debuggers (currently jdb only) may use vim tags to find required source files. This is disabled by default, to enable this set *g:vebugger_use_tags* option: From 876af0d1c26e43728f34c8c493ea2910cb6d8216 Mon Sep 17 00:00:00 2001 From: wsdjeg Date: Mon, 18 Dec 2017 22:40:40 +0800 Subject: [PATCH 41/47] Use full command names --- autoload/vebugger/std.vim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/autoload/vebugger/std.vim b/autoload/vebugger/std.vim index 490b12d..b9dee3b 100644 --- a/autoload/vebugger/std.vim +++ b/autoload/vebugger/std.vim @@ -307,13 +307,13 @@ let s:currentline_text = get(g:, 'vebugger_currentline_text', '**') if hlexists("DebuggedLine") sign define vebugger_current linehl=DebuggedLine else - exe 'sign define vebugger_current text=' . s:currentline_text + execute 'sign define vebugger_current text=' . s:currentline_text endif if hlexists('BreakPoint') - exe 'sign define vebugger_breakpoint text=' . s:breakpoint_text . ' linehl=BreakPoint texthl=BreakPoint' + execute 'sign define vebugger_breakpoint text=' . s:breakpoint_text . ' linehl=BreakPoint texthl=BreakPoint' else - exe 'sign define vebugger_breakpoint text=' . s:breakpoint_text . ' linehl=ColorColumn texthl=ColorColumn' + execute 'sign define vebugger_breakpoint text=' . s:breakpoint_text . ' linehl=ColorColumn texthl=ColorColumn' endif "Update all the marks(currently executed line and breakpoints) for a file From 8842555cac3a8f96958fdd16080b5baab717478d Mon Sep 17 00:00:00 2001 From: Ingo Heimbach Date: Tue, 27 Feb 2018 13:56:24 +0100 Subject: [PATCH 42/47] The LLDB wrapper can handle `None` as output from the Python lldb module --- autoload/vebugger/lldb_wrapper.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/vebugger/lldb_wrapper.py b/autoload/vebugger/lldb_wrapper.py index 534eb9e..cd6690c 100755 --- a/autoload/vebugger/lldb_wrapper.py +++ b/autoload/vebugger/lldb_wrapper.py @@ -213,6 +213,8 @@ class Debugger(object): def prefix_output(output, prefix): + if output is None: + output = '' lines = output.split('\n') lines = [prefix + line for line in lines] prefixed_output = '\n'.join(lines) From 7d1703ca32f5e6d9d28c4aaa6abd25e850accc20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20M=C3=A5rtensson?= Date: Wed, 11 Apr 2018 15:56:47 +0200 Subject: [PATCH 43/47] add support for attaching JDB to a running process --- autoload/vebugger/jdb.vim | 18 ++++++++++++++---- doc/vebugger.txt | 9 +++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/autoload/vebugger/jdb.vim b/autoload/vebugger/jdb.vim index 319fe3a..494d5ff 100644 --- a/autoload/vebugger/jdb.vim +++ b/autoload/vebugger/jdb.vim @@ -1,6 +1,7 @@ function! vebugger#jdb#start(entryClass,args) let l:debugger=vebugger#std#startDebugger(shellescape(vebugger#util#getToolFullPath('jdb',get(a:args,'version'),'jdb')) - \.(has_key(a:args,'classpath') ? ' -classpath '.fnameescape(a:args.classpath) : '')) + \.(has_key(a:args,'classpath') && !has_key(a:args,'attach') ? ' -classpath '.fnameescape(a:args.classpath) : '') + \.(has_key(a:args,'attach') ? ' -attach '.shellescape(a:args.attach) : '')) let l:debugger.state.jdb={} if has_key(a:args,'srcpath') let l:debugger.state.jdb.srcpath=a:args.srcpath @@ -9,10 +10,14 @@ function! vebugger#jdb#start(entryClass,args) endif let l:debugger.state.jdb.filesToClassesMap={} - call l:debugger.writeLine('stop on '.a:entryClass.'.main') - call l:debugger.writeLine('run '.a:entryClass.' '.vebugger#util#commandLineArgsForProgram(a:args)) + if !has_key(a:args,'attach') + call l:debugger.writeLine('stop on '.a:entryClass.'.main') + call l:debugger.writeLine('run '.a:entryClass.' '.vebugger#util#commandLineArgsForProgram(a:args)) + else + call l:debugger.writeLine('run') + endif call l:debugger.writeLine('monitor where') - if !has('win32') + if !has('win32') && !has_key(a:args,'attach') call vebugger#std#openShellBuffer(l:debugger) endif @@ -33,6 +38,11 @@ function! vebugger#jdb#start(entryClass,args) return l:debugger endfunction +function! vebugger#jdb#attach(address,args) + let a:args.attach = a:address + call vebugger#jdb#start('', a:args) +endfunction + function! vebugger#jdb#_readProgramOutput(pipeName,line,readResult,debugger) dict if 'out'==a:pipeName if a:line=~'\v^\> \>' diff --git a/doc/vebugger.txt b/doc/vebugger.txt index 697c3c6..d119363 100644 --- a/doc/vebugger.txt +++ b/doc/vebugger.txt @@ -212,6 +212,15 @@ file - it's the name of the class to run. The supported extra arguments are: * "classpath": Where to look for class files * "srcpath": Where to look for source files. You can have multiple srcpaths, passed as a list * "version": The version of the debugger to run + +Alternatively, to attach to a running process you can use *vebugger#jdb#attach* +> + call vebugger#jdb#attach('8000',{ + \'srcpath':'src'}) +< +The first argument here is the the address to attach to, e.g. 127.0.0.1:8000 +or just 8000. It does not support the "args" or "classpath" arguments. + If you don't supply "classpath" and "srcpath", Vebugger will assume you are using the current directory for source files and class files. From f1bdce4e69a29fcc9e9073e7aa79cd24ed1c5c63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20M=C3=A5rtensson?= Date: Wed, 11 Apr 2018 16:16:36 +0200 Subject: [PATCH 44/47] add support for not providing extra args to jdb#attach --- autoload/vebugger/jdb.vim | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/autoload/vebugger/jdb.vim b/autoload/vebugger/jdb.vim index 494d5ff..29d2dde 100644 --- a/autoload/vebugger/jdb.vim +++ b/autoload/vebugger/jdb.vim @@ -38,9 +38,10 @@ function! vebugger#jdb#start(entryClass,args) return l:debugger endfunction -function! vebugger#jdb#attach(address,args) - let a:args.attach = a:address - call vebugger#jdb#start('', a:args) +function! vebugger#jdb#attach(address, ...) + let l:args = a:0 ? a:{1} : {} + let l:args.attach = a:address + call vebugger#jdb#start('', l:args) endfunction function! vebugger#jdb#_readProgramOutput(pipeName,line,readResult,debugger) dict From 833806978e20a2c0f4da23a517aeeab447bdbba4 Mon Sep 17 00:00:00 2001 From: IdanArye Date: Sat, 21 Apr 2018 21:09:20 +0300 Subject: [PATCH 45/47] Fix #54 - remove all breakpoint signs with `:VBGclearBreakpoints` --- autoload/vebugger/std.vim | 9 +++++++-- autoload/vebugger/util.vim | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/autoload/vebugger/std.vim b/autoload/vebugger/std.vim index b9dee3b..7435008 100644 --- a/autoload/vebugger/std.vim +++ b/autoload/vebugger/std.vim @@ -319,9 +319,14 @@ endif "Update all the marks(currently executed line and breakpoints) for a file function! vebugger#std#updateMarksForFile(state,filename) let l:filename=fnamemodify(a:filename,":p") - if -1 < bufnr(l:filename) + let l:bufnr = bufnr(l:filename) + if -1 < l:bufnr exe 'sign unplace 1 file='.fnameescape(fnamemodify(l:filename,':p')) - exe 'sign unplace 2 file='.fnameescape(fnamemodify(l:filename,':p')) + for l:sign in vebugger#util#listSignsInBuffer(l:bufnr) + if l:sign.name == 'vebugger_breakpoint' + exe 'sign unplace 2 file='.fnameescape(fnamemodify(l:filename,':p')) + endif + endfor for l:breakpoint in g:vebugger_breakpoints if fnamemodify(l:breakpoint.file,':p')==fnamemodify(a:filename,':p') diff --git a/autoload/vebugger/util.vim b/autoload/vebugger/util.vim index b05ab50..1c7f33e 100644 --- a/autoload/vebugger/util.vim +++ b/autoload/vebugger/util.vim @@ -124,3 +124,25 @@ function! vebugger#util#listify(stringOrList) endif endfunction +function! s:listSigns(filter) abort + let l:result = [] + for l:line in split(execute('sign place '.a:filter), '\n') + let l:match = matchlist(l:line, '\C\v^\s+line\=(\d+)\s+id\=(\d+)\s+name\=(.+)$') + if !empty(l:match) + call add(l:result, { + \ 'line': str2nr(l:match[1]), + \ 'id': str2nr(l:match[2]), + \ 'name': l:match[3], + \ }) + endif + endfor + return l:result +endfunction + +function! vebugger#util#listSignsInBuffer(bufnr) abort + return s:listSigns('buffer='.a:bufnr) +endfunction + +function! vebugger#util#listSignsInFile(filename) abort + return s:listSigns('file='.a:filename) +endfunction From 77925fa4b2ad0492d832162b63303384d4a644ce Mon Sep 17 00:00:00 2001 From: Ingo Heimbach Date: Wed, 23 May 2018 11:49:26 +0200 Subject: [PATCH 46/47] Do not execute autocommands when writing lines to vebugger buffers For writing lines to vebugger's shell and terminal buffer the active window is changed for every single line which causes a huge slowdown on large output. By disabling autocommands, these slowdowns can be reduced. --- autoload/vebugger.vim | 4 ++-- autoload/vebugger/std.vim | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/autoload/vebugger.vim b/autoload/vebugger.vim index 4ff724b..3a29b54 100644 --- a/autoload/vebugger.vim +++ b/autoload/vebugger.vim @@ -148,7 +148,7 @@ function! s:f_debugger.addLineToTerminal(pipeName,line) dict if has_key(self,'terminalBuffer') let l:bufwin=bufwinnr(self.terminalBuffer) if -1 Date: Mon, 25 Jun 2018 16:15:41 +0200 Subject: [PATCH 47/47] Transform filenames to absolute paths when reading debugger locations Before this commit, many debugger `where` functions transformed the filename of the current debugger location to a path relative to vim's current working directory. When the user changed the current working directory in the meantime, the previously saved location could not resolved any more and lead to errors. This commit fixes this problem by storing absolute paths instead. --- autoload/vebugger/gdb.vim | 2 +- autoload/vebugger/jdb.vim | 2 +- autoload/vebugger/lldb.vim | 2 +- autoload/vebugger/mdbg.vim | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/autoload/vebugger/gdb.vim b/autoload/vebugger/gdb.vim index f94ddce..1298e83 100644 --- a/autoload/vebugger/gdb.vim +++ b/autoload/vebugger/gdb.vim @@ -128,7 +128,7 @@ function! vebugger#gdb#_readWhere(pipeName,line,readResult,debugger) let l:matches=matchlist(a:line,'\v^\*stopped.*fullname\=\"([^"]+)\",line\=\"(\d+)"') if 2