stack_trace: Add cursorline highlight and sign for current frame

This commit is contained in:
Ben Jackson 2021-05-04 21:59:44 +01:00
commit 9113dbb698
5 changed files with 150 additions and 27 deletions

View file

@ -1007,6 +1007,8 @@ be changed manually to "switch to" that thread.
to set the "focussed" thread to the currently selected one. If the selected to set the "focussed" thread to the currently selected one. If the selected
line is a stack frame, set the focussed thread to the thread of that frame and line is a stack frame, set the focussed thread to the thread of that frame and
jump to that frame in the code window. jump to that frame in the code window.
* The current frame when a breakpoint is hit or if manuall jumping is also
highlighted.
![stack trace](https://puremourning.github.io/vimspector-web/img/vimspector-callstack-window.png) ![stack trace](https://puremourning.github.io/vimspector-web/img/vimspector-callstack-window.png)
@ -1701,12 +1703,14 @@ define them in your `vimrc`.
| Sign | Description | Priority | | Sign | Description | Priority |
|------------------------|-------------------------------------|----------| |---------------------------|-----------------------------------------|----------|
| `vimspectorBP` | Line breakpoint | 9 | | `vimspectorBP` | Line breakpoint | 9 |
| `vimspectorBPCond` | Conditional line breakpoint | 9 | | `vimspectorBPCond` | Conditional line breakpoint | 9 |
| `vimspectorBPDisabled` | Disabled breakpoint | 9 | | `vimspectorBPDisabled` | Disabled breakpoint | 9 |
| `vimspectorPC` | Program counter (i.e. current line) | 200 | | `vimspectorPC` | Program counter (i.e. current line) | 200 |
| `vimspectorPCBP` | Program counter and breakpoint | 200 | | `vimspectorPCBP` | Program counter and breakpoint | 200 |
| `vimspectorCurrentThread` | Focussed thread in stack trace view | 200 |
| `vimspectorCurrentFrame` | Current stack frame in stack trace view | 200 |
The default symbols are the equivalent of something like the following: The default symbols are the equivalent of something like the following:
@ -1716,6 +1720,8 @@ sign define vimspectorBPCond text=\ ◆ texthl=WarningMsg
sign define vimspectorBPDisabled text=\ ● texthl=LineNr sign define vimspectorBPDisabled text=\ ● texthl=LineNr
sign define vimspectorPC text=\ ▶ texthl=MatchParen linehl=CursorLine sign define vimspectorPC text=\ ▶ texthl=MatchParen linehl=CursorLine
sign define vimspectorPCBP text=●▶ texthl=MatchParen linehl=CursorLine sign define vimspectorPCBP text=●▶ texthl=MatchParen linehl=CursorLine
sign define vimspectorCurrentThread text=▶ texthl=MatchParen linehl=CursorLine
sign define vimspectorCurrentFrame text=▶ texthl=Special linehl=CursorLine
``` ```
If the signs don't display properly, your font probably doesn't contain these If the signs don't display properly, your font probably doesn't contain these
@ -1728,6 +1734,8 @@ sign define vimspectorBPCond text=o? texthl=WarningMsg
sign define vimspectorBPDisabled text=o! texthl=LineNr sign define vimspectorBPDisabled text=o! texthl=LineNr
sign define vimspectorPC text=\ > texthl=MatchParen sign define vimspectorPC text=\ > texthl=MatchParen
sign define vimspectorPCBP text=o> texthl=MatchParen sign define vimspectorPCBP text=o> texthl=MatchParen
sign define vimspectorCurrentThread text=> texthl=MatchParen
sign define vimspectorCurrentFrame text=> texthl=Special
``` ```
## Sign priority ## Sign priority

View file

@ -42,7 +42,8 @@ DEFAULTS = {
'vimspectorBP': 9, 'vimspectorBP': 9,
'vimspectorBPCond': 9, 'vimspectorBPCond': 9,
'vimspectorBPDisabled': 9, 'vimspectorBPDisabled': 9,
'vimspectorCurrentThread': 200 'vimspectorCurrentThread': 200,
'vimspectorCurrentFrame': 200,
}, },
# Installer # Installer

View file

@ -102,7 +102,8 @@ class StackTraceView( object ):
self._scratch_buffers = [] self._scratch_buffers = []
# FIXME: This ID is by group, so should be module scope # FIXME: This ID is by group, so should be module scope
self._next_sign_id = 1 self._current_thread_sign_id = 0 # 1 when used
self._current_frame_sign_id = 0 # 2 when used
utils.SetUpHiddenBuffer( self._buf, 'vimspector.StackTrace' ) utils.SetUpHiddenBuffer( self._buf, 'vimspector.StackTrace' )
utils.SetUpUIWindow( win ) utils.SetUpUIWindow( win )
@ -127,6 +128,7 @@ class StackTraceView( object ):
':call vimspector#SetCurrentThread()<CR>' ) ':call vimspector#SetCurrentThread()<CR>' )
win.options[ 'cursorline' ] = False win.options[ 'cursorline' ] = False
win.options[ 'signcolumn' ] = 'auto'
if not signs.SignDefined( 'vimspectorCurrentThread' ): if not signs.SignDefined( 'vimspectorCurrentThread' ):
@ -136,6 +138,13 @@ class StackTraceView( object ):
texthl = 'MatchParen', texthl = 'MatchParen',
linehl = 'CursorLine' ) linehl = 'CursorLine' )
if not signs.SignDefined( 'vimspectorCurrentFrame' ):
signs.DefineSign( 'vimspectorCurrentFrame',
text = '▶ ',
double_text = '▶',
texthl = 'Special',
linehl = 'CursorLine' )
self._line_to_frame = {} self._line_to_frame = {}
self._line_to_thread = {} self._line_to_thread = {}
@ -157,9 +166,12 @@ class StackTraceView( object ):
self._sources = {} self._sources = {}
self._requesting_threads = StackTraceView.ThreadRequestState.NO self._requesting_threads = StackTraceView.ThreadRequestState.NO
self._pending_thread_request = None self._pending_thread_request = None
if self._next_sign_id: if self._current_thread_sign_id:
signs.UnplaceSign( self._next_sign_id, 'VimspectorStackTrace' ) signs.UnplaceSign( self._current_thread_sign_id, 'VimspectorStackTrace' )
self._next_sign_id = 0 self._current_thread_sign_id = 0
if self._current_frame_sign_id:
signs.UnplaceSign( self._current_frame_sign_id, 'VimspectorStackTrace' )
self._current_frame_sign_id = 0
with utils.ModifiableScratchBuffer( self._buf ): with utils.ModifiableScratchBuffer( self._buf ):
utils.ClearBuffer( self._buf ) utils.ClearBuffer( self._buf )
@ -273,10 +285,10 @@ class StackTraceView( object ):
self._line_to_frame.clear() self._line_to_frame.clear()
self._line_to_thread.clear() self._line_to_thread.clear()
if self._next_sign_id: if self._current_thread_sign_id:
signs.UnplaceSign( self._next_sign_id, 'VimspectorStackTrace' ) signs.UnplaceSign( self._current_thread_sign_id, 'VimspectorStackTrace' )
else: else:
self._next_sign_id = 1 self._current_thread_sign_id = 1
with utils.ModifiableScratchBuffer( self._buf ): with utils.ModifiableScratchBuffer( self._buf ):
with utils.RestoreCursorPosition(): with utils.RestoreCursorPosition():
@ -290,7 +302,7 @@ class StackTraceView( object ):
f'({thread.State()})' ) f'({thread.State()})' )
if self._current_thread == thread.id: if self._current_thread == thread.id:
signs.PlaceSign( self._next_sign_id, signs.PlaceSign( self._current_thread_sign_id,
'VimspectorStackTrace', 'VimspectorStackTrace',
'vimspectorCurrentThread', 'vimspectorCurrentThread',
self._buf.name, self._buf.name,
@ -421,6 +433,7 @@ class StackTraceView( object ):
# Should this set the current _Thread_ too ? If i jump to a frame in # Should this set the current _Thread_ too ? If i jump to a frame in
# Thread 2, should that become the focussed thread ? # Thread 2, should that become the focussed thread ?
self._current_frame = frame self._current_frame = frame
self._DrawThreads()
return self._session.SetCurrentFrame( self._current_frame, reason ) return self._session.SetCurrentFrame( self._current_frame, reason )
return False return False
@ -518,6 +531,11 @@ class StackTraceView( object ):
if not thread.IsExpanded(): if not thread.IsExpanded():
return return
if self._current_frame_sign_id:
signs.UnplaceSign( self._current_frame_sign_id, 'VimspectorStackTrace' )
else:
self._current_frame_sign_id = 2
for frame in thread.stacktrace: for frame in thread.stacktrace:
if frame.get( 'source' ): if frame.get( 'source' ):
source = frame[ 'source' ] source = frame[ 'source' ]
@ -542,6 +560,13 @@ class StackTraceView( object ):
source[ 'name' ], source[ 'name' ],
frame[ 'line' ] ) ) frame[ 'line' ] ) )
if self._current_frame[ 'id' ] == frame[ 'id' ]:
signs.PlaceSign( self._current_frame_sign_id,
'VimspectorStackTrace',
'vimspectorCurrentFrame',
self._buf.name,
line )
self._line_to_frame[ line ] = ( thread, frame ) self._line_to_frame[ line ] = ( thread, frame )
def _ResolveSource( self, source, and_then ): def _ResolveSource( self, source, and_then ):

View file

@ -1,4 +1,4 @@
def Settings( **kwargs ): def Settings( **kwargs ):
return { return {
'flags': [ '-x', 'c++', '-Wall', '-Wextra' ] 'flags': [ '-x', 'c++', '-Wall', '-Wextra', '-std=c++17' ]
} }

View file

@ -379,6 +379,20 @@ function! Test_UpDownStack()
\ '$' ) \ '$' )
\ ) \ )
\ } ) \ } )
call win_gotoid( g:vimspector_session_windows.stack_trace )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 1,
\ 'vimspectorCurrentThread',
\ 200 ) } )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 2,
\ 'vimspectorCurrentFrame',
\ 200 ) } )
wincmd w
call vimspector#DownFrame() call vimspector#DownFrame()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 )
@ -396,6 +410,21 @@ function! Test_UpDownStack()
\ '$' ) \ '$' )
\ ) \ )
\ } ) \ } )
call win_gotoid( g:vimspector_session_windows.stack_trace )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 1,
\ 'vimspectorCurrentThread',
\ 200 ) } )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 2,
\ 'vimspectorCurrentFrame',
\ 200 ) } )
wincmd w
call vimspector#UpFrame() call vimspector#UpFrame()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 )
@ -413,6 +442,21 @@ function! Test_UpDownStack()
\ '$' ) \ '$' )
\ ) \ )
\ } ) \ } )
call win_gotoid( g:vimspector_session_windows.stack_trace )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 1,
\ 'vimspectorCurrentThread',
\ 200 ) } )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 3,
\ 'vimspectorCurrentFrame',
\ 200 ) } )
wincmd w
call feedkeys( "\<Plug>VimspectorUpFrame", 'x' ) call feedkeys( "\<Plug>VimspectorUpFrame", 'x' )
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 23, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 23, 1 )
@ -430,6 +474,21 @@ function! Test_UpDownStack()
\ '$' ) \ '$' )
\ ) \ )
\ } ) \ } )
call win_gotoid( g:vimspector_session_windows.stack_trace )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 1,
\ 'vimspectorCurrentThread',
\ 200 ) } )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 4,
\ 'vimspectorCurrentFrame',
\ 200 ) } )
wincmd w
call feedkeys( "\<Plug>VimspectorDownFrame", 'x' ) call feedkeys( "\<Plug>VimspectorDownFrame", 'x' )
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 )
@ -447,6 +506,21 @@ function! Test_UpDownStack()
\ '$' ) \ '$' )
\ ) \ )
\ } ) \ } )
call win_gotoid( g:vimspector_session_windows.stack_trace )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 1,
\ 'vimspectorCurrentThread',
\ 200 ) } )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 3,
\ 'vimspectorCurrentFrame',
\ 200 ) } )
wincmd w
call vimspector#DownFrame() call vimspector#DownFrame()
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 )
@ -464,6 +538,21 @@ function! Test_UpDownStack()
\ '$' ) \ '$' )
\ ) \ )
\ } ) \ } )
call win_gotoid( g:vimspector_session_windows.stack_trace )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 1,
\ 'vimspectorCurrentThread',
\ 200 ) } )
call WaitForAssert( { ->
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
\ 'VimspectorStackTrace',
\ 2,
\ 'vimspectorCurrentFrame',
\ 200 ) } )
wincmd w
call vimspector#ClearBreakpoints() call vimspector#ClearBreakpoints()