From 463f7a8220b13d09a5cb451c952fecaaa5d6fa6e Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Mon, 4 Feb 2019 15:04:21 +0000 Subject: [PATCH] Mark unread output with *; Show vimspector log in output view --- python3/vimspector/code.py | 18 ++---- python3/vimspector/debug_session.py | 9 ++- python3/vimspector/output.py | 99 ++++++++++++++++++++++------- python3/vimspector/utils.py | 40 +++++++++++- 4 files changed, 129 insertions(+), 37 deletions(-) diff --git a/python3/vimspector/code.py b/python3/vimspector/code.py index 09fcc95..10299ec 100644 --- a/python3/vimspector/code.py +++ b/python3/vimspector/code.py @@ -64,18 +64,14 @@ class CodeView( object ): vim.current.window = self._window - buffer_number = int( vim.eval( 'bufnr( "{0}", 1 )'.format( - frame[ 'source' ][ 'path' ] ) ) ) - try: - vim.command( 'bu {0}'.format( buffer_number ) ) - self._window.cursor = ( frame[ 'line' ], frame[ 'column' ] ) - except vim.error as e: - if 'E325' not in str( e ): - self._logger.exception( - 'Unexpected error from vim: loading buffer {}'.format( - buffer_number ) ) - return False + utils.OpenFileInCurrentWindow( frame[ 'source' ][ 'path' ] ) + except vim.error: + self._logger.exception( 'Unexpected vim error opening file {}'.format( + frame[ 'source' ][ 'path' ] ) ) + return False + + self._window.cursor = ( frame[ 'line' ], frame[ 'column' ] ) self._signs[ 'vimspectorPC' ] = self._next_sign_id self._next_sign_id += 1 diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index e8dbef3..588b039 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -725,9 +725,12 @@ class DebugSession( object ): def OnEvent_stopped( self, message ): event = message[ 'body' ] - - utils.UserMessage( 'Paused in thread {0} due to {1}'.format( + msg = 'Paused in thread {0} due to {1}'.format( event.get( 'threadId', '' ), - event.get( 'description', event.get( 'reason', '' ) ) ) ) + event.get( 'description', event.get( 'reason', '' ) ) ) + utils.UserMessage( msg, persist = True ) + + if self._outputView: + self._outputView.ServerEcho( msg ) self._stackTraceView.OnStopped( event ) diff --git a/python3/vimspector/output.py b/python3/vimspector/output.py index 601183e..c3c0e0a 100644 --- a/python3/vimspector/output.py +++ b/python3/vimspector/output.py @@ -19,6 +19,14 @@ import vim import json +class TabBuffer( object ): + def __init__( self, buf, index ): + self.buf = buf + self.index = index + self.flag = False + self.job = None + + BUFFER_MAP = { 'console': 'Console', 'stdout': 'Console', @@ -40,7 +48,11 @@ class OutputView( object ): for b in set( BUFFER_MAP.values() ): self._CreateBuffer( b ) - self.ShowOutput( 'Console' ) + self._CreateBuffer( + 'Vimspector', + file_name = vim.eval( 'expand( "~/.vimspector.log" )' ) ) + + self._ShowOutput( 'Console' ) def ServerEcho( self, text ): self._Print( 'server', text.splitlines() ) @@ -58,15 +70,17 @@ class OutputView( object ): if category not in self._buffers: self._CreateBuffer( category ) - buf = self._buffers[ category ] + buf = self._buffers[ category ].buf + with utils.ModifiableScratchBuffer( buf ): utils.AppendToBuffer( buf, text_lines ) + self._ToggleFlag( category, True ) + # Scroll the buffer with utils.RestoreCurrentWindow(): with utils.RestoreCurrentBuffer( self._window ): - self.ShowOutput( category ) - vim.command( 'normal G' ) + self._ShowOutput( category ) def ConnectionClosed( self ): self._connection = None @@ -76,19 +90,28 @@ class OutputView( object ): def Clear( self ): for buf in self._buffers: - vim.command( 'bwipeout! {0}'.format( self._buffers[ buf ].name ) ) + vim.command( 'bwipeout! {0}'.format( self._buffers[ buf ].buf.name ) ) + + if 'Vimspector' in self._buffers: + if self._buffers[ 'Vimspector' ].job is not None: + utils.TerminateJob( self._buffers[ 'Vimspector' ].job ) self._buffers.clear() - def ShowOutput( self, category ): + def _ShowOutput( self, category ): vim.current.window = self._window - vim.command( 'bu {0}'.format( self._buffers[ category ].name ) ) + vim.command( 'bu {0}'.format( self._buffers[ category ].buf.name ) ) + vim.command( 'normal G' ) + + def ShowOutput( self, category ): + self._ToggleFlag( category, False ) + self._ShowOutput( category ) def Evaluate( self, frame, expression ): if not frame: return - console = self._buffers[ 'Console' ] + console = self._buffers[ 'Console' ].buf utils.AppendToBuffer( console, 'Evaluating: ' + expression ) def print_result( message ): @@ -110,24 +133,56 @@ class OutputView( object ): } } ) - def _CreateBuffer( self, category ): + def _ToggleFlag( self, category, flag ): + if self._buffers[ category ].flag != flag: + self._buffers[ category ].flag = flag + with utils.RestoreCurrentWindow(): + vim.current.window = self._window + self._RenderWinBar( category ) + + def _CreateBuffer( self, category, file_name = None ): with utils.RestoreCurrentWindow(): vim.current.window = self._window with utils.RestoreCurrentBuffer( self._window ): - vim.command( 'enew' ) - self._buffers[ category ] = vim.current.buffer - if category == 'Console': - utils.SetUpPromptBuffer( self._buffers[ category ], - 'vimspector.Console', - '> ', - 'vimspector#EvaluateConsole', - hidden=True ) + if file_name is not None: + tab_buffer = TabBuffer( utils.BufferForFile( file_name ), + len( self._buffers ) ) + tab_buffer.job = utils.SetUpTailBuffer( tab_buffer.buf, file_name ) + self._buffers[ category ] = tab_buffer else: - utils.SetUpHiddenBuffer( self._buffers[ category ], - 'vimspector.Output:{0}'.format( category ) ) + vim.command( 'enew' ) + tab_buffer = TabBuffer( vim.current.buffer, len( self._buffers ) ) + self._buffers[ category ] = tab_buffer + if category == 'Console': + utils.SetUpPromptBuffer( tab_buffer.buf, + 'vimspector.Console', + '> ', + 'vimspector#EvaluateConsole', + hidden=True ) + else: + utils.SetUpHiddenBuffer( + tab_buffer.buf, + 'vimspector.Output:{0}'.format( category ) ) - vim.command( "nnoremenu WinBar.{0} " - ":call vimspector#ShowOutput( '{0}' )".format( - utils.Escape( category ) ) ) + self._RenderWinBar( category ) + + def _RenderWinBar( self, category ): + tab_buffer = self._buffers[ category ] + + try: + if tab_buffer.flag: + vim.command( 'nunmenu WinBar.{}'.format( utils.Escape( category ) ) ) + else: + vim.command( 'nunmenu WinBar.{}*'.format( utils.Escape( category ) ) ) + except vim.error as e: + # E329 means the menu doesn't exist; ignore that. + if 'E329' not in str( e ): + raise + + vim.command( "nnoremenu 1.{0} WinBar.{1}{2} " + ":call vimspector#ShowOutput( '{1}' )".format( + tab_buffer.index, + utils.Escape( category ), + '*' if tab_buffer.flag else '' ) ) diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 53654fd..6d2213e 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -32,6 +32,41 @@ def SetUpLogging( logger ): logger.addHandler( _log_handler ) +def BufferNumberForFile( file_name ): + return int( vim.eval( 'bufnr( "{0}", 1 )'.format( file_name ) ) ) + + +def BufferForFile( file_name ): + return vim.buffers[ BufferNumberForFile( file_name ) ] + + +def OpenFileInCurrentWindow( file_name ): + buffer_number = BufferNumberForFile( file_name ) + try: + vim.command( 'bu {0}'.format( buffer_number ) ) + except vim.error as e: + if 'E325' not in str( e ): + raise + + return vim.buffers[ buffer_number ] + + +def SetUpTailBuffer( buf, path ): + cmd = [ 'tail', '-F', '-n', '0', '--', path ] + return vim.eval( 'job_start( {}, {{ "out_io": "buffer",' + ' "out_buf": {},' + ' "in_io": "null",' + ' "err_io": "null",' + ' "stoponexit": "term",' + ' "out_modifiable": 0 }} )'.format( + json.dumps( cmd ), buf.number ) ) + + +def TerminateJob( job ): + if vim.eval( 'job_status( {} )'.format( job ) ) == 'run': + vim.eval( 'job_stop( {} )'.format( job ) ) + + def SetUpScratchBuffer( buf, name ): buf.options[ 'buftype' ] = 'nofile' buf.options[ 'swapfile' ] = False @@ -199,7 +234,10 @@ def SelectFromList( prompt, options ): def AskForInput( prompt ): # TODO: Handle the ctrl-c and such responses returning empty or something with InputSave(): - return vim.eval( "input( '{0}' )".format( Escape( prompt ) ) ) + try: + return vim.eval( "input( '{0}' )".format( Escape( prompt ) ) ) + except KeyboardInterrupt: + return '' def AppendToBuffer( buf, line_or_lines, modified=False ):