diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index 942128a..de0c6c8 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -69,6 +69,10 @@ function! vimspector#GoToFrame() abort py3 _vimspector_session.GoToFrame() endfunction +function! vimspector#AddWatch( expr ) abort + py3 _vimspector_session.AddWatch( vim.eval( 'a:expr' ) ) +endfunction + " Boilerplate {{{ let &cpo=s:save_cpo unlet s:save_cpo diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 9a9f1e2..9674412 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -180,6 +180,9 @@ class DebugSession( object ): def ExpandVariable( self ): self._variablesView.ExpandVariable() + def AddWatch( self, expression ): + self._variablesView.AddWatch( self._currentFrame, expression ) + def GoToFrame( self ): self._stackTraceView.GoToFrame() @@ -221,6 +224,7 @@ class DebugSession( object ): self._currentFrame = frame self._codeView.SetCurrentFrame( frame ) self._variablesView.LoadScopes( frame ) + self._variablesView.EvaluateWatches() def _StartDebugAdapter( self ): self._logger.info( 'Starting debug adapter with: {0}'.format( json.dumps( diff --git a/python3/vimspector/variables.py b/python3/vimspector/variables.py index 831e0ab..daa0163 100644 --- a/python3/vimspector/variables.py +++ b/python3/vimspector/variables.py @@ -33,6 +33,9 @@ class VariablesView( object ): # children. Otherwise, we haven't or shouldn't. self._scopes = [] + # This is basically the same as scopes, but the top level is an "expression" + self._watches = [] + vim.current.buffer = buf vim.command( 'nnoremap :call vimspector#ExpandVariable()' ) @@ -55,7 +58,7 @@ class VariablesView( object ): }, } ) - self._DrawScopes() + self._DrawScopesAndWatches() self._connection.DoRequest( scopes_consumer, { 'command': 'scopes', @@ -64,6 +67,36 @@ class VariablesView( object ): }, } ) + def AddWatch( self, frame, expression ): + watch = { + 'expression': expression, + 'frameId': frame[ 'id' ], + 'context': 'watch', + } + self._watches.append( watch ) + self.EvaluateWatches() + + def EvaluateWatches( self ): + for watch in self._watches: + self._connection.DoRequest( partial( self._UpdateWatchExpression, + watch ), { + 'command': 'evaluate', + 'arguments': watch, + } ) + + def _UpdateWatchExpression( self, watch, message ): + 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() + def ExpandVariable( self ): if vim.current.window.buffer != self._buf: return @@ -75,7 +108,7 @@ class VariablesView( object ): variable = self._line_to_variable[ current_line ] if '_variables' in variable: del variable[ '_variables' ] - self._DrawScopes() + self._DrawScopesAndWatches() else: self._connection.DoRequest( partial( self._ConsumeVariables, variable ), { 'command': 'variables', @@ -93,13 +126,13 @@ class VariablesView( object ): '_variables' not in variable ) else '-', name = variable[ 'name' ], type_ = variable.get( 'type', '' ), - value = variable[ 'value' ] ) ) + value = variable[ 'value' ] ).split( '\n' ) ) self._line_to_variable[ len( self._buf ) ] = variable if '_variables' in variable: self._DrawVariables( variable[ '_variables' ], indent + 2 ) - def _DrawScopes( self ): + def _DrawScopesAndWatches( self ): self._line_to_variable = {} with utils.RestoreCursorPosition(): with utils.ModifiableScratchBuffer( self._buf ): @@ -110,6 +143,16 @@ class VariablesView( object ): indent = 2 self._DrawVariables( scope[ '_variables' ], indent ) + self._buf.append( 'Watches: ----' ) + for watch in self._watches: + self._buf.append( 'Expression: ' + watch[ 'expression' ] ) + if 'result' in watch: + result = watch[ 'result' ] + line = ' Result: ' + result[ 'result' ] + self._buf.append( line.split( '\n' ) ) + if '_variables' in result: + indent = 4 + self._DrawVariables( result[ '_variables' ], indent ) def _ConsumeVariables( self, parent, message ): for variable in message[ 'body' ][ 'variables' ]: @@ -118,4 +161,4 @@ class VariablesView( object ): parent[ '_variables' ].append( variable ) - self._DrawScopes() + self._DrawScopesAndWatches()