diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index f5206ce..036e55e 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -89,6 +89,12 @@ function! vimspector#AddWatchPrompt( expr ) abort call vimspector#AddWatch( a:expr ) endfunction +function! vimspector#EvaluateConsole( expr ) abort + stopinsert + setlocal nomodified + py3 _vimspector_session.EvaluateConsole( vim.eval( 'a:expr' ) ) +endfunction + function! vimspector#ShowOutput( category ) abort py3 _vimspector_session.ShowOutput( vim.eval( 'a:category' ) ) endfunction diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 47af543..c581d20 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -243,6 +243,10 @@ class DebugSession( object ): self._variablesView.AddWatch( self._stackTraceView.GetCurrentFrame(), expression ) + def EvaluateConsole( self, expression ): + self._outputView.Evaluate( self._stackTraceView.GetCurrentFrame(), + expression ) + def DeleteWatch( self ): self._variablesView.DeleteWatch() @@ -304,7 +308,8 @@ class DebugSession( object ): # Output/logging vim.command( '10spl' ) vim.command( 'enew' ) - self._outputView = output.OutputView( vim.current.window ) + self._outputView = output.OutputView( self._connection, + vim.current.window ) def ClearCurrentFrame( self ): self.SetCurrentFrame( None ) @@ -371,6 +376,7 @@ class DebugSession( object ): self._connection = None self._stackTraceView.ConnectionClosed() self._variablesView.ConnectionClosed() + self._outputView.ConnectionClosed() if callback: callback() diff --git a/python3/vimspector/output.py b/python3/vimspector/output.py index cb91e51..0dd0bf7 100644 --- a/python3/vimspector/output.py +++ b/python3/vimspector/output.py @@ -18,22 +18,44 @@ from vimspector import utils import vim +BUFFER_MAP = { + 'console': 'Console', + 'stdout': 'Console' +} + + +def CategoryToBuffer( category ): + return BUFFER_MAP.get( category, category ) + + class OutputView( object ): - def __init__( self, window ): + def __init__( self, connection, window ): self._window = window + self._connection = connection self._buffers = {} - self._CreateBuffer( 'stdout' ) - self.ShowOutput( 'stdout' ) + for b in set( BUFFER_MAP.values() ): + self._CreateBuffer( b ) + + self.ShowOutput( 'Console' ) def OnOutput( self, event ): - category = event.get( 'category' ) or 'output' + category = CategoryToBuffer( event.get( 'category' ) or 'output' ) if category not in self._buffers: self._CreateBuffer( category ) - with utils.ModifiableScratchBuffer( self._buffers[ category ] ): - utils.AppendToBuffer( self._buffers[ category ], - event[ 'output' ].splitlines() ) + buf = self._buffers[ category ] + with utils.ModifiableScratchBuffer( buf ): + utils.AppendToBuffer( buf, event[ 'output' ].splitlines() ) + + # Scroll the buffer + with utils.RestoreCurrentWindow(): + with utils.RestoreCurrentBuffer( self._window ): + self.ShowOutput( category ) + vim.command( 'normal G' ) + + def ConnectionClosed( self ): + self._connection = None def Reset( self ): self.Clear() @@ -48,18 +70,42 @@ class OutputView( object ): vim.current.window = self._window vim.command( 'bu {0}'.format( self._buffers[ category ].name ) ) + def Evaluate( self, frame, expression ): + if not frame: + return + + console = self._buffers[ 'Console' ] + utils.AppendToBuffer( console, expression ) + + def print_result( message ): + utils.AppendToBuffer( console, message[ 'body' ][ 'result' ] ) + + self._connection.DoRequest( print_result, { + 'command': 'evaluate', + 'arguments': { + 'expression': expression, + 'context': 'repl', + 'frameId': frame[ 'id' ], + } + } ) + def _CreateBuffer( self, category ): - with utils.RestorCurrentWindow(): + with utils.RestoreCurrentWindow(): vim.current.window = self._window with utils.RestoreCurrentBuffer( self._window ): vim.command( 'enew' ) self._buffers[ category ] = vim.current.buffer - utils.AppendToBuffer( self._buffers[ category ], - category + '-----' ) - utils.SetUpHiddenBuffer( self._buffers[ category ], - 'vimspector.Output:{0}'.format( category ) ) + if category == 'Console': + utils.SetUpPromptBuffer( self._buffers[ category ], + 'vimspector.Console', + '> ', + 'vimspector#EvaluateConsole', + hidden = True ) + else: + utils.SetUpHiddenBuffer( self._buffers[ category ], + 'vimspector.Output:{0}'.format( category ) ) vim.command( "nnoremenu WinBar.{0} " ":call vimspector#ShowOutput( '{0}' )".format( diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 8633892..5800b8b 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -52,7 +52,7 @@ def SetUpHiddenBuffer( buf, name ): buf.options[ 'bufhidden' ] = 'hide' buf.name = name -def SetUpPromptBuffer( buf, name, prompt, callback ): +def SetUpPromptBuffer( buf, name, prompt, callback, hidden=False ): # This feature is _super_ new, so only enable when available if not int( vim.eval( "exists( '*prompt_setprompt' )" ) ): return SetUpScratchBuffer( buf, name ) @@ -63,7 +63,7 @@ def SetUpPromptBuffer( buf, name, prompt, callback ): buf.options[ 'modified' ] = False buf.options[ 'readonly' ] = False buf.options[ 'buflisted' ] = False - buf.options[ 'bufhidden' ] = 'wipe' + buf.options[ 'bufhidden' ] = 'wipe' if not hidden else 'hide' buf.name = name vim.eval( "prompt_setprompt( {0}, '{1}' )".format( buf.number, @@ -101,7 +101,7 @@ def RestoreCursorPosition(): @contextlib.contextmanager -def RestorCurrentWindow(): +def RestoreCurrentWindow(): # TODO: Don't trigger autoccommands when shifting windows old_window = vim.current.window try: @@ -117,7 +117,7 @@ def RestoreCurrentBuffer( window ): try: yield finally: - with RestorCurrentWindow(): + with RestoreCurrentWindow(): vim.current.window = window vim.current.buffer = old_buffer @@ -218,3 +218,7 @@ def AppendToBuffer( buf, line_or_lines ): def ClearBuffer( buf ): buf[:] = None + + +def IsCurrent( window, buf ): + return vim.current.window == window and vim.current.window.buffer == buf