Improve output view; use jobs to display logs and remote commands

This commit is contained in:
Ben Jackson 2019-02-12 09:04:52 +00:00
commit bb3909c16f
4 changed files with 86 additions and 63 deletions

View file

@ -211,7 +211,8 @@ class DebugSession( object ):
def OnServerStderr( self, data ):
self._logger.info( "Server stderr: %s", data )
if self._outputView:
self._outputView.ServerEcho( data )
self._outputView.Print( 'server', data )
def OnRequestTimeout( self, timer_id ):
if self._connection:
@ -461,11 +462,8 @@ class DebugSession( object ):
for index, item in enumerate( cmd ):
cmd[ index ] = item.replace( '%PID%', pid )
# TODO: Log files, etc. ?
self._logger.debug( 'Running remote app: %s', cmd )
self._attach_process = vim.eval(
'vimspector#internal#job#RunCommand( {} )'.format(
json.dumps( cmd ) ) )
self._outputView.RunJobWithOutput( 'Remote', cmd )
else:
if atttach_config[ 'pidSelect' ] == 'ask':
pid = utils.AskForInput( 'Enter PID to attach to: ' )
@ -478,7 +476,7 @@ class DebugSession( object ):
atttach_config[ 'pidSelect' ] ) )
def _PrepareRun( self, adapter_config, launch_config ):
def _PrepareLaunch( self, command_line, adapter_config, launch_config ):
run_config = adapter_config.get( 'launch', {} )
if 'remote' in run_config:
@ -490,10 +488,18 @@ class DebugSession( object ):
ssh.append( remote[ 'host' ] )
cmd = ssh + remote[ 'runCommand' ][:]
self._logger.debug( 'Running remote app: %s', cmd )
self._attach_process = vim.eval(
'vimspector#internal#job#RunCommand( {} )'.format(
json.dumps( cmd ) ) )
full_cmd = []
for item in cmd:
if isinstance( command_line, list ):
if item == '%CMD%':
full_cmd.extend( command_line )
else:
full_cmd.append( item )
else:
full_cmd.append( item.replace( '%CMD%', command_line ) )
self._logger.debug( 'Running remote app: %s', full_cmd )
self._outputView.RunJobWithOutput( 'Remote', full_cmd )
def _Initialise( self ):
@ -518,17 +524,24 @@ class DebugSession( object ):
def OnFailure( self, reason, message ):
msg = "Request for '{}' failed: {}".format( message[ 'command' ],
reason )
self._outputView.ServerEcho( msg )
self._outputView.Print( 'server', msg )
def _Launch( self ):
self._logger.debug( "LAUNCH!" )
adapter_config = self._adapter
launch_config = self._configuration[ 'configuration' ]
if launch_config.get( 'request' ) == "attach":
request = self._configuration.get(
'remote-request',
launch_config.get( 'request', 'launch' ) )
if request == "attach":
self._PrepareAttach( adapter_config, launch_config )
elif launch_config.get( 'request' ) == "run":
self._PrepareRun( adapter_config, launch_config )
elif request == "launch":
# FIXME: This cmdLine hack is not fun.
self._PrepareLaunch( self._configuration.get( 'remote-cmdLine', [] ),
adapter_config,
launch_config )
# FIXME: name is mandatory. Forcefully add it (we should really use the
# _actual_ name, but that isn't actually remembered at this point)
@ -730,6 +743,6 @@ class DebugSession( object ):
utils.UserMessage( msg, persist = True )
if self._outputView:
self._outputView.ServerEcho( msg )
self._outputView.Print( 'server', msg )
self._stackTraceView.OnStopped( event )

View file

@ -24,7 +24,7 @@ class TabBuffer( object ):
self.buf = buf
self.index = index
self.flag = False
self.job = None
self.is_job = False
BUFFER_MAP = {
@ -54,7 +54,7 @@ class OutputView( object ):
self._ShowOutput( 'Console' )
def ServerEcho( self, text ):
def Print( self, categroy, text ):
self._Print( 'server', text.splitlines() )
def OnOutput( self, event ):
@ -93,12 +93,10 @@ class OutputView( object ):
self.Clear()
def Clear( self ):
for buf in self._buffers:
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 )
for category, tab_buffer in self._buffers.items():
if tab_buffer.is_job:
utils.CleanUpCommand( category )
vim.command( 'bdelete! {0}'.format( tab_buffer.buf.number ) )
self._buffers.clear()
@ -113,6 +111,7 @@ class OutputView( object ):
def Evaluate( self, frame, expression ):
if not frame:
self.Print( 'Console', 'There is no current stack frame' )
return
console = self._buffers[ 'Console' ].buf
@ -144,17 +143,26 @@ class OutputView( object ):
vim.current.window = self._window
self._RenderWinBar( category )
def _CreateBuffer( self, category, file_name = None ):
def RunJobWithOutput( self, category, cmd ):
self._CreateBuffer( category, cmd = cmd )
def _CreateBuffer( self, category, file_name = None, cmd = None ):
with utils.RestoreCurrentWindow():
vim.current.window = self._window
with utils.RestoreCurrentBuffer( self._window ):
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
assert cmd is None
cmd = [ 'tail', '-F', '-n', '+1', '--', file_name ]
if cmd is not None:
buf = utils.SetUpCommandBuffer( cmd, category )
self._buffers[ category ] = TabBuffer( buf, len( self._buffers ) )
self._buffers[ category ].is_job = True
self._RenderWinBar( category )
else:
vim.command( 'enew' )
tab_buffer = TabBuffer( vim.current.buffer, len( self._buffers ) )
@ -170,7 +178,7 @@ class OutputView( object ):
tab_buffer.buf,
'vimspector.Output:{0}'.format( category ) )
self._RenderWinBar( category )
self._RenderWinBar( category )
def _RenderWinBar( self, category ):
tab_buffer = self._buffers[ category ]

View file

@ -51,15 +51,39 @@ def OpenFileInCurrentWindow( file_name ):
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 SetUpCommandBuffer( cmd, name ):
vim.command(
'let g:vimspector_command_job_{name} = job_start('
' {cmd},'
' {{'
' "out_io": "buffer",'
' "in_io": "null",'
' "err_io": "buffer",'
' "out_name": "_vimspector_log_{name}",'
' "err_name": "_vimspector_log_{name}",'
' "out_modifiable": 0,'
' "err_modifiable": 0,'
' "stoponexit": "term",'
' }} )'.format( name = name,
cmd = json.dumps( cmd ) ) )
stdout = vim.eval( 'ch_getbufnr( '
' job_getchannel( g:vimspector_command_job_{name} ), '
' "out"'
')'.format( name = name ) )
stderr = vim.eval( 'ch_getbufnr( '
' job_getchannel( g:vimspector_command_job_{name} ), '
' "err"'
')'.format( name = name ) )
assert stdout == stderr
return vim.buffers[ int( stdout ) ]
def CleanUpCommand( name ):
cmd = 'job_stop( g:vimspector_command_job_{name}, "kill" )'.format(
name = name )
vim.eval( cmd )
def TerminateJob( job ):
@ -253,14 +277,11 @@ def AppendToBuffer( buf, line_or_lines, modified=False ):
else:
line = 1
buf[:] = line_or_lines
except vim.error as e:
except:
# There seem to be a lot of Vim bugs that lead to E351, whose help says that
# this is an internal error. Ignore the error, but write a trace to the log.
if 'E315' in str( e ):
logging.getLogger( __name__ ).exception(
'Internal error while updating buffer' )
else:
raise e
logging.getLogger( __name__ ).exception(
'Internal error while updating buffer %s (%s)', buf.name, buf.number )
finally:
if not modified:
buf.options[ 'modified' ] = False