Display a different sign when there's a breakpoint on the PC line

Vim only renders a single sign-per-line. If we have the PC _and_ a
breakpoint, we should make that clear. Do this using a vimspectorPCBP
sign which combines both vimspectorPC and vimspectorBP (sort of).

We can't (unfortuantely) render the breakpoint blob in a different
colour, but it's at least obvious when we toggle on the PC line.
This commit is contained in:
Ben Jackson 2020-09-19 15:11:09 +01:00
commit 2ad1a3e502
5 changed files with 67 additions and 26 deletions

View file

@ -1405,6 +1405,7 @@ define them in your `vimrc`.
| `vimspectorBPCond` | Conditional line breakpiont | 9 | | `vimspectorBPCond` | Conditional line breakpiont | 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 |
The default symbols are the equivalent of something like the following: The default symbols are the equivalent of something like the following:
@ -1413,6 +1414,7 @@ sign define vimspectorBP text=\ ● texthl=WarningMsg
sign define vimspectorBPCond text=\ ◆ texthl=WarningMsg 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
``` ```
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
@ -1420,10 +1422,11 @@ glyphs. You can easily change them by deifining the sign in your vimrc. For
example, you could put this in your `vimrc` to use some simple ASCII symbols: example, you could put this in your `vimrc` to use some simple ASCII symbols:
```viml ```viml
sign define vimspectorBP text==> texthl=WarningMsg sign define vimspectorBP text=o texthl=WarningMsg
sign define vimspectorBPCond text=?> texthl=WarningMsg sign define vimspectorBPCond text=o? texthl=WarningMsg
sign define vimspectorBPDisabled text=!> 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 priority ## Sign priority

View file

@ -39,6 +39,7 @@ class CodeView( object ):
'vimspectorPC': None, 'vimspectorPC': None,
'breakpoints': [] 'breakpoints': []
} }
self._current_frame = None
with utils.LetCurrentWindow( self._window ): with utils.LetCurrentWindow( self._window ):
vim.command( 'nnoremenu WinBar.■\\ Stop :call vimspector#Stop()<CR>' ) vim.command( 'nnoremenu WinBar.■\\ Stop :call vimspector#Stop()<CR>' )
@ -55,6 +56,50 @@ class CodeView( object ):
text = '▶', text = '▶',
texthl = 'MatchParen', texthl = 'MatchParen',
linehl = 'CursorLine' ) linehl = 'CursorLine' )
if not signs.SignDefined( 'vimspectorPCBP' ):
signs.DefineSign( 'vimspectorPCBP',
text = '●▶',
texthl = 'MatchParen',
linehl = 'CursorLine' )
def _UndisplayPC( self ):
if self._signs[ 'vimspectorPC' ]:
signs.UnplaceSign( self._signs[ 'vimspectorPC' ], 'VimspectorCode' )
self._signs[ 'vimspectorPC' ] = None
def _DisplayPC( self ):
frame = self._current_frame
if not frame:
return
self._UndisplayPC()
# FIXME: Do we relly need to keep using up IDs ?
self._signs[ 'vimspectorPC' ] = self._next_sign_id
self._next_sign_id += 1
sign = 'vimspectorPC'
# If there's also a breakpoint on this line, use vimspectorPCBP
for bp in self._breakpoints.get( frame[ 'source' ][ 'path' ], [] ):
if 'line' not in bp:
continue
if bp[ 'line' ] == frame[ 'line' ]:
sign = 'vimspectorPCBP'
break
try:
signs.PlaceSign( self._signs[ 'vimspectorPC' ],
'VimspectorCode',
sign,
frame[ 'source' ][ 'path' ],
frame[ 'line' ] )
except vim.error as e:
# Ignore 'invalid buffer name'
if 'E158' not in str( e ):
raise
def SetCurrentFrame( self, frame ): def SetCurrentFrame( self, frame ):
@ -62,29 +107,16 @@ class CodeView( object ):
otherwise. False means either the frame is junk, we couldn't find the file otherwise. False means either the frame is junk, we couldn't find the file
(or don't have the data) or the code window no longer exits.""" (or don't have the data) or the code window no longer exits."""
if self._signs[ 'vimspectorPC' ]:
signs.UnplaceSign( self._signs[ 'vimspectorPC' ], 'VimspectorCode' )
self._signs[ 'vimspectorPC' ] = None
if not frame or not frame.get( 'source' ): if not frame or not frame.get( 'source' ):
self._UndisplayPC()
return False return False
if 'path' not in frame[ 'source' ]: if 'path' not in frame[ 'source' ]:
self._UndisplayPC()
return False return False
self._signs[ 'vimspectorPC' ] = self._next_sign_id self._current_frame = frame
self._next_sign_id += 1 self._DisplayPC()
try:
signs.PlaceSign( self._signs[ 'vimspectorPC' ],
'VimspectorCode',
'vimspectorPC',
frame[ 'source' ][ 'path' ],
frame[ 'line' ] )
except vim.error as e:
# Ignore 'invalid buffer name'
if 'E158' not in str( e ):
raise
if not self._window.valid: if not self._window.valid:
return False return False
@ -120,6 +152,7 @@ class CodeView( object ):
signs.UnplaceSign( self._signs[ 'vimspectorPC' ], 'VimspectorCode' ) signs.UnplaceSign( self._signs[ 'vimspectorPC' ], 'VimspectorCode' )
self._signs[ 'vimspectorPC' ] = None self._signs[ 'vimspectorPC' ] = None
self._current_frame = None
self._UndisplaySigns() self._UndisplaySigns()
self.current_syntax = None self.current_syntax = None
@ -187,6 +220,9 @@ class CodeView( object ):
file_name, file_name,
breakpoint[ 'line' ] ) breakpoint[ 'line' ] )
# We need to also check if there's a breakpoint on this PC line and chnge
# the PC
self._DisplayPC()
def BreakpointsAsQuickFix( self ): def BreakpointsAsQuickFix( self ):
qf = [] qf = []

View file

@ -29,6 +29,7 @@ DEFAULTS = {
# Signs # Signs
'sign_priority': { 'sign_priority': {
'vimspectorPC': 200, 'vimspectorPC': 200,
'vimspectorPCBP': 200,
'vimspectorBP': 9, 'vimspectorBP': 9,
'vimspectorBPCond': 9, 'vimspectorBPCond': 9,
'vimspectorBPDisabled': 9, 'vimspectorBPDisabled': 9,

View file

@ -551,6 +551,7 @@ endfunction
function! Test_Custom_Breakpoint_Priority() function! Test_Custom_Breakpoint_Priority()
let g:vimspector_sign_priority = { let g:vimspector_sign_priority = {
\ 'vimspectorPC': 1, \ 'vimspectorPC': 1,
\ 'vimspectorPCBP': 1,
\ 'vimspectorBP': 2, \ 'vimspectorBP': 2,
\ 'vimspectorBPCond': 3, \ 'vimspectorBPCond': 3,
\ 'vimspectorBPDisabled': 4 \ 'vimspectorBPDisabled': 4
@ -597,7 +598,7 @@ function! Test_Custom_Breakpoint_Priority()
call vimspector#test#signs#AssertSignAtLine( call vimspector#test#signs#AssertSignAtLine(
\ 'VimspectorCode', \ 'VimspectorCode',
\ 15, \ 15,
\ 'vimspectorPC', \ 'vimspectorPCBP',
\ 1 ) \ 1 )
call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorCode', call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorCode',
\ 17, \ 17,
@ -626,7 +627,7 @@ function! Test_Custom_Breakpoint_Priority()
call vimspector#test#signs#AssertSignAtLine( call vimspector#test#signs#AssertSignAtLine(
\ 'VimspectorCode', \ 'VimspectorCode',
\ 17, \ 17,
\ 'vimspectorPC', \ 'vimspectorPCBP',
\ 1 ) \ 1 )
@ -684,7 +685,7 @@ function! Test_Custom_Breakpoint_Priority_Partial()
call vimspector#test#signs#AssertSignAtLine( call vimspector#test#signs#AssertSignAtLine(
\ 'VimspectorCode', \ 'VimspectorCode',
\ 15, \ 15,
\ 'vimspectorPC', \ 'vimspectorPCBP',
\ 200 ) \ 200 )
call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorCode', call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorCode',
\ 17, \ 17,
@ -713,7 +714,7 @@ function! Test_Custom_Breakpoint_Priority_Partial()
call vimspector#test#signs#AssertSignAtLine( call vimspector#test#signs#AssertSignAtLine(
\ 'VimspectorCode', \ 'VimspectorCode',
\ 17, \ 17,
\ 'vimspectorPC', \ 'vimspectorPCBP',
\ 200 ) \ 200 )

View file

@ -32,7 +32,7 @@ function! vimspector#test#signs#AssertPCIsAtLineInBuffer( buffer, line ) abort
let index = 0 let index = 0
while index < len( signs[ 0 ].signs ) while index < len( signs[ 0 ].signs )
let s = signs[ 0 ].signs[ index ] let s = signs[ 0 ].signs[ index ]
if s.name ==# 'vimspectorPC' if s.name ==# 'vimspectorPC' || s.name ==# 'vimspectorPCBP'
if assert_false( pc_index >= 0, 'Too many PC signs' ) if assert_false( pc_index >= 0, 'Too many PC signs' )
return 1 return 1
endif endif