Added documentation

This commit is contained in:
IdanArye 2014-05-17 22:43:18 +03:00
parent 663c38e1a6
commit b35eb96727
4 changed files with 282 additions and 3 deletions

View File

@ -1,3 +1,4 @@
"Read and return all new lines from a Vebugger pipe object.
function! s:readNewLinesFromPipe(pipeObject) function! s:readNewLinesFromPipe(pipeObject)
"read "read
let l:text=a:pipeObject.pipe.read(1000,0) let l:text=a:pipeObject.pipe.read(1000,0)
@ -19,6 +20,7 @@ endfunction
let s:f_debugger={} let s:f_debugger={}
"Terminate the debugger
function! s:f_debugger.kill() dict function! s:f_debugger.kill() dict
if self.shell.is_valid if self.shell.is_valid
call self.addLineToTerminal('','== DEBUGGER TERMINATED ==') call self.addLineToTerminal('','== DEBUGGER TERMINATED ==')
@ -32,10 +34,12 @@ function! s:f_debugger.kill() dict
endif endif
endfunction endfunction
"Write a line to the debugger's interactive shell
function! s:f_debugger.writeLine(line) dict function! s:f_debugger.writeLine(line) dict
call self.shell.stdin.write(a:line."\n") call self.shell.stdin.write(a:line."\n")
endfunction endfunction
"Check for new lines from the debugger's interactive shell and handle them
function! s:f_debugger.invokeReading() dict function! s:f_debugger.invokeReading() dict
let l:newLines={} let l:newLines={}
for l:k in keys(self.pipes) for l:k in keys(self.pipes)
@ -58,6 +62,7 @@ function! s:f_debugger.invokeReading() dict
call feedkeys("f\e") " Make sure the CursorHold event is refired even if the user does nothing call feedkeys("f\e") " Make sure the CursorHold event is refired even if the user does nothing
endfunction endfunction
"Handle a single line from the debugger's interactive shell
function! s:f_debugger.handleLine(pipeName,line) dict function! s:f_debugger.handleLine(pipeName,line) dict
call self.addLineToTerminal(a:pipeName,a:line) call self.addLineToTerminal(a:pipeName,a:line)
@ -74,6 +79,7 @@ function! s:f_debugger.handleLine(pipeName,line) dict
call self.performWriteActions() call self.performWriteActions()
endfunction endfunction
"Perform all write actions
function! s:f_debugger.performWriteActions() dict function! s:f_debugger.performWriteActions() dict
for l:namespace in keys(self.writeActions) for l:namespace in keys(self.writeActions)
let l:handlers=get(self.writeHandlers,l:namespace) let l:handlers=get(self.writeHandlers,l:namespace)
@ -90,6 +96,8 @@ function! s:f_debugger.performWriteActions() dict
call self.generateWriteActionsFromTemplate() call self.generateWriteActionsFromTemplate()
endfunction endfunction
"Show the terminal buffer that gets it's content from the debugger's
"interactive shell
function! s:f_debugger.showTerminalBuffer() dict function! s:f_debugger.showTerminalBuffer() dict
if has_key(self,'terminalBuffer') if has_key(self,'terminalBuffer')
if -1<bufwinnr(self.terminalBuffer) if -1<bufwinnr(self.terminalBuffer)
@ -104,6 +112,7 @@ function! s:f_debugger.showTerminalBuffer() dict
wincmd p wincmd p
endfunction endfunction
"Close the terminal buffer
function! s:f_debugger.closeTerminalBuffer() dict function! s:f_debugger.closeTerminalBuffer() dict
if has_key(self,'terminalBuffer') if has_key(self,'terminalBuffer')
if -1<bufwinnr(self.terminalBuffer) if -1<bufwinnr(self.terminalBuffer)
@ -115,6 +124,7 @@ function! s:f_debugger.closeTerminalBuffer() dict
endif endif
endfunction endfunction
"Check if the terminal buffer associated with this debugger is currently open
function! s:f_debugger.isTerminalBufferOpen() dict function! s:f_debugger.isTerminalBufferOpen() dict
if has_key(self,'terminalBuffer') if has_key(self,'terminalBuffer')
if -1<bufwinnr(self.terminalBuffer) if -1<bufwinnr(self.terminalBuffer)
@ -124,6 +134,7 @@ function! s:f_debugger.isTerminalBufferOpen() dict
return 0 return 0
endfunction endfunction
"Turn on and off the terminal buffer associated with this debugger
function! s:f_debugger.toggleTerminalBuffer() dict function! s:f_debugger.toggleTerminalBuffer() dict
if self.isTerminalBufferOpen() if self.isTerminalBufferOpen()
call self.closeTerminalBuffer() call self.closeTerminalBuffer()
@ -132,6 +143,7 @@ function! s:f_debugger.toggleTerminalBuffer() dict
endif endif
endfunction endfunction
"Write a line to the terminal buffer. This function does not process the line
function! s:f_debugger.addLineToTerminal(pipeName,line) dict function! s:f_debugger.addLineToTerminal(pipeName,line) dict
if has_key(self,'terminalBuffer') if has_key(self,'terminalBuffer')
let l:bufwin=bufwinnr(self.terminalBuffer) let l:bufwin=bufwinnr(self.terminalBuffer)
@ -150,6 +162,7 @@ function! s:f_debugger.addLineToTerminal(pipeName,line) dict
endif endif
endfunction endfunction
"Add an handler to a handler list
function! s:addHandler(list,handler) function! s:addHandler(list,handler)
if type(a:handler) == type({}) if type(a:handler) == type({})
call add(a:list,a:handler) call add(a:list,a:handler)
@ -158,6 +171,7 @@ function! s:addHandler(list,handler)
endif endif
endfunction endfunction
"Set a named handler in a handler dictionary
function! s:setHandler(dict,namespace,name,handler) function! s:setHandler(dict,namespace,name,handler)
if !has_key(a:dict,a:namespace) if !has_key(a:dict,a:namespace)
let a:dict[a:namespace]={} let a:dict[a:namespace]={}
@ -169,34 +183,51 @@ function! s:setHandler(dict,namespace,name,handler)
endif endif
endfunction endfunction
"Add a read handler. Read handlers process output from the debugger's
"interactive shell and modify read result objects with structured information
"parsed from those lines
function! s:f_debugger.addReadHandler(handler) dict function! s:f_debugger.addReadHandler(handler) dict
call s:addHandler(self.readHandlers,a:handler) call s:addHandler(self.readHandlers,a:handler)
endfunction endfunction
"Add a think handler. Think handlers are debugger agnostic - they look at
"read result objects and decide what to do with them.
function! s:f_debugger.addThinkHandler(handler) dict function! s:f_debugger.addThinkHandler(handler) dict
call s:addHandler(self.thinkHandlers,a:handler) call s:addHandler(self.thinkHandlers,a:handler)
endfunction endfunction
"Set a write handler. Write handlers get write action objects and convert them
"to debugger specific commands. A write action can only handle a write action
"of the namespace and name it is registered for, to prevent the same write
"action handled by multiple write handlers.
function! s:f_debugger.setWriteHandler(namespace,name,handler) dict function! s:f_debugger.setWriteHandler(namespace,name,handler) dict
call s:setHandler(self.writeHandlers,a:namespace,a:name,a:handler) call s:setHandler(self.writeHandlers,a:namespace,a:name,a:handler)
endfunction endfunction
"Add a close handler. Close handlers are called when the debugger is closed to
"tidy things up.
function! s:f_debugger.addCloseHandler(handler) dict function! s:f_debugger.addCloseHandler(handler) dict
call s:addHandler(self.closeHandlers,a:handler) call s:addHandler(self.closeHandlers,a:handler)
endfunction endfunction
"Create an empty write action that follows the write actions template. That
"action will later be filled by think handlers or from outside.
function! s:f_debugger.generateWriteActionsFromTemplate() dict function! s:f_debugger.generateWriteActionsFromTemplate() dict
let self.writeActions=deepcopy(self.writeActionsTemplate) let self.writeActions=deepcopy(self.writeActionsTemplate)
endfunction endfunction
"Set a write action of a specific namespace and name, for write actions that
"do not support a list
function! s:f_debugger.setWriteAction(namespace,name,value) dict function! s:f_debugger.setWriteAction(namespace,name,value) dict
let self.writeActions[a:namespace][a:name]=a:value let self.writeActions[a:namespace][a:name]=a:value
endfunction endfunction
"Add a write action of a specific namespace and name, for write actions that supports a list
function! s:f_debugger.addWriteAction(namespace,name,value) dict function! s:f_debugger.addWriteAction(namespace,name,value) dict
call add(self.writeActions[a:namespace][a:name],a:value) call add(self.writeActions[a:namespace][a:name],a:value)
endfunction endfunction
"Create a bare debugger object from a raw shell line
function! vebugger#createDebugger(command) function! vebugger#createDebugger(command)
let l:debugger=deepcopy(s:f_debugger) let l:debugger=deepcopy(s:f_debugger)
@ -225,8 +256,8 @@ function! vebugger#createDebugger(command)
return l:debugger return l:debugger
endfunction endfunction
" all the functions here are currently just for testing:
"Create a debugger and set it as the currently active debugger
function! vebugger#startDebugger(command) function! vebugger#startDebugger(command)
call vebugger#killDebugger() call vebugger#killDebugger()
@ -240,6 +271,7 @@ function! vebugger#startDebugger(command)
return s:debugger return s:debugger
endfunction endfunction
"Terminate the currently active debugger
function! vebugger#killDebugger() function! vebugger#killDebugger()
augroup vebugger_shell augroup vebugger_shell
autocmd! autocmd!
@ -251,24 +283,28 @@ function! vebugger#killDebugger()
endif endif
endfunction endfunction
"Write a line to the currently active debugger
function! vebugger#writeLine(line) function! vebugger#writeLine(line)
if exists('s:debugger') if exists('s:debugger')
call s:debugger.writeLine(a:line) call s:debugger.writeLine(a:line)
endif endif
endfunction endfunction
"Invoke reading for the currently active debugger
function! vebugger#invokeReading() function! vebugger#invokeReading()
if exists('s:debugger') if exists('s:debugger')
call s:debugger.invokeReading() call s:debugger.invokeReading()
endif endif
endfunction endfunction
"Toggle the terminal buffer for the currently active debugger
function! vebugger#toggleTerminalBuffer() function! vebugger#toggleTerminalBuffer()
if exists('s:debugger') if exists('s:debugger')
call s:debugger.toggleTerminalBuffer() call s:debugger.toggleTerminalBuffer()
endif endif
endfunction endfunction
"Fetch the currently active debugger object
function! vebugger#getActiveDebugger() function! vebugger#getActiveDebugger()
if exists('s:debugger') if exists('s:debugger')
return s:debugger return s:debugger
@ -277,29 +313,34 @@ function! vebugger#getActiveDebugger()
endif endif
endfunction endfunction
"Set a write action for the currently active debugger
function! vebugger#setWriteAction(namespace,name,value) function! vebugger#setWriteAction(namespace,name,value)
if exists('s:debugger') if exists('s:debugger')
call s:debugger.setWriteAction(a:namespace,a:name,a:value) call s:debugger.setWriteAction(a:namespace,a:name,a:value)
endif endif
endfunction endfunction
"Add a write action to the currently active debugger
function! vebugger#addWriteAction(namespace,name,value) function! vebugger#addWriteAction(namespace,name,value)
if exists('s:debugger') if exists('s:debugger')
call s:debugger.addWriteAction(a:namespace,a:name,a:value) call s:debugger.addWriteAction(a:namespace,a:name,a:value)
endif endif
endfunction endfunction
"Force performing all the write of the currently active debugger
function! vebugger#performWriteActions() function! vebugger#performWriteActions()
if exists('s:debugger') if exists('s:debugger')
call s:debugger.performWriteActions() call s:debugger.performWriteActions()
endif endif
endfunction endfunction
"Set a write action for the currently active debugger and perform it
function! vebugger#setWriteActionAndPerform(namespace,name,value) function! vebugger#setWriteActionAndPerform(namespace,name,value)
call vebugger#setWriteAction(a:namespace,a:name,a:value) call vebugger#setWriteAction(a:namespace,a:name,a:value)
call vebugger#performWriteActions() call vebugger#performWriteActions()
endfunction endfunction
"Add a write action to the currently active debugger and perform it
function! vebugger#addWriteActionAndPerform(namespace,name,value) function! vebugger#addWriteActionAndPerform(namespace,name,value)
call vebugger#addWriteAction(a:namespace,a:name,a:value) call vebugger#addWriteAction(a:namespace,a:name,a:value)
call vebugger#performWriteActions() call vebugger#performWriteActions()

