Merge pull request #375 from puremourning/up-down-stack
Add commands to navigate up/down the stack in focussed thread.
This commit is contained in:
commit
d84ebdd0ee
6 changed files with 229 additions and 36 deletions
84
README.md
84
README.md
|
|
@ -656,18 +656,23 @@ personal and so you should work out what you like and use vim's powerful mapping
|
|||
features to set your own mappings. To that end, Vimspector defines the following
|
||||
`<Plug>` mappings:
|
||||
|
||||
* `<Plug>VimspectorContinue`
|
||||
* `<Plug>VimspectorStop`
|
||||
* `<Plug>VimspectorRestart`
|
||||
* `<Plug>VimspectorPause`
|
||||
* `<Plug>VimspectorToggleBreakpoint`
|
||||
* `<Plug>VimspectorToggleConditionalBreakpoint`
|
||||
* `<Plug>VimspectorAddFunctionBreakpoint`
|
||||
* `<Plug>VimspectorStepOver`
|
||||
* `<Plug>VimspectorStepInto`
|
||||
* `<Plug>VimspectorStepOut`
|
||||
* `<Plug>VimspectorRunToCursor`
|
||||
* `<Plug>VimspectorBalloonEval`
|
||||
| Mapping | Function | API |
|
||||
| --- | --- | --- |
|
||||
| `<Plug>VimspectorContinue` | When debugging, continue. Otherwise start debugging. | `vimspector#Continue()` |
|
||||
| `<Plug>VimspectorStop` | Stop debugging. | `vimspector#Stop()` |
|
||||
| `<Plug>VimpectorRestart` | Restart debugging with the same configuration. | `vimspector#Restart()` |
|
||||
| `<Plug>VimspectorPause` | Pause debuggee. | `vimspector#Pause()` |
|
||||
| `<Plug>VimspectorToggleBreakpoint` | Toggle line breakpoint on the current line. | `vimspector#ToggleBreakpoint()` |
|
||||
| `<Plug>VimspectorToggleConditionalBreakpoint` | Toggle conditional line breakpoint on the current line. | `vimspector#ToggleBreakpoint( { trigger expr, hit count expr } )` |
|
||||
| `<Plug>VimspectorAddFunctionBreakpoint` | Add a function breakpoint for the expression under cursor | `vimspector#AddFunctionBreakpoint( '<cexpr>' )` |
|
||||
| `<Plug>VimspectorRunToCursor` | Run to Cursor | `vimspector#RunToCursor()` |
|
||||
| `<Plug>VimspectorStepOver` | Step Over | `vimspector#StepOver()` |
|
||||
| `<Plug>VimspectorStepInto` | Step Into | `vimspector#StepInto()` |
|
||||
| `<Plug>VimspectorStepOut` | Step out of current function scope | `vimspector#StepOut()` |
|
||||
| `<Plug>VimspectorUpFrame` | Move up a frame in the current call stack | `vimspector#UpFrame()` |
|
||||
| `<Plug>VimspectorDownFrame` | Move down a frame in the current call stack | `vimspector#DownFrame()` |
|
||||
| `<Plug>VimspectorBalloonEval` | Evaluate expression under cursor (or visual) in popup | *internal* |
|
||||
|
||||
|
||||
These map roughly 1-1 with the API functions below.
|
||||
|
||||
|
|
@ -695,17 +700,17 @@ loading vimspector**:
|
|||
let g:vimspector_enable_mappings = 'VISUAL_STUDIO'
|
||||
```
|
||||
|
||||
| Key | Function | API |
|
||||
| --- | --- | --- |
|
||||
| `F5` | When debugging, continue. Otherwise start debugging. | `vimspector#Continue()` |
|
||||
| `Shift F5` | Stop debugging. | `vimspector#Stop()` |
|
||||
| `Ctrl Shift F5` | Restart debugging with the same configuration. | `vimspector#Restart()` |
|
||||
| `F6` | Pause debuggee. | `vimspector#Pause()` |
|
||||
| `F9` | Toggle line breakpoint on the current line. | `vimspector#ToggleBreakpoint()` |
|
||||
| `Shift F9` | Add a function breakpoint for the expression under cursor | `vimspector#AddFunctionBreakpoint( '<cexpr>' )` |
|
||||
| `F10` | Step Over | `vimspector#StepOver()` |
|
||||
| `F11` | Step Into | `vimspector#StepInto()` |
|
||||
| `Shift F11` | Step out of current function scope | `vimspector#StepOut()` |
|
||||
| Key | Mapping | Function
|
||||
| --- | --- | ---
|
||||
| `F5` | `<Plug>VimspectorContinue` | When debugging, continue. Otherwise start debugging.
|
||||
| `Shift F5` | `<Plug>VimspectorStop` | Stop debugging.
|
||||
| `Ctrl Shift F5` | `<Plug>VimspectorRestart` | Restart debugging with the same configuration.
|
||||
| `F6` | `<Plug>VimspectorPause` | Pause debuggee.
|
||||
| `F9` | `<Plug>VimspectorToggleBreakpoint` | Toggle line breakpoint on the current line.
|
||||
| `Shift F9` | `<Plug>VimspectorAddFunctionBreakpoint` | Add a function breakpoint for the expression under cursor
|
||||
| `F10` | `<Plug>VimspectorStepOver` | Step Over
|
||||
| `F11` | `<Plug>VimspectorStepInto` | Step Into
|
||||
| `Shift F11` | `<Plug>VimspectorStepOut` | Step out of current function scope
|
||||
|
||||
## Human Mode
|
||||
|
||||
|
|
@ -720,19 +725,19 @@ loading vimspector**:
|
|||
let g:vimspector_enable_mappings = 'HUMAN'
|
||||
```
|
||||
|
||||
| Key | Function | API |
|
||||
| --- | --- | --- |
|
||||
| `F5` | When debugging, continue. Otherwise start debugging. | `vimspector#Continue()` |
|
||||
| `F3` | Stop debugging. | `vimspector#Stop()` |
|
||||
| `F4` | Restart debugging with the same configuration. | `vimspector#Restart()` |
|
||||
| `F6` | Pause debuggee. | `vimspector#Pause()` |
|
||||
| `F9` | Toggle line breakpoint on the current line. | `vimspector#ToggleBreakpoint()` |
|
||||
| `<leader>F9` | Toggle conditional line breakpoint on the current line. | `vimspector#ToggleBreakpoint( { trigger expr, hit count expr } )` |
|
||||
| `F8` | Add a function breakpoint for the expression under cursor | `vimspector#AddFunctionBreakpoint( '<cexpr>' )` |
|
||||
| `<leader>F8` | Run to Cursor | `vimspector#RunToCursor()` |
|
||||
| `F10` | Step Over | `vimspector#StepOver()` |
|
||||
| `F11` | Step Into | `vimspector#StepInto()` |
|
||||
| `F12` | Step out of current function scope | `vimspector#StepOut()` |
|
||||
| Key | Mapping | Function
|
||||
| --- | --- | ---
|
||||
| `F5` | `<Plug>VimspectorContinue` | When debugging, continue. Otherwise start debugging.
|
||||
| `F3` | `<Plug>VimspectorStop` | Stop debugging.
|
||||
| `F4` | `<Plug>VimspectorRestart` | Restart debugging with the same configuration.
|
||||
| `F6` | `<Plug>VimspectorPause` | Pause debuggee.
|
||||
| `F9` | `<Plug>VimspectorToggleBreakpoint` | Toggle line breakpoint on the current line.
|
||||
| `<leader>F9` | `<Plug>VimspectorToggleConditionalBreakpoint` | Toggle conditional line breakpoint on the current line.
|
||||
| `F8` | `<Plug>VimspectorAddFunctionBreakpoint` | Add a function breakpoint for the expression under cursor
|
||||
| `<leader>F8` | `<Plug>VimspectorRunToCursor` | Run to Cursor
|
||||
| `F10` | `<Plug>VimspectorStepOver` | Step Over
|
||||
| `F11` | `<Plug>VimspectorStepInto` | Step Into
|
||||
| `F12` | `<Plug>VimspectorStepOut` | Step out of current function scope
|
||||
|
||||
In addition, I recommend adding a mapping to `<Plug>VimspectorBalloonEval`, in
|
||||
normal and visual modes, for example:
|
||||
|
|
@ -746,6 +751,13 @@ nmap <Leader>di <Plug>VimspectorBalloonEval
|
|||
xmap <Leader>di <Plug>VimspectorBalloonEval
|
||||
```
|
||||
|
||||
You may also wish to add mappings for up/down the stack, for example:
|
||||
|
||||
```viml
|
||||
nmap <LocalLeader><F11> <Plug>VimspectorUpFrame
|
||||
nmap <LocalLeader><F12> <Plug>VimspectorDownFrame
|
||||
```
|
||||
|
||||
# Usage and API
|
||||
|
||||
This section defines detailed usage instructions, organised by feature. For most
|
||||
|
|
|
|||
|
|
@ -234,6 +234,20 @@ function! vimspector#GoToFrame() abort
|
|||
py3 _vimspector_session.ExpandFrameOrThread()
|
||||
endfunction
|
||||
|
||||
function! vimspector#UpFrame() abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.UpFrame()
|
||||
endfunction
|
||||
|
||||
function! vimspector#DownFrame() abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.DownFrame()
|
||||
endfunction
|
||||
|
||||
function! vimspector#AddWatch( ... ) abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
|
|
|
|||
|
|
@ -67,6 +67,11 @@ nnoremap <silent> <Plug>VimspectorBalloonEval
|
|||
xnoremap <silent> <Plug>VimspectorBalloonEval
|
||||
\ :<c-u>call vimspector#ShowEvalBalloon( 1 )<CR>
|
||||
|
||||
nnoremap <silent> <Plug>VimspectorUpFrame
|
||||
\ :<c-u>call vimspector#UpFrame()<CR>
|
||||
nnoremap <silent> <Plug>VimspectorDownFrame
|
||||
\ :<c-u>call vimspector#DownFrame()<CR>
|
||||
|
||||
if s:mappings ==# 'VISUAL_STUDIO'
|
||||
nmap <F5> <Plug>VimspectorContinue
|
||||
nmap <S-F5> <Plug>VimspectorStop
|
||||
|
|
|
|||
|
|
@ -571,6 +571,14 @@ class DebugSession( object ):
|
|||
def ExpandFrameOrThread( self ):
|
||||
self._stackTraceView.ExpandFrameOrThread()
|
||||
|
||||
@IfConnected()
|
||||
def UpFrame( self ):
|
||||
self._stackTraceView.UpFrame()
|
||||
|
||||
@IfConnected()
|
||||
def DownFrame( self ):
|
||||
self._stackTraceView.DownFrame()
|
||||
|
||||
def ToggleLog( self ):
|
||||
if self._HasUI():
|
||||
return self.ShowOutput( 'Vimspector' )
|
||||
|
|
|
|||
|
|
@ -367,6 +367,46 @@ class StackTraceView( object ):
|
|||
self._JumpToFrame( frame )
|
||||
|
||||
|
||||
|
||||
def _GetFrameOffset( self, delta ):
|
||||
thread: Thread
|
||||
for thread in self._threads:
|
||||
if thread.id != self._current_thread:
|
||||
continue
|
||||
|
||||
if not thread.stacktrace:
|
||||
return
|
||||
|
||||
frame_idx = None
|
||||
for index, frame in enumerate( thread.stacktrace ):
|
||||
if frame == self._current_frame:
|
||||
frame_idx = index
|
||||
break
|
||||
|
||||
if frame_idx is not None:
|
||||
target_idx = frame_idx + delta
|
||||
if target_idx >= 0 and target_idx < len( thread.stacktrace ):
|
||||
return thread.stacktrace[ target_idx ]
|
||||
|
||||
break
|
||||
|
||||
|
||||
def UpFrame( self ):
|
||||
frame = self._GetFrameOffset( 1 )
|
||||
if not frame:
|
||||
utils.UserMessage( 'Top of stack' )
|
||||
else:
|
||||
self._JumpToFrame( frame, 'up' )
|
||||
|
||||
|
||||
def DownFrame( self ):
|
||||
frame = self._GetFrameOffset( -1 )
|
||||
if not frame:
|
||||
utils.UserMessage( 'Bottom of stack' )
|
||||
else:
|
||||
self._JumpToFrame( frame, 'down' )
|
||||
|
||||
|
||||
def AnyThreadsRunning( self ):
|
||||
for thread in self._threads:
|
||||
if thread.state != Thread.TERMINATED:
|
||||
|
|
|
|||
|
|
@ -356,3 +356,117 @@ function! Test_Multiple_Threads_Step()
|
|||
call vimspector#test#setup#Reset()
|
||||
%bwipe!
|
||||
endfunction
|
||||
|
||||
function! Test_UpDownStack()
|
||||
let fn='../support/test/python/simple_python/main.py'
|
||||
exe 'edit ' . fn
|
||||
call setpos( '.', [ 0, 6, 1 ] )
|
||||
|
||||
call vimspector#SetLineBreakpoint( fn, 15 )
|
||||
call vimspector#LaunchWithSettings( { 'configuration': 'run' } )
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 )
|
||||
call WaitForAssert( {->
|
||||
\ AssertMatchist(
|
||||
\ [
|
||||
\ '- Thread 1: MainThread (paused)',
|
||||
\ ' 2: DoSomething@main.py:15',
|
||||
\ ' 3: __init__@main.py:8',
|
||||
\ ' 4: Main@main.py:23',
|
||||
\ ' 5: <module>@main.py:29',
|
||||
\ ],
|
||||
\ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ),
|
||||
\ 1,
|
||||
\ '$' )
|
||||
\ )
|
||||
\ } )
|
||||
|
||||
call vimspector#DownFrame()
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 )
|
||||
call WaitForAssert( {->
|
||||
\ AssertMatchist(
|
||||
\ [
|
||||
\ '- Thread 1: MainThread (paused)',
|
||||
\ ' 2: DoSomething@main.py:15',
|
||||
\ ' 3: __init__@main.py:8',
|
||||
\ ' 4: Main@main.py:23',
|
||||
\ ' 5: <module>@main.py:29',
|
||||
\ ],
|
||||
\ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ),
|
||||
\ 1,
|
||||
\ '$' )
|
||||
\ )
|
||||
\ } )
|
||||
|
||||
call vimspector#UpFrame()
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 )
|
||||
call WaitForAssert( {->
|
||||
\ AssertMatchist(
|
||||
\ [
|
||||
\ '- Thread 1: MainThread (paused)',
|
||||
\ ' 2: DoSomething@main.py:15',
|
||||
\ ' 3: __init__@main.py:8',
|
||||
\ ' 4: Main@main.py:23',
|
||||
\ ' 5: <module>@main.py:29',
|
||||
\ ],
|
||||
\ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ),
|
||||
\ 1,
|
||||
\ '$' )
|
||||
\ )
|
||||
\ } )
|
||||
|
||||
call feedkeys( "\<Plug>VimspectorUpFrame", 'x' )
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 23, 1 )
|
||||
call WaitForAssert( {->
|
||||
\ AssertMatchist(
|
||||
\ [
|
||||
\ '- Thread 1: MainThread (paused)',
|
||||
\ ' 2: DoSomething@main.py:15',
|
||||
\ ' 3: __init__@main.py:8',
|
||||
\ ' 4: Main@main.py:23',
|
||||
\ ' 5: <module>@main.py:29',
|
||||
\ ],
|
||||
\ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ),
|
||||
\ 1,
|
||||
\ '$' )
|
||||
\ )
|
||||
\ } )
|
||||
|
||||
call feedkeys( "\<Plug>VimspectorDownFrame", 'x' )
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 )
|
||||
call WaitForAssert( {->
|
||||
\ AssertMatchist(
|
||||
\ [
|
||||
\ '- Thread 1: MainThread (paused)',
|
||||
\ ' 2: DoSomething@main.py:15',
|
||||
\ ' 3: __init__@main.py:8',
|
||||
\ ' 4: Main@main.py:23',
|
||||
\ ' 5: <module>@main.py:29',
|
||||
\ ],
|
||||
\ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ),
|
||||
\ 1,
|
||||
\ '$' )
|
||||
\ )
|
||||
\ } )
|
||||
|
||||
call vimspector#DownFrame()
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 )
|
||||
call WaitForAssert( {->
|
||||
\ AssertMatchist(
|
||||
\ [
|
||||
\ '- Thread 1: MainThread (paused)',
|
||||
\ ' 2: DoSomething@main.py:15',
|
||||
\ ' 3: __init__@main.py:8',
|
||||
\ ' 4: Main@main.py:23',
|
||||
\ ' 5: <module>@main.py:29',
|
||||
\ ],
|
||||
\ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ),
|
||||
\ 1,
|
||||
\ '$' )
|
||||
\ )
|
||||
\ } )
|
||||
|
||||
|
||||
call vimspector#ClearBreakpoints()
|
||||
call vimspector#test#setup#Reset()
|
||||
%bwipe!
|
||||
endfunction
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue