Switch to running the actual install_gadget.py

This re-uses the OutputView code to run the installer script. Refactor
to remove connection from the base OutputView (and other places, it
wasn't used - only used after ConnectionUp).

This also consolidates the stdout and stderr buffers for running jobs.
The distinction was always arbitrary and probably an error, based on the
fact that they were separate in the APIs not based on usability.
This commit is contained in:
Ben Jackson 2020-07-21 16:43:39 +01:00
commit 23e5f6bbf4
12 changed files with 236 additions and 167 deletions

View file

@ -528,7 +528,6 @@ class DebugSession( object ):
stack_trace_window = vim.current.window
one_third = int( vim.eval( 'winheight( 0 )' ) ) / 3
self._stackTraceView = stack_trace.StackTraceView( self,
self._connection,
stack_trace_window )
# Watches
@ -546,17 +545,15 @@ class DebugSession( object ):
with utils.LetCurrentWindow( stack_trace_window ):
vim.command( f'{ one_third }wincmd _' )
self._variablesView = variables.VariablesView( self._connection,
vars_window,
self._variablesView = variables.VariablesView( vars_window,
watch_window )
# Output/logging
vim.current.window = code_window
vim.command( f'rightbelow { settings.Int( "bottombar_height", 10 ) }new' )
output_window = vim.current.window
self._outputView = output.OutputView( self._connection,
output_window,
self._api_prefix )
self._outputView = output.DAPOutputView( output_window,
self._api_prefix )
# TODO: If/when we support multiple sessions, we'll need some way to
# indicate which tab was created and store all the tabs

View file

@ -36,7 +36,9 @@ import traceback
import zipfile
import json
from vimspector import install, gadgets
from vimspector import install
OUTPUT_VIEW = None
class Options:
@ -52,31 +54,94 @@ def Configure( **kwargs ):
setattr( options, k, v )
def Install( languages, force ):
all_enabled = 'all' in languages
force_all = all_enabled and force
def PathToAnyWorkingPython3():
# We can't rely on sys.executable because it's usually 'vim' (fixme, not with
# neovim?)
paths = os.environ[ 'PATH' ].split( os.pathsep )
install.MakeInstallDirs( options.vimspector_base )
all_adapters = ReadAdapters()
failed = []
if install.GetOS() == 'windows':
paths.insert( 0, os.getcwd() )
candidates = [ os.path.join( sys.exec_prefix, 'python.exe' ),
'python.exe' ]
else:
candidates = [ os.path.join( sys.exec_prefix, 'bin', 'python3' ),
'python3',
'python' ]
for name, gadget in gadgets.GADGETS.items():
if not gadget.get( 'enabled', True ):
if ( not force_all
and not ( force and gadget[ 'language' ] in languages ) ):
for candidate in candidates:
for path in paths:
filename = os.path.abspath( os.path.join( path, candidate ) )
if not os.path.isfile( filename ):
continue
else:
if not all_enabled and not gadget[ 'language' ] in languages:
if not os.access( filename, os.F_OK | os.X_OK ):
continue
InstallGagdet( name,
gadget,
failed,
all_adapters )
return filename
WriteAdapters( all_adapters )
raise RuntimeError( "Unable to find a working python3" )
def RunInstaller( api_prefix, *args ):
from vimspector import utils, output, settings
import vim
vimspector_home = utils.GetVimString( vim.vars, 'vimspector_home' )
vimspector_base_dir = utils.GetVimspectorBase()
# TODO: Translate the arguments to something more user-friendly than -- args
global OUTPUT_VIEW
if OUTPUT_VIEW:
OUTPUT_VIEW.Reset()
OUTPUT_VIEW = None
with utils.RestoreCurrentWindow():
vim.command( f'botright { settings.Int( "bottombar_height", 10 ) }new' )
win = vim.current.window
OUTPUT_VIEW = output.OutputView( win, api_prefix )
cmd = [
PathToAnyWorkingPython3(),
'-u',
os.path.join( vimspector_home, 'install_gadget.py' ),
'--update-gadget-config',
]
if not vimspector_base_dir == vimspector_home:
cmd.extend( '--basedir', vimspector_base_dir )
cmd.extend( args )
OUTPUT_VIEW.RunJobWithOutput( 'Installer', cmd )
OUTPUT_VIEW.ShowOutput( 'Installer' )
# def Install( languages, force ):
# all_enabled = 'all' in languages
# force_all = all_enabled and force
#
# install.MakeInstallDirs( options.vimspector_base )
# all_adapters = ReadAdapters()
# succeeded = []
# failed = []
#
# for name, gadget in gadgets.GADGETS.items():
# if not gadget.get( 'enabled', True ):
# if ( not force_all
# and not ( force and gadget[ 'language' ] in languages ) ):
# continue
# else:
# if not all_enabled and not gadget[ 'language' ] in languages:
# continue
#
# InstallGagdet( name,
# gadget,
# succeeded,
# failed,
# all_adapters )
#
# WriteAdapters( all_adapters )
#
# return succeeded, failed
return failed
def InstallGeneric( name, root, gadget ):
@ -182,7 +247,7 @@ def InstallNodeDebug( name, root, gadget ):
MakeSymlink( name, root )
def InstallGagdet( name, gadget, failed, all_adapters ):
def InstallGagdet( name, gadget, succeeded, failed, all_adapters ):
try:
v = {}
v.update( gadget.get( 'all', {} ) )
@ -235,6 +300,7 @@ def InstallGagdet( name, gadget, failed, all_adapters ):
# Add any other "all" adapters
all_adapters.update( gadget.get( 'adapters', {} ) )
succeeded.append( name )
print( "Done installing {}".format( name ) )
except Exception as e:
traceback.print_exc()

View file

@ -25,7 +25,6 @@ class TabBuffer( object ):
self.index = index
self.flag = False
self.is_job = False
self.job_category = None
BUFFER_MAP = {
@ -40,18 +39,24 @@ def CategoryToBuffer( category ):
return BUFFER_MAP.get( category, category )
VIEWS = set()
def ShowOutputInWindow( win_id, category ):
for view in VIEWS:
if view._window.valid and utils.WindowID( view._window ) == win_id:
view.ShowOutput( category )
return
raise ValueError( f'Unable to find output object for win id {win_id}!' )
class OutputView( object ):
def __init__( self, connection, window, api_prefix ):
def __init__( self, window, api_prefix ):
self._window = window
self._connection = connection
self._buffers = {}
self._api_prefix = api_prefix
for b in set( BUFFER_MAP.values() ):
self._CreateBuffer( b )
self._CreateBuffer( 'Vimspector', file_name = utils.LOG_FILE )
self._ShowOutput( 'Console' )
VIEWS.add( self )
def Print( self, categroy, text ):
self._Print( 'server', text.splitlines() )
@ -82,22 +87,23 @@ class OutputView( object ):
with utils.RestoreCurrentBuffer( self._window ):
self._ShowOutput( category )
def ConnectionUp( self, connection ):
self._connection = connection
def ConnectionClosed( self ):
# Don't clear because output is probably still useful
self._connection = None
def Reset( self ):
self.Clear()
VIEWS.remove( self )
def _CleanUpBuffer( self, category, tab_buffer = None ):
if tab_buffer is None:
tab_buffer = self._buffers[ category ]
if tab_buffer.is_job:
utils.CleanUpCommand( category, self._api_prefix )
utils.CleanUpHiddenBuffer( tab_buffer.buf )
def Clear( self ):
for category, tab_buffer in self._buffers.items():
if tab_buffer.is_job:
utils.CleanUpCommand( tab_buffer.job_category or category,
self._api_prefix )
utils.CleanUpHiddenBuffer( tab_buffer.buf )
self._CleanUpBuffer( category, tab_buffer )
# FIXME: nunmenu the WinBar ?
self._buffers = {}
@ -125,28 +131,6 @@ class OutputView( object ):
self._ToggleFlag( category, False )
self._ShowOutput( category )
def Evaluate( self, frame, expression ):
self._Print( 'Console', [ 'Evaluating: ' + expression ] )
def print_result( message ):
result = message[ 'body' ][ 'result' ]
if result is None:
result = '<no result>'
self._Print( 'Console', f' Result: { result }' )
request = {
'command': 'evaluate',
'arguments': {
'expression': expression,
'context': 'repl',
}
}
if frame:
request[ 'arguments' ][ 'frameId' ] = frame[ 'id' ]
self._connection.DoRequest( print_result, request )
def _ToggleFlag( self, category, flag ):
if self._buffers[ category ].flag != flag:
self._buffers[ category ].flag = flag
@ -178,16 +162,10 @@ class OutputView( object ):
cmd = [ 'tail', '-F', '-n', '+1', '--', file_name ]
if cmd is not None:
out, err = utils.SetUpCommandBuffer( cmd, category, self._api_prefix )
self._buffers[ category + '-out' ] = TabBuffer( out,
len( self._buffers ) )
self._buffers[ category + '-out' ].is_job = True
self._buffers[ category + '-out' ].job_category = category
self._buffers[ category + '-err' ] = TabBuffer( err,
len( self._buffers ) )
self._buffers[ category + '-err' ].is_job = False
self._RenderWinBar( category + '-out' )
self._RenderWinBar( category + '-err' )
out = utils.SetUpCommandBuffer( cmd, category, self._api_prefix )
self._buffers[ category ] = TabBuffer( out, 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 ) )
@ -218,10 +196,52 @@ class OutputView( object ):
raise
vim.command( "nnoremenu 1.{0} WinBar.{1}{2} "
":call vimspector#ShowOutput( '{1}' )<CR>".format(
":call vimspector#ShowOutputInWindow( {3}, '{1}' )<CR>".format(
tab_buffer.index,
utils.Escape( category ),
'*' if tab_buffer.flag else '' ) )
'*' if tab_buffer.flag else '',
utils.WindowID( self._window ) ) )
def GetCategories( self ):
return list( self._buffers.keys() )
class DAPOutputView( OutputView ):
def __init__( self, *args ):
super().__init__( *args )
self._connection = None
for b in set( BUFFER_MAP.values() ):
self._CreateBuffer( b )
self._CreateBuffer( 'Vimspector', file_name = utils.LOG_FILE )
self._ShowOutput( 'Console' )
def ConnectionUp( self, connection ):
self._connection = connection
def ConnectionClosed( self ):
# Don't clear because output is probably still useful
self._connection = None
def Evaluate( self, frame, expression ):
self._Print( 'Console', [ 'Evaluating: ' + expression ] )
def print_result( message ):
result = message[ 'body' ][ 'result' ]
if result is None:
result = '<no result>'
self._Print( 'Console', f' Result: { result }' )
request = {
'command': 'evaluate',
'arguments': {
'expression': expression,
'context': 'repl',
}
}
if frame:
request[ 'arguments' ][ 'frameId' ] = frame[ 'id' ]
self._connection.DoRequest( print_result, request )

View file

@ -21,13 +21,13 @@ from vimspector import utils
class StackTraceView( object ):
def __init__( self, session, connection, win ):
def __init__( self, session, win ):
self._logger = logging.getLogger( __name__ )
utils.SetUpLogging( self._logger )
self._buf = win.buffer
self._session = session
self._connection = connection
self._connection = None
self._current_thread = None
self._current_frame = None

View file

@ -72,20 +72,18 @@ def OpenFileInCurrentWindow( file_name ):
def SetUpCommandBuffer( cmd, name, api_prefix ):
bufs = vim.eval(
'vimspector#internal#{}job#StartCommandWithLog( {}, "{}" )'.format(
api_prefix,
json.dumps( cmd ),
name ) )
buf = Call( f'vimspector#internal#{api_prefix}job#StartCommandWithLog',
cmd,
name )
if bufs is None:
if buf is None:
raise RuntimeError( "Unable to start job {}: {}".format( cmd, name ) )
elif not all( int( b ) > 0 for b in bufs ):
elif int( buf ) <= 0:
raise RuntimeError( "Unable to get all streams for job {}: {}".format(
name,
cmd ) )
return [ vim.buffers[ int( b ) ] for b in bufs ]
return vim.buffers[ int( buf ) ]
def CleanUpCommand( name, api_prefix ):
@ -558,7 +556,6 @@ def Call( vimscript_function, *args ):
call += 'g:' + arg_name
call += ')'
_logger.debug( 'Calling: {}'.format( call ) )
return vim.eval( call )
@ -633,16 +630,26 @@ def HideSplash( api_prefix, splash ):
return None
def GetVimString( vim_dict, name, default=None ):
# FIXME: use 'encoding' ?
try:
value = vim_dict[ name ]
except KeyError:
return default
if isinstance( value, bytes ):
return value.decode( 'utf-8' )
return value
def GetVimspectorBase():
base = vim.vars.get( 'vimspector_base_dir' )
if base is None:
return os.path.abspath( os.path.join( os.path.dirname( __file__ ),
'..',
'..' ) )
elif isinstance( base, bytes ):
return base.decode( 'utf-8' )
else:
return base
return GetVimString( vim.vars,
'vimspector_base_dir',
os.path.abspath(
os.path.join( os.path.dirname( __file__ ),
'..',
'..' ) ) )
def GetUnusedLocalPort():
@ -655,5 +662,7 @@ def GetUnusedLocalPort():
return port
def WindowID( window, tab ):
def WindowID( window, tab=None ):
if tab is None:
tab = window.tabpage
return int( Call( 'win_getid', window.number, tab.number ) )

View file

@ -124,11 +124,11 @@ class View:
class VariablesView( object ):
def __init__( self, connection, variables_win, watches_win ):
def __init__( self, variables_win, watches_win ):
self._logger = logging.getLogger( __name__ )
utils.SetUpLogging( self._logger )
self._connection = connection
self._connection = None
self._current_syntax = ''
# Set up the "Variables" buffer in the variables_win