Calculate variables on-demand; add an unused-local-port variable-function

This commit is contained in:
Ben Jackson 2020-07-08 21:22:28 +01:00
commit 044804ca20
2 changed files with 71 additions and 32 deletions

View file

@ -177,43 +177,53 @@ class DebugSession( object ):
return [ '', '' ]
return os.path.splitext( p )
self._variables = {
variables = {
'dollar': '$', # HACK. Hote '$$' also works.
'workspaceRoot': self._workspace_root,
'workspaceFolder': self._workspace_root,
'gadgetDir': install.GetGadgetDir( VIMSPECTOR_HOME, install.GetOS() ),
'file': current_file,
'relativeFile': relpath( current_file, self._workspace_root ),
'fileBasename': os.path.basename( current_file ),
}
calculus = {
'gadgetDir': lambda: install.GetGadgetDir( VIMSPECTOR_HOME,
install.GetOS() ),
'relativeFile': lambda: relpath( current_file,
self._workspace_root ),
'fileBasename': lambda: os.path.basename( current_file ),
'fileBasenameNoExtension':
splitext( os.path.basename( current_file ) )[ 0 ],
'fileDirname': os.path.dirname( current_file ),
'fileExtname': splitext( os.path.basename( current_file ) )[ 1 ],
lambda: splitext( os.path.basename( current_file ) )[ 0 ],
'fileDirname': lambda: os.path.dirname( current_file ),
'fileExtname': lambda: splitext( os.path.basename( current_file ) )[ 1 ],
# NOTE: this is the window-local cwd for the current window, *not* Vim's
# working directory.
'cwd': os.getcwd(),
'cwd': os.getcwd,
'unusedLocalPort': utils.GetUnusedLocalPort,
}
# Pretend that vars passed to the launch command were typed in by the user
# (they may have been in theory)
USER_CHOICES.update( launch_variables )
self._variables.update( launch_variables )
variables.update( launch_variables )
self._variables.update(
variables.update(
utils.ParseVariables( adapter.get( 'variables', {} ),
self._variables,
variables,
calculus,
USER_CHOICES ) )
self._variables.update(
variables.update(
utils.ParseVariables( configuration.get( 'variables', {} ),
self._variables,
variables,
calculus,
USER_CHOICES ) )
utils.ExpandReferencesInDict( configuration,
self._variables,
variables,
calculus,
USER_CHOICES )
utils.ExpandReferencesInDict( adapter,
self._variables,
variables,
calculus,
USER_CHOICES )
if not adapter:

View file

@ -345,9 +345,9 @@ def IsCurrent( window, buf ):
return vim.current.window == window and vim.current.window.buffer == buf
def ExpandReferencesInObject( obj, mapping, user_choices ):
def ExpandReferencesInObject( obj, mapping, calculus, user_choices ):
if isinstance( obj, dict ):
ExpandReferencesInDict( obj, mapping, user_choices )
ExpandReferencesInDict( obj, mapping, calculus, user_choices )
elif isinstance( obj, list ):
j_offset = 0
obj_copy = list( obj )
@ -360,6 +360,7 @@ def ExpandReferencesInObject( obj, mapping, user_choices ):
# *${something} - expand list in place
value = ExpandReferencesInString( obj_copy[ i ][ 1: ],
mapping,
calculus,
user_choices )
obj.pop( j )
j_offset -= 1
@ -369,14 +370,18 @@ def ExpandReferencesInObject( obj, mapping, user_choices ):
else:
obj[ j ] = ExpandReferencesInObject( obj_copy[ i ],
mapping,
calculus,
user_choices )
elif isinstance( obj, str ):
obj = ExpandReferencesInString( obj, mapping, user_choices )
obj = ExpandReferencesInString( obj, mapping, calculus, user_choices )
return obj
def ExpandReferencesInString( orig_s, mapping, user_choices ):
def ExpandReferencesInString( orig_s,
mapping,
calculus,
user_choices ):
s = os.path.expanduser( orig_s )
s = os.path.expandvars( s )
@ -393,15 +398,19 @@ def ExpandReferencesInString( orig_s, mapping, user_choices ):
# HACK: This is seemingly the only way to get the key. str( e ) returns
# the key surrounded by '' for unknowable reasons.
key = e.args[ 0 ]
default_value = user_choices.get( key, None )
mapping[ key ] = AskForInput( 'Enter value for {}: '.format( key ),
default_value )
user_choices[ key ] = mapping[ key ]
_logger.debug( "Value for %s not set in %s (from %s): set to %s",
key,
s,
orig_s,
mapping[ key ] )
if key in calculus:
mapping[ key ] = calculus[ key ]()
else:
default_value = user_choices.get( key, None )
mapping[ key ] = AskForInput( 'Enter value for {}: '.format( key ),
default_value )
user_choices[ key ] = mapping[ key ]
_logger.debug( "Value for %s not set in %s (from %s): set to %s",
key,
s,
orig_s,
mapping[ key ] )
except ValueError as e:
UserMessage( 'Invalid $ in string {}: {}'.format( s, e ),
persist = True )
@ -412,12 +421,18 @@ def ExpandReferencesInString( orig_s, mapping, user_choices ):
# TODO: Should we just run the substitution on the whole JSON string instead?
# That woul dallow expansion in bool and number values, such as ports etc. ?
def ExpandReferencesInDict( obj, mapping, user_choices ):
def ExpandReferencesInDict( obj, mapping, calculus, user_choices ):
for k in obj.keys():
obj[ k ] = ExpandReferencesInObject( obj[ k ], mapping, user_choices )
obj[ k ] = ExpandReferencesInObject( obj[ k ],
mapping,
calculus,
user_choices )
def ParseVariables( variables_list, mapping, user_choices ):
def ParseVariables( variables_list,
mapping,
calculus,
user_choices ):
new_variables = {}
new_mapping = mapping.copy()
@ -431,7 +446,10 @@ def ParseVariables( variables_list, mapping, user_choices ):
if 'shell' in v:
new_v = v.copy()
# Bit of a hack. Allows environment variables to be used.
ExpandReferencesInDict( new_v, new_mapping, user_choices )
ExpandReferencesInDict( new_v,
new_mapping,
calculus,
user_choices )
env = os.environ.copy()
env.update( new_v.get( 'env' ) or {} )
@ -455,6 +473,7 @@ def ParseVariables( variables_list, mapping, user_choices ):
else:
new_variables[ n ] = ExpandReferencesInObject( v,
mapping,
calculus,
user_choices )
return new_variables
@ -575,3 +594,13 @@ def GetVimspectorBase():
return base.decode( 'utf-8' )
else:
return base
def GetUnusedLocalPort():
import socket
sock = socket.socket()
# This tells the OS to give us any free port in the range [1024 - 65535]
sock.bind( ( '', 0 ) )
port = sock.getsockname()[ 1 ]
sock.close()
return port