Merge pull request #58 from puremourning/remember-choices
Remember user choices
This commit is contained in:
commit
968a443d09
4 changed files with 69 additions and 50 deletions
|
|
@ -43,7 +43,7 @@ class ProjectBreakpoints( object ):
|
||||||
# These are the user-entered breakpoints.
|
# These are the user-entered breakpoints.
|
||||||
self._line_breakpoints = defaultdict( list )
|
self._line_breakpoints = defaultdict( list )
|
||||||
self._func_breakpoints = []
|
self._func_breakpoints = []
|
||||||
self._exceptionBreakpoints = None
|
self._exception_breakpoints = None
|
||||||
|
|
||||||
# FIXME: Remove this. Remove breakpoints nonesense from code.py
|
# FIXME: Remove this. Remove breakpoints nonesense from code.py
|
||||||
self._breakpoints_handler = None
|
self._breakpoints_handler = None
|
||||||
|
|
@ -66,13 +66,12 @@ class ProjectBreakpoints( object ):
|
||||||
|
|
||||||
def ConnectionClosed( self ):
|
def ConnectionClosed( self ):
|
||||||
self._breakpoints_handler = None
|
self._breakpoints_handler = None
|
||||||
self._exceptionBreakpoints = None
|
|
||||||
self._server_capabilities = {}
|
self._server_capabilities = {}
|
||||||
self._connection = None
|
self._connection = None
|
||||||
self.UpdateUI()
|
self.UpdateUI()
|
||||||
|
|
||||||
# for each breakpoint:
|
# NOTE: we don't reset self._exception_breakpoints because we don't want to
|
||||||
# clear its resolved status
|
# re-ask the user every time for the sane info.
|
||||||
|
|
||||||
|
|
||||||
def ListBreakpoints( self ):
|
def ListBreakpoints( self ):
|
||||||
|
|
@ -117,7 +116,6 @@ class ProjectBreakpoints( object ):
|
||||||
|
|
||||||
self._line_breakpoints = defaultdict( list )
|
self._line_breakpoints = defaultdict( list )
|
||||||
self._func_breakpoints = []
|
self._func_breakpoints = []
|
||||||
self._exceptionBreakpoints = None
|
|
||||||
|
|
||||||
self.UpdateUI()
|
self.UpdateUI()
|
||||||
|
|
||||||
|
|
@ -250,16 +248,16 @@ class ProjectBreakpoints( object ):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if self._exceptionBreakpoints is None:
|
if self._exception_breakpoints is None:
|
||||||
self._SetUpExceptionBreakpoints()
|
self._SetUpExceptionBreakpoints()
|
||||||
|
|
||||||
if self._exceptionBreakpoints:
|
if self._exception_breakpoints:
|
||||||
awaiting = awaiting + 1
|
awaiting = awaiting + 1
|
||||||
self._connection.DoRequest(
|
self._connection.DoRequest(
|
||||||
lambda msg: response_handler( None, None ),
|
lambda msg: response_handler( None, None ),
|
||||||
{
|
{
|
||||||
'command': 'setExceptionBreakpoints',
|
'command': 'setExceptionBreakpoints',
|
||||||
'arguments': self._exceptionBreakpoints
|
'arguments': self._exception_breakpoints
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -268,44 +266,36 @@ class ProjectBreakpoints( object ):
|
||||||
|
|
||||||
|
|
||||||
def _SetUpExceptionBreakpoints( self ):
|
def _SetUpExceptionBreakpoints( self ):
|
||||||
exceptionBreakpointFilters = self._server_capabilities.get(
|
exception_breakpoint_filters = self._server_capabilities.get(
|
||||||
'exceptionBreakpointFilters',
|
'exceptionBreakpointFilters',
|
||||||
[] )
|
[] )
|
||||||
|
|
||||||
if exceptionBreakpointFilters or not self._server_capabilities.get(
|
if exception_breakpoint_filters or not self._server_capabilities.get(
|
||||||
'supportsConfigurationDoneRequest' ):
|
'supportsConfigurationDoneRequest' ):
|
||||||
exceptionFilters = []
|
exception_filters = []
|
||||||
if exceptionBreakpointFilters:
|
if exception_breakpoint_filters:
|
||||||
for f in exceptionBreakpointFilters:
|
for f in exception_breakpoint_filters:
|
||||||
response = utils.AskForInput(
|
default_value = 'Y' if f.get( 'default' ) else 'N'
|
||||||
"Enable exception filter '{}'? (Y/N)".format( f[ 'label' ] ) )
|
|
||||||
|
|
||||||
if response == 'Y':
|
result = utils.AskForInput(
|
||||||
exceptionFilters.append( f[ 'filter' ] )
|
"Break on {} (Y/N/default: {})? ".format( f[ 'label' ],
|
||||||
elif not response and f.get( 'default' ):
|
default_value ),
|
||||||
exceptionFilters.append( f[ 'filter' ] )
|
default_value )
|
||||||
|
|
||||||
self._exceptionBreakpoints = {
|
if result == 'Y':
|
||||||
'filters': exceptionFilters
|
exception_filters.append( f[ 'filter' ] )
|
||||||
|
elif not result and f.get( 'default' ):
|
||||||
|
exception_filters.append( f[ 'filter' ] )
|
||||||
|
|
||||||
|
self._exception_breakpoints = {
|
||||||
|
'filters': exception_filters
|
||||||
}
|
}
|
||||||
|
|
||||||
if self._server_capabilities.get( 'supportsExceptionOptions' ):
|
if self._server_capabilities.get( 'supportsExceptionOptions' ):
|
||||||
# FIXME Sigh. The python debug adapter requires this
|
# TODO: There are more elaborate exception breakpoint options here, but
|
||||||
# key to exist. Even though it is optional.
|
# we don't support them. It doesn't seem like any of the servers really
|
||||||
break_mode = utils.SelectFromList( 'When to break on exception?',
|
# pay any attention to them anyway.
|
||||||
[ 'never',
|
self._exception_breakpoints[ 'exceptionOptions' ] = []
|
||||||
'always',
|
|
||||||
'unhandled',
|
|
||||||
'userHandled' ] )
|
|
||||||
|
|
||||||
if not break_mode:
|
|
||||||
break_mode = 'unhandled'
|
|
||||||
|
|
||||||
path = [ { 'nagate': True, 'names': [ 'DO_NOT_MATCH' ] } ]
|
|
||||||
self._exceptionBreakpoints[ 'exceptionOptions' ] = [ {
|
|
||||||
'path': path,
|
|
||||||
'breakMode': break_mode
|
|
||||||
} ]
|
|
||||||
|
|
||||||
def _ShowBreakpoints( self ):
|
def _ShowBreakpoints( self ):
|
||||||
for file_name, line_breakpoints in self._line_breakpoints.items():
|
for file_name, line_breakpoints in self._line_breakpoints.items():
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,9 @@ VIMSPECTOR_HOME = os.path.abspath( os.path.join( os.path.dirname( __file__ ),
|
||||||
'..',
|
'..',
|
||||||
'..' ) )
|
'..' ) )
|
||||||
|
|
||||||
|
# cache of what the user entered for any option we ask them
|
||||||
|
USER_CHOICES = {}
|
||||||
|
|
||||||
|
|
||||||
class DebugSession( object ):
|
class DebugSession( object ):
|
||||||
def __init__( self ):
|
def __init__( self ):
|
||||||
|
|
@ -148,14 +151,26 @@ class DebugSession( object ):
|
||||||
}
|
}
|
||||||
self._variables.update(
|
self._variables.update(
|
||||||
utils.ParseVariables( adapter.get( 'variables', {} ),
|
utils.ParseVariables( adapter.get( 'variables', {} ),
|
||||||
self._variables ) )
|
self._variables,
|
||||||
|
USER_CHOICES ) )
|
||||||
self._variables.update(
|
self._variables.update(
|
||||||
utils.ParseVariables( configuration.get( 'variables', {} ),
|
utils.ParseVariables( configuration.get( 'variables', {} ),
|
||||||
self._variables ) )
|
self._variables,
|
||||||
|
USER_CHOICES ) )
|
||||||
|
|
||||||
|
# Pretend that vars passed to the launch command were typed in by the user
|
||||||
|
# (they may have been in theory)
|
||||||
|
# TODO: Is it right that we do this _after_ ParseVariables, rather than
|
||||||
|
# before ?
|
||||||
|
USER_CHOICES.update( launch_variables )
|
||||||
self._variables.update( launch_variables )
|
self._variables.update( launch_variables )
|
||||||
|
|
||||||
utils.ExpandReferencesInDict( configuration, self._variables )
|
utils.ExpandReferencesInDict( configuration,
|
||||||
utils.ExpandReferencesInDict( adapter, self._variables )
|
self._variables,
|
||||||
|
USER_CHOICES )
|
||||||
|
utils.ExpandReferencesInDict( adapter,
|
||||||
|
self._variables,
|
||||||
|
USER_CHOICES )
|
||||||
|
|
||||||
if not adapter:
|
if not adapter:
|
||||||
utils.UserMessage( 'No adapter configured for {}'.format(
|
utils.UserMessage( 'No adapter configured for {}'.format(
|
||||||
|
|
|
||||||
|
|
@ -261,10 +261,16 @@ def SelectFromList( prompt, options ):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def AskForInput( prompt ):
|
def AskForInput( prompt, default_value = None ):
|
||||||
|
if default_value is None:
|
||||||
|
default_option = ''
|
||||||
|
else:
|
||||||
|
default_option = ", '{}'".format( Escape( default_value ) )
|
||||||
|
|
||||||
with InputSave():
|
with InputSave():
|
||||||
try:
|
try:
|
||||||
return vim.eval( "input( '{0}' )".format( Escape( prompt ) ) )
|
return vim.eval( "input( '{}' {} )".format( Escape( prompt ),
|
||||||
|
default_option ) )
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
|
@ -306,7 +312,7 @@ def IsCurrent( window, buf ):
|
||||||
|
|
||||||
# TODO: Should we just run the substitution on the whole JSON string instead?
|
# 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. ?
|
# That woul dallow expansion in bool and number values, such as ports etc. ?
|
||||||
def ExpandReferencesInDict( obj, mapping, **kwargs ):
|
def ExpandReferencesInDict( obj, mapping, user_choices ):
|
||||||
def expand_refs_in_string( orig_s ):
|
def expand_refs_in_string( orig_s ):
|
||||||
s = os.path.expanduser( orig_s )
|
s = os.path.expanduser( orig_s )
|
||||||
s = os.path.expandvars( s )
|
s = os.path.expandvars( s )
|
||||||
|
|
@ -318,13 +324,16 @@ def ExpandReferencesInDict( obj, mapping, **kwargs ):
|
||||||
++bug_catcher
|
++bug_catcher
|
||||||
|
|
||||||
try:
|
try:
|
||||||
s = string.Template( s ).substitute( mapping, **kwargs )
|
s = string.Template( s ).substitute( mapping )
|
||||||
break
|
break
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
# HACK: This is seemingly the only way to get the key. str( e ) returns
|
# HACK: This is seemingly the only way to get the key. str( e ) returns
|
||||||
# the key surrounded by '' for unknowable reasons.
|
# the key surrounded by '' for unknowable reasons.
|
||||||
key = e.args[ 0 ]
|
key = e.args[ 0 ]
|
||||||
mapping[ key ] = AskForInput( 'Enter value for {}: '.format( key ) )
|
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",
|
_logger.debug( "Value for %s not set in %s (from %s): set to %s",
|
||||||
key,
|
key,
|
||||||
s,
|
s,
|
||||||
|
|
@ -339,7 +348,7 @@ def ExpandReferencesInDict( obj, mapping, **kwargs ):
|
||||||
|
|
||||||
def expand_refs_in_object( obj ):
|
def expand_refs_in_object( obj ):
|
||||||
if isinstance( obj, dict ):
|
if isinstance( obj, dict ):
|
||||||
ExpandReferencesInDict( obj, mapping, **kwargs )
|
ExpandReferencesInDict( obj, mapping, user_choices )
|
||||||
elif isinstance( obj, list ):
|
elif isinstance( obj, list ):
|
||||||
for i, _ in enumerate( obj ):
|
for i, _ in enumerate( obj ):
|
||||||
# FIXME: We are assuming that it is a list of string, but could be a
|
# FIXME: We are assuming that it is a list of string, but could be a
|
||||||
|
|
@ -354,7 +363,7 @@ def ExpandReferencesInDict( obj, mapping, **kwargs ):
|
||||||
obj[ k ] = expand_refs_in_object( obj[ k ] )
|
obj[ k ] = expand_refs_in_object( obj[ k ] )
|
||||||
|
|
||||||
|
|
||||||
def ParseVariables( variables_list, mapping, **kwargs ):
|
def ParseVariables( variables_list, mapping, user_choices ):
|
||||||
new_variables = {}
|
new_variables = {}
|
||||||
new_mapping = mapping.copy()
|
new_mapping = mapping.copy()
|
||||||
|
|
||||||
|
|
@ -371,7 +380,7 @@ def ParseVariables( variables_list, mapping, **kwargs ):
|
||||||
|
|
||||||
new_v = v.copy()
|
new_v = v.copy()
|
||||||
# Bit of a hack. Allows environment variables to be used.
|
# Bit of a hack. Allows environment variables to be used.
|
||||||
ExpandReferencesInDict( new_v, new_mapping, **kwargs )
|
ExpandReferencesInDict( new_v, new_mapping, user_choices )
|
||||||
|
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env.update( new_v.get( 'env' ) or {} )
|
env.update( new_v.get( 'env' ) or {} )
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,10 @@
|
||||||
class TestClass( object ):
|
class TestClass( object ):
|
||||||
def __init__( self, value ):
|
def __init__( self, value ):
|
||||||
self._var = value
|
self._var = value
|
||||||
self.DoSomething()
|
try:
|
||||||
|
self.DoSomething()
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
def DoSomething( self ):
|
def DoSomething( self ):
|
||||||
for i in range( 0, 100 ):
|
for i in range( 0, 100 ):
|
||||||
|
|
@ -13,6 +16,8 @@ class TestClass( object ):
|
||||||
else:
|
else:
|
||||||
print( '{0} might be more'.format( i ) )
|
print( '{0} might be more'.format( i ) )
|
||||||
|
|
||||||
|
raise ValueError( 'Done' )
|
||||||
|
|
||||||
|
|
||||||
def Main():
|
def Main():
|
||||||
t = TestClass( 18 )
|
t = TestClass( 18 )
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue