diff --git a/autoload/vimspector/internal/neopopup.vim b/autoload/vimspector/internal/neopopup.vim index fe5fe05..cc25020 100644 --- a/autoload/vimspector/internal/neopopup.vim +++ b/autoload/vimspector/internal/neopopup.vim @@ -80,6 +80,28 @@ function! vimspector#internal#neopopup#HideSplash( id ) abort unlet s:db[ a:id ] endfunction +function! vimspector#internal#neopopup#Confirm( confirm_id, + \ text, + \ default_value ) abort + let result = confirm( a:text, '&Yes &No &Default', 3 ) + + " Map the results to what popup_menu_filter would return (ok s:ConfirmCallback + " in popup.vim) + if result == 2 + " No is represented as 0 + let result = 0 + elseif result == 0 + " User pressed ESC/ctrl-c + let result = -1 + elseif result == 3 + " Default + let result = a:default_value + endif + + py3 __import__( 'vimspector', fromlist = [ 'utils' ] ).utils.ConfirmCallback( + \ int( vim.eval( 'a:confirm_id' ) ), + \ int( vim.eval( 'result' ) ) ) +endfunction " Boilerplate {{{ let &cpoptions=s:save_cpo unlet s:save_cpo diff --git a/autoload/vimspector/internal/popup.vim b/autoload/vimspector/internal/popup.vim index fc8820b..e8658ab 100644 --- a/autoload/vimspector/internal/popup.vim +++ b/autoload/vimspector/internal/popup.vim @@ -32,6 +32,37 @@ function! vimspector#internal#popup#HideSplash( id ) abort call popup_hide( a:id ) endfunction +function! s:YesNoDefaultFilter( default_value, id, key ) abort + if a:key ==# "\" || a:key ==# 'D' || a:key ==# 'd' + call popup_close( a:id, a:default_value ) + endif + + return popup_filter_yesno( a:id, a:key ) +endfunction + +function! s:ConfirmCallback( confirm_id, id, result ) abort + py3 __import__( 'vimspector', fromlist = [ 'utils' ] ).utils.ConfirmCallback( + \ int( vim.eval( 'a:confirm_id' ) ), + \ int( vim.eval( 'a:result' ) ) ) +endfunction + +function! vimspector#internal#popup#Confirm( + \ confirm_id, + \ text, + \ default_value ) abort + let text = a:text + if type( a:text ) != v:t_list + let text = [ a:text ] + endif + + call extend( text, [ '', '(Y)es (N)o (D)efault' ] ) + + return popup_dialog( text, { + \ 'callback': function( 's:ConfirmCallback', [ a:confirm_id ] ), + \ 'filter': function( 's:YesNoDefaultFilter', [ a:default_value ] ) + \ } ) +endfunction + " Boilerplate {{{ let &cpoptions=s:save_cpo unlet s:save_cpo diff --git a/python3/vimspector/custom/java.py b/python3/vimspector/custom/java.py index 0dfa89c..83705c1 100644 --- a/python3/vimspector/custom/java.py +++ b/python3/vimspector/custom/java.py @@ -29,12 +29,15 @@ class JavaDebugAdapter( object ): return if body.get( 'changeType' ) == 'BUILD_COMPLETE': - if utils.AskForInput( 'Code has changed, hot reload? [Y/N] ', - 'Y' ).upper()[ 0 ] == 'Y': - self.debug_session._connection.DoRequest( None, { - 'command': 'redefineClasses', - 'arguments': {}, - } ) + def handler( result ): + if result == 1: + self.debug_session._connection.DoRequest( None, { + 'command': 'redefineClasses', + 'arguments': {}, + } ) + + utils.Confirm( self.debug_session._api_prefix, + 'Code has changed, hot reload?', + handler ) elif body.get( 'message' ): utils.UserMessage( 'Hot code replace: ' + body[ 'message' ] ) - diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 31b4342..ae16706 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -911,39 +911,52 @@ class DebugSession( object ): self._logger.info( 'Debug Adapter Started' ) def _StopDebugAdapter( self, interactive = False, callback = None ): - self._splash_screen = utils.DisplaySplash( - self._api_prefix, - self._splash_screen, - "Shutting down debug adapter..." ) + def disconnect( arguments = {} ): + self._splash_screen = utils.DisplaySplash( + self._api_prefix, + self._splash_screen, + "Shutting down debug adapter..." ) - def handler( *args ): - self._splash_screen = utils.HideSplash( self._api_prefix, - self._splash_screen ) + def handler( *args ): + self._splash_screen = utils.HideSplash( self._api_prefix, + self._splash_screen ) - if callback: - self._logger.debug( "Setting server exit handler before disconnect" ) - assert not self._run_on_server_exit - self._run_on_server_exit = callback + if callback: + self._logger.debug( "Setting server exit handler before disconnect" ) + assert not self._run_on_server_exit + self._run_on_server_exit = callback - vim.eval( 'vimspector#internal#{}#StopDebugSession()'.format( - self._connection_type ) ) + vim.eval( 'vimspector#internal#{}#StopDebugSession()'.format( + self._connection_type ) ) - arguments = {} - if ( interactive and - self._server_capabilities.get( 'supportTerminateDebuggee' ) ): - if self._stackTraceView.AnyThreadsRunning(): - choice = utils.AskForInput( "Terminate debuggee [Y/N/default]? ", "" ) - if choice == "Y" or choice == "y": + self._connection.DoRequest( handler, { + 'command': 'disconnect', + 'arguments': {}, + }, failure_handler = handler, timeout = 5000 ) + + if not interactive: + disconnect() + elif not self._server_capabilities.get( 'supportTerminateDebuggee' ): + disconnect() + elif not self._stackTraceView.AnyThreadsRunning(): + disconnect() + else: + def handle_choice( choice ): + arguments = {} + if choice == 1: arguments[ 'terminateDebuggee' ] = True - elif choice == "N" or choice == 'n': + elif choice == 0: arguments[ 'terminateDebuggee' ] = False + elif choice == -1: + # Abort + return - self._connection.DoRequest( handler, { - 'command': 'disconnect', - 'arguments': arguments, - }, failure_handler = handler, timeout = 5000 ) + disconnect( arguments ) - # TODO: Use the 'tarminate' request if supportsTerminateRequest set + utils.Confirm( self._api_prefix, + "Terminate debuggee?", + handle_choice, + default_value = 3 ) def _PrepareAttach( self, adapter_config, launch_config ): diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index d8dd345..c65a184 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -375,6 +375,31 @@ def AskForInput( prompt, default_value = None, completion = None ): return None +CONFIRM = {} +CONFIRM_ID = 0 + +def ConfirmCallback( confirm_id, result ): + try: + handler = CONFIRM.pop( confirm_id ) + except KeyError: + UserMessage( f"Internal error: unexpected callback id { confirm_id }", + persist = True, + error = True ) + return + + handler( result ) + + +def Confirm( api_prefix, prompt, handler, default_value = 1 ): + global CONFIRM_ID + CONFIRM_ID += 1 + CONFIRM[ CONFIRM_ID ] = handler + Call( f'vimspector#internal#{ api_prefix }popup#Confirm', + CONFIRM_ID, + prompt, + default_value ) + + def AppendToBuffer( buf, line_or_lines, modified=False ): line = 1 try: @@ -403,8 +428,10 @@ def AppendToBuffer( buf, line_or_lines, modified=False ): -def ClearBuffer( buf ): +def ClearBuffer( buf, modified = False ): buf[ : ] = None + if not modified: + buf.options[ 'modified' ] = False def SetBufferContents( buf, lines, modified=False ):