Allow deleting watches and improve expansion
Now scopes and watch results can be expanded/collapsed. Locals still default to being expanded, but watches do not.
This commit is contained in:
parent
437dbe8776
commit
3f73d1c2f8
4 changed files with 71 additions and 26 deletions
|
|
@ -65,6 +65,10 @@ function! vimspector#ExpandVariable() abort
|
||||||
py3 _vimspector_session.ExpandVariable()
|
py3 _vimspector_session.ExpandVariable()
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function! vimspector#DeleteWatch() abort
|
||||||
|
py3 _vimspector_session.DeleteWatch()
|
||||||
|
endfunction
|
||||||
|
|
||||||
function! vimspector#GoToFrame() abort
|
function! vimspector#GoToFrame() abort
|
||||||
py3 _vimspector_session.GoToFrame()
|
py3 _vimspector_session.GoToFrame()
|
||||||
endfunction
|
endfunction
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,9 @@ class DebugSession( object ):
|
||||||
def AddWatch( self, expression ):
|
def AddWatch( self, expression ):
|
||||||
self._variablesView.AddWatch( self._currentFrame, expression )
|
self._variablesView.AddWatch( self._currentFrame, expression )
|
||||||
|
|
||||||
|
def DeleteWatch( self ):
|
||||||
|
self._variablesView.DeleteWatch()
|
||||||
|
|
||||||
def GoToFrame( self ):
|
def GoToFrame( self ):
|
||||||
self._stackTraceView.GoToFrame()
|
self._stackTraceView.GoToFrame()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,9 @@ def RestoreCursorPosition():
|
||||||
try:
|
try:
|
||||||
yield
|
yield
|
||||||
finally:
|
finally:
|
||||||
vim.current.window.cursor = current_pos
|
vim.current.window.cursor = (
|
||||||
|
min( current_pos[ 0 ], len( vim.current.buffer ) ),
|
||||||
|
current_pos[ 1 ] )
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,11 @@ class VariablesView( object ):
|
||||||
def __init__( self, connection, buf ):
|
def __init__( self, connection, buf ):
|
||||||
self._buf = buf
|
self._buf = buf
|
||||||
self._connection = connection
|
self._connection = connection
|
||||||
|
|
||||||
|
# Allows us to hit <CR> to expand/collapse variables
|
||||||
self._line_to_variable = {}
|
self._line_to_variable = {}
|
||||||
|
vim.command(
|
||||||
|
'nnoremap <buffer> <CR> :call vimspector#ExpandVariable()<CR>' )
|
||||||
|
|
||||||
# This is actually the tree (scopes are alwyas the root)
|
# This is actually the tree (scopes are alwyas the root)
|
||||||
# it's just a list of DAP scope dicts, with one magic key (_variables)
|
# it's just a list of DAP scope dicts, with one magic key (_variables)
|
||||||
|
|
@ -33,12 +37,17 @@ class VariablesView( object ):
|
||||||
# children. Otherwise, we haven't or shouldn't.
|
# children. Otherwise, we haven't or shouldn't.
|
||||||
self._scopes = []
|
self._scopes = []
|
||||||
|
|
||||||
# This is basically the same as scopes, but the top level is an "expression"
|
# This is similar to scopes, but the top level is an "expression" (request)
|
||||||
|
# containing a special '_result' key which is the response. The response
|
||||||
|
# structure con contain _variables and is handled identically to the scopes
|
||||||
|
# above. It also has a special _line key which is where we printed it (last)
|
||||||
self._watches = []
|
self._watches = []
|
||||||
|
|
||||||
vim.current.buffer = buf
|
# Allows us to delete manual watches
|
||||||
vim.command(
|
vim.command(
|
||||||
'nnoremap <buffer> <CR> :call vimspector#ExpandVariable()<CR>' )
|
'nnoremap <buffer> <DEL> :call vimspector#DeleteWatch()<CR>' )
|
||||||
|
|
||||||
|
vim.current.buffer = buf
|
||||||
|
|
||||||
utils.SetUpScratchBuffer( self._buf )
|
utils.SetUpScratchBuffer( self._buf )
|
||||||
|
|
||||||
|
|
@ -76,6 +85,18 @@ class VariablesView( object ):
|
||||||
self._watches.append( watch )
|
self._watches.append( watch )
|
||||||
self.EvaluateWatches()
|
self.EvaluateWatches()
|
||||||
|
|
||||||
|
def DeleteWatch( self ):
|
||||||
|
if vim.current.window.buffer != self._buf:
|
||||||
|
return
|
||||||
|
|
||||||
|
current_line = vim.current.window.cursor[ 0 ]
|
||||||
|
|
||||||
|
for index, watch in enumerate( self._watches ):
|
||||||
|
if '_line' in watch and watch[ '_line' ] == current_line:
|
||||||
|
del self._watches[ index ]
|
||||||
|
self._DrawScopesAndWatches()
|
||||||
|
return
|
||||||
|
|
||||||
def EvaluateWatches( self ):
|
def EvaluateWatches( self ):
|
||||||
for watch in self._watches:
|
for watch in self._watches:
|
||||||
self._connection.DoRequest( partial( self._UpdateWatchExpression,
|
self._connection.DoRequest( partial( self._UpdateWatchExpression,
|
||||||
|
|
@ -85,16 +106,7 @@ class VariablesView( object ):
|
||||||
} )
|
} )
|
||||||
|
|
||||||
def _UpdateWatchExpression( self, watch, message ):
|
def _UpdateWatchExpression( self, watch, message ):
|
||||||
watch[ 'result' ] = message[ 'body' ]
|
watch[ '_result' ] = message[ 'body' ]
|
||||||
if 'variablesReference' in watch[ 'result' ]:
|
|
||||||
self._connection.DoRequest(
|
|
||||||
partial( self._ConsumeVariables, watch[ 'result' ] ), {
|
|
||||||
'command': 'variables',
|
|
||||||
'arguments': {
|
|
||||||
'variablesReference': watch[ 'result' ][ 'variablesReference' ]
|
|
||||||
},
|
|
||||||
} )
|
|
||||||
|
|
||||||
self._DrawScopesAndWatches()
|
self._DrawScopesAndWatches()
|
||||||
|
|
||||||
def ExpandVariable( self ):
|
def ExpandVariable( self ):
|
||||||
|
|
@ -119,6 +131,7 @@ class VariablesView( object ):
|
||||||
|
|
||||||
def _DrawVariables( self, variables, indent ):
|
def _DrawVariables( self, variables, indent ):
|
||||||
for variable in variables:
|
for variable in variables:
|
||||||
|
self._line_to_variable[ len( self._buf ) + 1 ] = variable
|
||||||
self._buf.append(
|
self._buf.append(
|
||||||
'{indent}{icon} {name} ({type_}): {value}'.format(
|
'{indent}{icon} {name} ({type_}): {value}'.format(
|
||||||
indent = ' ' * indent,
|
indent = ' ' * indent,
|
||||||
|
|
@ -127,7 +140,6 @@ class VariablesView( object ):
|
||||||
name = variable[ 'name' ],
|
name = variable[ 'name' ],
|
||||||
type_ = variable.get( 'type', '<unknown type>' ),
|
type_ = variable.get( 'type', '<unknown type>' ),
|
||||||
value = variable[ 'value' ] ).split( '\n' ) )
|
value = variable[ 'value' ] ).split( '\n' ) )
|
||||||
self._line_to_variable[ len( self._buf ) ] = variable
|
|
||||||
|
|
||||||
if '_variables' in variable:
|
if '_variables' in variable:
|
||||||
self._DrawVariables( variable[ '_variables' ], indent + 2 )
|
self._DrawVariables( variable[ '_variables' ], indent + 2 )
|
||||||
|
|
@ -138,21 +150,45 @@ class VariablesView( object ):
|
||||||
with utils.ModifiableScratchBuffer( self._buf ):
|
with utils.ModifiableScratchBuffer( self._buf ):
|
||||||
self._buf[:] = None
|
self._buf[:] = None
|
||||||
for scope in self._scopes:
|
for scope in self._scopes:
|
||||||
self._buf.append( 'Scope: ' + scope[ 'name' ] )
|
self._DrawScope( 0, scope )
|
||||||
if '_variables' in scope:
|
|
||||||
indent = 2
|
|
||||||
self._DrawVariables( scope[ '_variables' ], indent )
|
|
||||||
|
|
||||||
self._buf.append( 'Watches: ----' )
|
self._buf.append( 'Watches: ----' )
|
||||||
for watch in self._watches:
|
for watch in self._watches:
|
||||||
self._buf.append( 'Expression: ' + watch[ 'expression' ] )
|
self._buf.append( 'Expression: ' + watch[ 'expression' ] )
|
||||||
if 'result' in watch:
|
watch[ '_line' ] = len( self._buf )
|
||||||
result = watch[ 'result' ]
|
self._DrawWatchResult( 2, watch )
|
||||||
line = ' Result: ' + result[ 'result' ]
|
|
||||||
self._buf.append( line.split( '\n' ) )
|
def _DrawScope( self, indent, scope ):
|
||||||
if '_variables' in result:
|
icon = '+' if ( scope[ 'variablesReference' ] > 0 and
|
||||||
indent = 4
|
'_variables' not in scope ) else '-'
|
||||||
self._DrawVariables( result[ '_variables' ], indent )
|
|
||||||
|
self._line_to_variable[ len( self._buf ) + 1 ] = scope
|
||||||
|
self._buf.append( '{0}{1} Scope: {2}'.format( ' ' * indent,
|
||||||
|
icon,
|
||||||
|
scope[ 'name' ] ) )
|
||||||
|
|
||||||
|
if '_variables' in scope:
|
||||||
|
indent += 2
|
||||||
|
self._DrawVariables( scope[ '_variables' ], indent )
|
||||||
|
|
||||||
|
def _DrawWatchResult( self, indent, watch ):
|
||||||
|
if '_result' not in watch:
|
||||||
|
return
|
||||||
|
|
||||||
|
result = watch[ '_result' ]
|
||||||
|
self._line_to_variable[ len( self._buf ) + 1 ] = result
|
||||||
|
|
||||||
|
icon = '+' if ( result[ 'variablesReference' ] > 0 and
|
||||||
|
'_variables' not in result ) else '-'
|
||||||
|
|
||||||
|
line = '{0}{1} Result: {2} '.format( ' ' * indent,
|
||||||
|
icon,
|
||||||
|
result[ 'result' ] )
|
||||||
|
self._buf.append( line.split( '\n' ) )
|
||||||
|
|
||||||
|
if '_variables' in result:
|
||||||
|
indent = 4
|
||||||
|
self._DrawVariables( result[ '_variables' ], indent )
|
||||||
|
|
||||||
def _ConsumeVariables( self, parent, message ):
|
def _ConsumeVariables( self, parent, message ):
|
||||||
for variable in message[ 'body' ][ 'variables' ]:
|
for variable in message[ 'body' ][ 'variables' ]:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue