Improve output view; use jobs to display logs and remote commands
This commit is contained in:
parent
e006b15100
commit
bb3909c16f
4 changed files with 86 additions and 63 deletions
|
|
@ -58,25 +58,6 @@ function! s:_Send( msg ) abort
|
||||||
return 1
|
return 1
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! vimspector#internal#job#RunCommand( cmd ) abort
|
|
||||||
return job_start( a:cmd,
|
|
||||||
\ {
|
|
||||||
\ 'in_mode': 'raw',
|
|
||||||
\ 'out_mode': 'raw',
|
|
||||||
\ 'err_mode': 'raw',
|
|
||||||
\ 'out_cb': funcref( 's:_OnServerError' ),
|
|
||||||
\ 'err_cb': funcref( 's:_OnServerError' ),
|
|
||||||
\ 'stoponexit': 'term',
|
|
||||||
\ }
|
|
||||||
\ )
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! vimspector#internal#job#KillCommand( job ) abort
|
|
||||||
if job_status( a:job ) == 'run'
|
|
||||||
call job_stop( a:job, 'term' )
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! vimspector#internal#job#StartDebugSession( config ) abort
|
function! vimspector#internal#job#StartDebugSession( config ) abort
|
||||||
if exists( 's:job' )
|
if exists( 's:job' )
|
||||||
echom "Not starging: Job is already running"
|
echom "Not starging: Job is already running"
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,8 @@ class DebugSession( object ):
|
||||||
def OnServerStderr( self, data ):
|
def OnServerStderr( self, data ):
|
||||||
self._logger.info( "Server stderr: %s", data )
|
self._logger.info( "Server stderr: %s", data )
|
||||||
if self._outputView:
|
if self._outputView:
|
||||||
self._outputView.ServerEcho( data )
|
self._outputView.Print( 'server', data )
|
||||||
|
|
||||||
|
|
||||||
def OnRequestTimeout( self, timer_id ):
|
def OnRequestTimeout( self, timer_id ):
|
||||||
if self._connection:
|
if self._connection:
|
||||||
|
|
@ -461,11 +462,8 @@ class DebugSession( object ):
|
||||||
for index, item in enumerate( cmd ):
|
for index, item in enumerate( cmd ):
|
||||||
cmd[ index ] = item.replace( '%PID%', pid )
|
cmd[ index ] = item.replace( '%PID%', pid )
|
||||||
|
|
||||||
# TODO: Log files, etc. ?
|
|
||||||
self._logger.debug( 'Running remote app: %s', cmd )
|
self._logger.debug( 'Running remote app: %s', cmd )
|
||||||
self._attach_process = vim.eval(
|
self._outputView.RunJobWithOutput( 'Remote', cmd )
|
||||||
'vimspector#internal#job#RunCommand( {} )'.format(
|
|
||||||
json.dumps( cmd ) ) )
|
|
||||||
else:
|
else:
|
||||||
if atttach_config[ 'pidSelect' ] == 'ask':
|
if atttach_config[ 'pidSelect' ] == 'ask':
|
||||||
pid = utils.AskForInput( 'Enter PID to attach to: ' )
|
pid = utils.AskForInput( 'Enter PID to attach to: ' )
|
||||||
|
|
@ -478,7 +476,7 @@ class DebugSession( object ):
|
||||||
atttach_config[ 'pidSelect' ] ) )
|
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', {} )
|
run_config = adapter_config.get( 'launch', {} )
|
||||||
|
|
||||||
if 'remote' in run_config:
|
if 'remote' in run_config:
|
||||||
|
|
@ -490,10 +488,18 @@ class DebugSession( object ):
|
||||||
ssh.append( remote[ 'host' ] )
|
ssh.append( remote[ 'host' ] )
|
||||||
|
|
||||||
cmd = ssh + remote[ 'runCommand' ][:]
|
cmd = ssh + remote[ 'runCommand' ][:]
|
||||||
self._logger.debug( 'Running remote app: %s', cmd )
|
full_cmd = []
|
||||||
self._attach_process = vim.eval(
|
for item in cmd:
|
||||||
'vimspector#internal#job#RunCommand( {} )'.format(
|
if isinstance( command_line, list ):
|
||||||
json.dumps( cmd ) ) )
|
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 ):
|
def _Initialise( self ):
|
||||||
|
|
@ -518,17 +524,24 @@ class DebugSession( object ):
|
||||||
def OnFailure( self, reason, message ):
|
def OnFailure( self, reason, message ):
|
||||||
msg = "Request for '{}' failed: {}".format( message[ 'command' ],
|
msg = "Request for '{}' failed: {}".format( message[ 'command' ],
|
||||||
reason )
|
reason )
|
||||||
self._outputView.ServerEcho( msg )
|
self._outputView.Print( 'server', msg )
|
||||||
|
|
||||||
def _Launch( self ):
|
def _Launch( self ):
|
||||||
self._logger.debug( "LAUNCH!" )
|
self._logger.debug( "LAUNCH!" )
|
||||||
adapter_config = self._adapter
|
adapter_config = self._adapter
|
||||||
launch_config = self._configuration[ 'configuration' ]
|
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 )
|
self._PrepareAttach( adapter_config, launch_config )
|
||||||
elif launch_config.get( 'request' ) == "run":
|
elif request == "launch":
|
||||||
self._PrepareRun( adapter_config, launch_config )
|
# 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
|
# FIXME: name is mandatory. Forcefully add it (we should really use the
|
||||||
# _actual_ name, but that isn't actually remembered at this point)
|
# _actual_ name, but that isn't actually remembered at this point)
|
||||||
|
|
@ -730,6 +743,6 @@ class DebugSession( object ):
|
||||||
utils.UserMessage( msg, persist = True )
|
utils.UserMessage( msg, persist = True )
|
||||||
|
|
||||||
if self._outputView:
|
if self._outputView:
|
||||||
self._outputView.ServerEcho( msg )
|
self._outputView.Print( 'server', msg )
|
||||||
|
|
||||||
self._stackTraceView.OnStopped( event )
|
self._stackTraceView.OnStopped( event )
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ class TabBuffer( object ):
|
||||||
self.buf = buf
|
self.buf = buf
|
||||||
self.index = index
|
self.index = index
|
||||||
self.flag = False
|
self.flag = False
|
||||||
self.job = None
|
self.is_job = False
|
||||||
|
|
||||||
|
|
||||||
BUFFER_MAP = {
|
BUFFER_MAP = {
|
||||||
|
|
@ -54,7 +54,7 @@ class OutputView( object ):
|
||||||
|
|
||||||
self._ShowOutput( 'Console' )
|
self._ShowOutput( 'Console' )
|
||||||
|
|
||||||
def ServerEcho( self, text ):
|
def Print( self, categroy, text ):
|
||||||
self._Print( 'server', text.splitlines() )
|
self._Print( 'server', text.splitlines() )
|
||||||
|
|
||||||
def OnOutput( self, event ):
|
def OnOutput( self, event ):
|
||||||
|
|
@ -93,12 +93,10 @@ class OutputView( object ):
|
||||||
self.Clear()
|
self.Clear()
|
||||||
|
|
||||||
def Clear( self ):
|
def Clear( self ):
|
||||||
for buf in self._buffers:
|
for category, tab_buffer in self._buffers.items():
|
||||||
vim.command( 'bwipeout! {0}'.format( self._buffers[ buf ].buf.name ) )
|
if tab_buffer.is_job:
|
||||||
|
utils.CleanUpCommand( category )
|
||||||
if 'Vimspector' in self._buffers:
|
vim.command( 'bdelete! {0}'.format( tab_buffer.buf.number ) )
|
||||||
if self._buffers[ 'Vimspector' ].job is not None:
|
|
||||||
utils.TerminateJob( self._buffers[ 'Vimspector' ].job )
|
|
||||||
|
|
||||||
self._buffers.clear()
|
self._buffers.clear()
|
||||||
|
|
||||||
|
|
@ -113,6 +111,7 @@ class OutputView( object ):
|
||||||
|
|
||||||
def Evaluate( self, frame, expression ):
|
def Evaluate( self, frame, expression ):
|
||||||
if not frame:
|
if not frame:
|
||||||
|
self.Print( 'Console', 'There is no current stack frame' )
|
||||||
return
|
return
|
||||||
|
|
||||||
console = self._buffers[ 'Console' ].buf
|
console = self._buffers[ 'Console' ].buf
|
||||||
|
|
@ -144,17 +143,26 @@ class OutputView( object ):
|
||||||
vim.current.window = self._window
|
vim.current.window = self._window
|
||||||
self._RenderWinBar( category )
|
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():
|
with utils.RestoreCurrentWindow():
|
||||||
vim.current.window = self._window
|
vim.current.window = self._window
|
||||||
|
|
||||||
with utils.RestoreCurrentBuffer( self._window ):
|
with utils.RestoreCurrentBuffer( self._window ):
|
||||||
|
|
||||||
if file_name is not None:
|
if file_name is not None:
|
||||||
tab_buffer = TabBuffer( utils.BufferForFile( file_name ),
|
assert cmd is None
|
||||||
len( self._buffers ) )
|
cmd = [ 'tail', '-F', '-n', '+1', '--', file_name ]
|
||||||
tab_buffer.job = utils.SetUpTailBuffer( tab_buffer.buf, file_name )
|
|
||||||
self._buffers[ category ] = tab_buffer
|
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:
|
else:
|
||||||
vim.command( 'enew' )
|
vim.command( 'enew' )
|
||||||
tab_buffer = TabBuffer( vim.current.buffer, len( self._buffers ) )
|
tab_buffer = TabBuffer( vim.current.buffer, len( self._buffers ) )
|
||||||
|
|
|
||||||
|
|
@ -51,15 +51,39 @@ def OpenFileInCurrentWindow( file_name ):
|
||||||
return vim.buffers[ buffer_number ]
|
return vim.buffers[ buffer_number ]
|
||||||
|
|
||||||
|
|
||||||
def SetUpTailBuffer( buf, path ):
|
def SetUpCommandBuffer( cmd, name ):
|
||||||
cmd = [ 'tail', '-F', '-n', '0', '--', path ]
|
vim.command(
|
||||||
return vim.eval( 'job_start( {}, {{ "out_io": "buffer",'
|
'let g:vimspector_command_job_{name} = job_start('
|
||||||
' "out_buf": {},'
|
' {cmd},'
|
||||||
|
' {{'
|
||||||
|
' "out_io": "buffer",'
|
||||||
' "in_io": "null",'
|
' "in_io": "null",'
|
||||||
' "err_io": "null",'
|
' "err_io": "buffer",'
|
||||||
|
' "out_name": "_vimspector_log_{name}",'
|
||||||
|
' "err_name": "_vimspector_log_{name}",'
|
||||||
|
' "out_modifiable": 0,'
|
||||||
|
' "err_modifiable": 0,'
|
||||||
' "stoponexit": "term",'
|
' "stoponexit": "term",'
|
||||||
' "out_modifiable": 0 }} )'.format(
|
' }} )'.format( name = name,
|
||||||
json.dumps( cmd ), buf.number ) )
|
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 ):
|
def TerminateJob( job ):
|
||||||
|
|
@ -253,14 +277,11 @@ def AppendToBuffer( buf, line_or_lines, modified=False ):
|
||||||
else:
|
else:
|
||||||
line = 1
|
line = 1
|
||||||
buf[:] = line_or_lines
|
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
|
# 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.
|
# this is an internal error. Ignore the error, but write a trace to the log.
|
||||||
if 'E315' in str( e ):
|
|
||||||
logging.getLogger( __name__ ).exception(
|
logging.getLogger( __name__ ).exception(
|
||||||
'Internal error while updating buffer' )
|
'Internal error while updating buffer %s (%s)', buf.name, buf.number )
|
||||||
else:
|
|
||||||
raise e
|
|
||||||
finally:
|
finally:
|
||||||
if not modified:
|
if not modified:
|
||||||
buf.options[ 'modified' ] = False
|
buf.options[ 'modified' ] = False
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue