diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index e664121..c2deb08 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -31,7 +31,6 @@ from vimspector import ( breakpoints, variables, settings, terminal, - installer, launch ) # We cache this once, and don't allow it to change (FIXME?) @@ -109,6 +108,7 @@ class DebugSession( object ): if not configurations: configuration_name, configuration = launch.SuggestConfiguration( + current_file, filetypes ) else: configuration_name, configuration = launch.SelectConfiguration( @@ -267,6 +267,9 @@ class DebugSession( object ): def _Reset( self ): self._logger.info( "Debugging complete." ) + + launch.SaveConfiguration( self._configuration ) + if self._uiTab: self._logger.debug( "Clearing down UI" ) diff --git a/python3/vimspector/launch.py b/python3/vimspector/launch.py index 2903a7f..c4f0af4 100644 --- a/python3/vimspector/launch.py +++ b/python3/vimspector/launch.py @@ -120,7 +120,7 @@ def SelectConfiguration( launch_variables, configurations ): return configuration_name, configuration -def SuggestConfiguration( filetypes ): +def SuggestConfiguration( current_file, filetypes ): nothing = None, None templates = [] filetypes = set( filetypes ) @@ -160,10 +160,49 @@ def SuggestConfiguration( filetypes ): configuration_name = utils.AskForInput( 'Give the config a name: ', configuration[ 'description' ] ) + configuration[ 'launch_configuration' ][ 'generated' ] = { + 'name': configuration_name, + 'path': os.path.join( os.path.dirname( current_file ), '.vimspector.json' ), + } return configuration_name, configuration[ 'launch_configuration' ] +def SaveConfiguration( configuration ): + gen = configuration.pop( 'generated', None ) + if not gen: + return + + config_path = utils.AskForInput( + f'Would you like to save the configuration named "{ gen[ "name" ] }"' + '? Enter the path to save to (ctrl-c to cancel): ', + gen[ 'path' ] ) + + if not config_path: + return + + os.makedirs( os.path.dirname( config_path ), exist_ok = True ) + current_contents = {} + + if os.path.exists( config_path ): + if utils.Confirm( 'File exists, overwrite? (NOTE: comments and ' + 'formatting in the existing file will be LOST!!)', + '&Yes\n&No' ) == 1: + with open( config_path, 'r' ) as f: + current_contents = json.loads( minify( f.read() ) ) + + # TODO: how much of configuration is mangled at this point ? + # TODO: how about the defaulted arguments? All the refs are replaced at this + # point? + current_contents.setdefault( 'configurations', {} ) + current_contents[ 'configurations' ][ gen[ 'name' ] ] = configuration + + with open( config_path, 'w' ) as f: + json.dump( current_contents, f, indent=2 ) + + utils.UserMessage( f'Wrote { config_path }.', persist = True ) + + def SelectAdapter( api_prefix, debug_session, configuration_name, diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 581411a..ab5d2ca 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -386,6 +386,14 @@ def AskForInput( prompt, default_value = None ): return None +def Confirm( msg, *args ): + with AskingForUserInput(): + try: + return int( Call( 'confirm', msg, *args ) ) + except ( KeyboardInterrupt, vim.error ): + return 0 + + def AppendToBuffer( buf, line_or_lines, modified=False ): line = 1 try: @@ -600,8 +608,6 @@ def CoerceType( mapping: typing.Dict[ str, typing.Any ], key: str ): mapping[ key ] = DICT_TYPES[ new_type ]( value ) -# 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, calculus, user_choices ): for k in list( obj.keys() ): obj[ k ] = ExpandReferencesInObject( obj[ k ], @@ -817,6 +823,7 @@ def WindowID( window, tab=None ): return int( Call( 'win_getid', window.number, tab.number ) ) +@memoize def UseWinBar(): # Buggy neovim doesn't render correctly when the WinBar is defined: # https://github.com/neovim/neovim/issues/12689