View File

@ -1,5 +1,6 @@
let g:vebugger_breakpoints=[] let g:vebugger_breakpoints=[]
"Initialize the std part of the debugger's state
function! vebugger#std#setStandardState(debugger) function! vebugger#std#setStandardState(debugger)
let a:debugger.state.std={ let a:debugger.state.std={
\'config':{ \'config':{
@ -9,6 +10,7 @@ function! vebugger#std#setStandardState(debugger)
\'evaluateExpressions':[]} \'evaluateExpressions':[]}
endfunction endfunction
"Initialize the std part of the debugger's read result template
function! vebugger#std#setStandardReadResultTemplate(debugger) function! vebugger#std#setStandardReadResultTemplate(debugger)
let a:debugger.readResultTemplate.std={ let a:debugger.readResultTemplate.std={
\'programOutput':{}, \'programOutput':{},
@ -19,6 +21,7 @@ function! vebugger#std#setStandardReadResultTemplate(debugger)
\'exception':{}} \'exception':{}}
endfunction endfunction
"Initialize the std part of the debugger's write actions template
function! vebugger#std#setStandardWriteactionsTemplate(debugger) function! vebugger#std#setStandardWriteactionsTemplate(debugger)
let a:debugger.writeActionsTemplate.std={ let a:debugger.writeActionsTemplate.std={
\'flow':'', \'flow':'',
@ -29,24 +32,28 @@ function! vebugger#std#setStandardWriteactionsTemplate(debugger)
\'closeDebugger':''} \'closeDebugger':''}
endfunction endfunction
"Adds the std_ functions to the debugger object
function! vebugger#std#addStandardFunctions(debugger) function! vebugger#std#addStandardFunctions(debugger)
for l:k in keys(s:standardFunctions) for l:k in keys(s:standardFunctions)
let a:debugger['std_'.l:k]=s:standardFunctions[l:k] let a:debugger['std_'.l:k]=s:standardFunctions[l:k]
endfor endfor
endfunction endfunction
"Add the standard think handlers to the debugger
function! vebugger#std#addStandardThinkHandlers(debugger) function! vebugger#std#addStandardThinkHandlers(debugger)
for l:ThinkHandler in values(s:standardThinkHandlers) for l:ThinkHandler in values(s:standardThinkHandlers)
call a:debugger.addThinkHandler(l:ThinkHandler) call a:debugger.addThinkHandler(l:ThinkHandler)
endfor endfor
endfunction endfunction
"Add the standard close handlers to the debugger
function! vebugger#std#addStandardCloseHandlers(debugger) function! vebugger#std#addStandardCloseHandlers(debugger)
for l:CloseHandler in values(s:standardCloseHandlers) for l:CloseHandler in values(s:standardCloseHandlers)
call a:debugger.addCloseHandler(l:CloseHandler) call a:debugger.addCloseHandler(l:CloseHandler)
endfor endfor
endfunction endfunction
"Performs the standard initialization of the debugger object
function! vebugger#std#standardInit(debugger) function! vebugger#std#standardInit(debugger)
call vebugger#std#setStandardState(a:debugger) call vebugger#std#setStandardState(a:debugger)
call vebugger#std#setStandardReadResultTemplate(a:debugger) call vebugger#std#setStandardReadResultTemplate(a:debugger)
@ -56,6 +63,7 @@ function! vebugger#std#standardInit(debugger)
call vebugger#std#addStandardCloseHandlers(a:debugger) call vebugger#std#addStandardCloseHandlers(a:debugger)
endfunction endfunction
"Start a debugger with the std settings
function! vebugger#std#startDebugger(command) function! vebugger#std#startDebugger(command)
let l:debugger=vebugger#startDebugger(a:command) let l:debugger=vebugger#startDebugger(a:command)
@ -65,6 +73,10 @@ function! vebugger#std#startDebugger(command)
endfunction endfunction
"Opens the shell buffer for a debugger. The shell buffer displays the output
"of the debugged program, and when it's closed the debugger gets terminated.
"Shell buffers should not be used when attaching a debugger to a running
"process.
function! vebugger#std#openShellBuffer(debugger) function! vebugger#std#openShellBuffer(debugger)
if has_key(a:debugger,'shellBuffer') if has_key(a:debugger,'shellBuffer')
if -1<bufwinnr(a:debugger.shellBuffer) if -1<bufwinnr(a:debugger.shellBuffer)
@ -90,6 +102,8 @@ function! vebugger#std#openShellBuffer(debugger)
endfunction endfunction
let s:standardFunctions={} let s:standardFunctions={}
"Write a line to the shell buffer
function! s:standardFunctions.addLineToShellBuffer(line) dict function! s:standardFunctions.addLineToShellBuffer(line) dict
if has_key(self,'shellBuffer') if has_key(self,'shellBuffer')
let l:bufwin=bufwinnr(self.shellBuffer) let l:bufwin=bufwinnr(self.shellBuffer)
@ -102,6 +116,7 @@ function! s:standardFunctions.addLineToShellBuffer(line) dict
endif endif
endfunction endfunction
"Set the write actions to add all breakpoints registered in Vebugger
function! s:standardFunctions.addAllBreakpointActions(breakpoints) dict function! s:standardFunctions.addAllBreakpointActions(breakpoints) dict
for l:breakpoint in a:breakpoints for l:breakpoint in a:breakpoints
call self.addWriteAction('std','breakpoints',{ call self.addWriteAction('std','breakpoints',{
@ -111,6 +126,7 @@ function! s:standardFunctions.addAllBreakpointActions(breakpoints) dict
endfor endfor
endfunction endfunction
"Make the debugger evaluate an expression
function! s:standardFunctions.eval(expression) dict function! s:standardFunctions.eval(expression) dict
if -1==index(self.state.std.evaluateExpressions,a:expression) if -1==index(self.state.std.evaluateExpressions,a:expression)
call add(self.state.std.evaluateExpressions,a:expression) call add(self.state.std.evaluateExpressions,a:expression)
@ -120,14 +136,17 @@ function! s:standardFunctions.eval(expression) dict
call self.performWriteActions() call self.performWriteActions()
endfunction endfunction
"Executes a statement in the debugged program "Execute a statement in the debugged program
function! s:standardFunctions.execute(statement) dict function! s:standardFunctions.execute(statement) dict
call self.addWriteAction('std','executeStatements',{ call self.addWriteAction('std','executeStatements',{
\'statement':(a:statement)}) \'statement':(a:statement)})
call self.performWriteActions() call self.performWriteActions()
endfunction endfunction
let s:standardThinkHandlers={} let s:standardThinkHandlers={}
"Update the shell buffer with program output
function! s:standardThinkHandlers.addProgramOutputToShell(readResult,debugger) dict function! s:standardThinkHandlers.addProgramOutputToShell(readResult,debugger) dict
let l:programOutput=a:readResult.std.programOutput let l:programOutput=a:readResult.std.programOutput
if !empty(l:programOutput) if !empty(l:programOutput)
@ -135,6 +154,7 @@ function! s:standardThinkHandlers.addProgramOutputToShell(readResult,debugger) d
endif endif
endfunction endfunction
"Make Vim jump to the currently executed line
function! s:standardThinkHandlers.moveToCurrentLine(readResult,debugger) dict function! s:standardThinkHandlers.moveToCurrentLine(readResult,debugger) dict
if !empty(a:readResult.std.location) if !empty(a:readResult.std.location)
if !empty(a:debugger.state.std.config.externalFileStop_flowCommand) " Do we need to worry about stopping at external files? if !empty(a:debugger.state.std.config.externalFileStop_flowCommand) " Do we need to worry about stopping at external files?
@ -157,6 +177,7 @@ function! s:standardThinkHandlers.moveToCurrentLine(readResult,debugger) dict
endif endif
endfunction endfunction
"Update the call stack
function! s:standardThinkHandlers.updateCallStack(readResult,debugger) dict function! s:standardThinkHandlers.updateCallStack(readResult,debugger) dict
let l:callstack=a:readResult.std.callstack let l:callstack=a:readResult.std.callstack
if !empty(l:callstack) if !empty(l:callstack)
@ -172,6 +193,7 @@ function! s:standardThinkHandlers.updateCallStack(readResult,debugger) dict
endif endif
endfunction endfunction
"Print an expression that it's evaluation was previously requested
function! s:standardThinkHandlers.printEvaluatedExpression(readResult,debugger) dict function! s:standardThinkHandlers.printEvaluatedExpression(readResult,debugger) dict
let l:evaluatedExpression=a:readResult.std.evaluatedExpression let l:evaluatedExpression=a:readResult.std.evaluatedExpression
if !empty(l:evaluatedExpression) if !empty(l:evaluatedExpression)
@ -189,12 +211,15 @@ function! s:standardThinkHandlers.printEvaluatedExpression(readResult,debugger)
endif endif
endfunction endfunction
"Close the debugger when the program is finished but the debugger wasn't
"closed automatically
function! s:standardThinkHandlers.closeDebuggerWhenProgramFinishes(readResult,debugger) dict function! s:standardThinkHandlers.closeDebuggerWhenProgramFinishes(readResult,debugger) dict
if !empty(a:readResult.std.programFinish) if !empty(a:readResult.std.programFinish)
call a:debugger.setWriteAction('std','closeDebugger','close') call a:debugger.setWriteAction('std','closeDebugger','close')
endif endif
endfunction endfunction
"Print an exception message
function! s:standardThinkHandlers.printException(readResult,debugger) dict function! s:standardThinkHandlers.printException(readResult,debugger) dict
if !empty(a:readResult.std.exception) if !empty(a:readResult.std.exception)
echohl WarningMsg echohl WarningMsg
@ -204,6 +229,7 @@ function! s:standardThinkHandlers.printException(readResult,debugger) dict
endfunction endfunction
let s:standardCloseHandlers={} let s:standardCloseHandlers={}
"Remove the currently executed line when a debugger is closed
function! s:standardCloseHandlers.removeCurrentMarker(debugger) dict function! s:standardCloseHandlers.removeCurrentMarker(debugger) dict
let a:debugger.state.std.location={} let a:debugger.state.std.location={}
sign unplace 1 sign unplace 1
@ -211,6 +237,8 @@ endfunction
sign define vebugger_current text=-> sign define vebugger_current text=->
sign define vebugger_breakpoint text=** linehl=ColorColumn 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) function! vebugger#std#updateMarksForFile(state,filename)
let l:filename=fnamemodify(a:filename,":p") let l:filename=fnamemodify(a:filename,":p")
if bufexists(l:filename) if bufexists(l:filename)
@ -232,6 +260,7 @@ function! vebugger#std#updateMarksForFile(state,filename)
endif endif
endfunction endfunction
"Toggle a breakpoint on and off
function! vebugger#std#toggleBreakpoint(file,line) function! vebugger#std#toggleBreakpoint(file,line)
let l:debugger=vebugger#getActiveDebugger() let l:debugger=vebugger#getActiveDebugger()
let l:debuggerState=empty(l:debugger) let l:debuggerState=empty(l:debugger)
@ -257,6 +286,7 @@ function! vebugger#std#toggleBreakpoint(file,line)
call vebugger#std#updateMarksForFile(l:debuggerState,a:file) call vebugger#std#updateMarksForFile(l:debuggerState,a:file)
endfunction endfunction
"Clear all breakpoints
function! vebugger#std#clearBreakpoints() function! vebugger#std#clearBreakpoints()
let l:debugger=vebugger#getActiveDebugger() let l:debugger=vebugger#getActiveDebugger()
let l:debuggerState=empty(l:debugger) ? {} : l:debugger.state let l:debuggerState=empty(l:debugger) ? {} : l:debugger.state
@ -274,6 +304,7 @@ function! vebugger#std#clearBreakpoints()
endfor endfor
endfunction endfunction
"Ask the active debugger to evaluate an expression
function! vebugger#std#eval(expression) function! vebugger#std#eval(expression)
let l:debugger=vebugger#getActiveDebugger() let l:debugger=vebugger#getActiveDebugger()
if !empty(l:debugger) && !empty(l:debugger.std_eval) if !empty(l:debugger) && !empty(l:debugger.std_eval)
@ -281,6 +312,7 @@ function! vebugger#std#eval(expression)
endif endif
endfunction endfunction
"Ask the active debugger to execute a statement
function! vebugger#std#execute(statement) function! vebugger#std#execute(statement)
let l:debugger=vebugger#getActiveDebugger() let l:debugger=vebugger#getActiveDebugger()
if !empty(l:debugger) && !empty(l:debugger.std_eval) if !empty(l:debugger) && !empty(l:debugger.std_eval)

View File

@ -1,6 +1,7 @@
"Shamefully stolen from http://stackoverflow.com/a/6271254/794380 "Returns the visually selected text
function! vebugger#util#get_visual_selection() function! vebugger#util#get_visual_selection()
"Shamefully stolen from http://stackoverflow.com/a/6271254/794380
" Why is this not a built-in Vim script function?! " Why is this not a built-in Vim script function?!
let [lnum1, col1] = getpos("'<")[1:2] let [lnum1, col1] = getpos("'<")[1:2]
let [lnum2, col2] = getpos("'>")[1:2] let [lnum2, col2] = getpos("'>")[1:2]
@ -10,6 +11,8 @@ function! vebugger#util#get_visual_selection()
return join(lines, "\n") return join(lines, "\n")
endfunction endfunction
"Prompts the user with a filtered list of process, and returns the process id
"the user selects
function! vebugger#util#selectProcessOfFile(ofFile) function! vebugger#util#selectProcessOfFile(ofFile)
let l:fileName=fnamemodify(a:ofFile,':t') let l:fileName=fnamemodify(a:ofFile,':t')
let l:resultLines=split(vimproc#system('ps -o pid,user,comm,start,state,tt -C '.fnameescape(l:fileName)),'\r\n\|\n\|\r') let l:resultLines=split(vimproc#system('ps -o pid,user,comm,start,state,tt -C '.fnameescape(l:fileName)),'\r\n\|\n\|\r')
@ -32,6 +35,8 @@ function! vebugger#util#selectProcessOfFile(ofFile)
return str2nr(matchlist(l:chosenLine,'\v^\s*\d+\)\s+(\d+)')[1]) return str2nr(matchlist(l:chosenLine,'\v^\s*\d+\)\s+(\d+)')[1])
endfunction endfunction
"Escape args(from a debugger's extra arguments) as a command line arguments
"string
function! vebugger#util#commandLineArgsForProgram(debuggerArgs) function! vebugger#util#commandLineArgsForProgram(debuggerArgs)
if has_key(a:debuggerArgs,'args') if has_key(a:debuggerArgs,'args')
if type(a:debuggerArgs.args)==type([]) if type(a:debuggerArgs.args)==type([])
@ -44,6 +49,7 @@ function! vebugger#util#commandLineArgsForProgram(debuggerArgs)
endif endif
endfunction endfunction
"Escape a single argument for the command line
function! s:argEscape(arg) function! s:argEscape(arg)
if has('win32') if has('win32')
return shellescape(a:arg) return shellescape(a:arg)

200
doc/vebugger.txt Normal file
View File

@ -0,0 +1,200 @@
*vebugger.txt*
Author: Idan Arye <https://github.com/someboddy/>
License: Same terms as Vim itself (see |license|)
Version: 1.0.0
INTRODUCTION *vebugger*
Vebugger is yet another debugger frontend plugin for Vim, created because I
wasn't happy with the other debugger plugins I found. Vebugger currently
supports:
* Tracking the currently executed command in the source code
* 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)
Vebugger is built as a generic framework for building frontends for
interactive shell debugger, and comes with implementations for:
* GDB - doesn't need introdcution...
* JDB - a Java debugger
* PDB - a Python module for debugging Python scripts
* RDebug - a Ruby command line option for debugging Ruby scripts
Other implementations can be added with ease.
Vebugger is built under the following assumptions:
* While command line debuggers share enough in common to make the creation
of such a framework as Vebugger possible, the differences between them are
too great to be expressed with regular expression. To support them all at
least some code has to be written.
* Unlike IDE users, Vim users tend to understand the tools the operate behind
the scenes. While Vebugger automates the common features, it allows you to
"open the hood" and interact with the debugger's shell directly so you could
utilize the full power of your debugger.
* I have no intention to aim for the lowest common denominator. If one
debugger has a cool feature I want to support, I'll implement it even if the
other debuggers don't have it.
CONFIGURATION *vebugger-configuration*
If you want to use the keymaps, you need to choose a leader for them by
setting *g:vebugger_leader* in your vimrc.
Example: >
let g:vebugger_leader='<Leader>d'
<
LAUNCHING DEBUGGERS *vebugger-launching*
A debugger's implementation is responsible for starting it. The standard is to
have a "start" function that accepts two arguments: The file to launch(EXE
file or main script file) and a dictionary of other arguments. There should
also be a command for launching the debugger with more ease.
LAUNCHING GDB *vebugger-gdb*
GDB can be launched with *vebuger#gdb#start*
>
call vebugger#gdb#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".
GDB can also be launched with the *VBGstartGDB* command:
>
VBGstartGDB a.out hello world
<
The *VBGattachGDB* command searches for processes launched from the EXE to
attach to, and attaches to them:
>
VBGattachGDB a.out
<
LAUNCHING JDB *vebugger-jdb*
JDB is launched with *vebugger#jdb#start*
>
call vebugger#jdb#start('Main',{
\'classpath':'classes',
\'srcpath':'src',
\'args':['hello','world']})
<
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
If you don't supply "classpath" and "srcpath", Vebugger will assume you are
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".
LAUNCHING RDEBUG *vebugger-rdebug*
RDebug is launched with *vebugger#rdebug#start*
>
call vebugger#rdebug#start('script.rb',{'args':['hello','world']})
<
The supported extra arguments are:
* "args": Command line arguments for the debugged script
RDebug can also be launched with the *VBGstartRDebug* command:
>
VBGstartRDebug script.rb hello world
<
LAUNCHING PDB *vebugger-pdb*
PDB is launched with *vebugger#pdb#start*
>
call vebugger#pdb#start('script.py',{'args':['hello','world']})
<
The supported extra arguments are:
* "args": Command line arguments for the debugged script
PDB can also be launched with the *VBGstartPDB* command:
>
VBGstartPDB script.py hello world
<
USING THE DEBUGGERS *vebugger-usage* *vebugger-commands*
Once you have launched a debugger, you can use the following commands to
interact with it:
CONTROL THE EXECUTION OF THE PROGRAM *vebugger-execution-control*
*:VBGstepOver* Continue the execution, stopping at the next statement.
*:VBGstepIn* Same as VBGstepOver but stepps into functions.
*:VBGstepOut* Continue the execution until the end of the current function.
*:VBGcontinue* Continue the execution.
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.
EVALUATE EXPRESSIONS *vebugger-evalutate*
*:VBGeval* Evaluate and print the expression supplied as argument.
*:VBGevalSelectedText* Evaluate and print the selected text.
*:VBGevalWordUnderCursor* Evaluate the <cword> under the cursor
EXECUTE STATEMENTS *vebugger-execute*
*:VBGexecute* Execute the statement supplied as argument.
*:VBGexecuteSelectedText* Execute the selected text.
TERMINATING THE DEBUGGER *vebugger-terminate*
*:VBGkill* Terminates the debugger
OPENING THE HOOD *vebugger-open-the-hood*
You can open the hood and interact with the running debugger directly using
the following commands:
*:VBGtoggleTerminalBuffer* Opens a buffer that shows everything printed from
the debugger interactive shell.
*:VBGrawWrite* Sends a line supplied as argument to the debugger interactive shell.
*:VBGrawWriteSelectedText* Sends the selected text to the debugger interactive
shell.
KEYMAPS *vebugger-keymaps*
If you set|g:vebugger_leader| in your vimrc you'll get keymaps for the
Vebugger commands. The keymaps all start with the leader you set, following
with:
i |:VBGstepIn|
o |:VBGstepOver|
O |:VBGstepOut|
c |:VBGcontinue|
b |:VBGtoggleBreakpointThisLine|
B |:VBGclearBreakpints|
e |:VBGevalWordUnderCursor| in normal mode
|:VBGevalSelectedText| in select mode
E Prompt for an argument for |:VBGeval|
x |:VBGexecute| current line in normal mode.
|:VBGexecuteSelectedText| in select mode
X Prompt for an argument for |:VBGexecute|
t |:VBGtoggleTerminalBuffer|
r Select mode only - |:VBGrawWriteSelectedText|
R Prompt for an argument for |:VBGrawWrite|