From 6fd472418985d1599afc01e1d5db068a0003f1d7 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 23 Sep 2020 12:29:40 +0100 Subject: [PATCH] Launch remote commands in a termianl This allows stdin and mans you don't need the output window visible to see the useful process output when debugging a remote-Launch. --- python3/vimspector/code.py | 89 +++++------------------------ python3/vimspector/debug_session.py | 25 ++++++-- python3/vimspector/terminal.py | 82 ++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 80 deletions(-) create mode 100644 python3/vimspector/terminal.py diff --git a/python3/vimspector/code.py b/python3/vimspector/code.py index c50d602..977ecec 100644 --- a/python3/vimspector/code.py +++ b/python3/vimspector/code.py @@ -18,7 +18,7 @@ import logging import json from collections import defaultdict -from vimspector import utils, settings, signs +from vimspector import utils, terminal, signs class CodeView( object ): @@ -26,8 +26,7 @@ class CodeView( object ): self._window = window self._api_prefix = api_prefix - self._terminal_window = None - self._terminal_buffer_number = None + self._terminal = None self.current_syntax = None self._logger = logging.getLogger( __name__ ) @@ -63,7 +62,9 @@ class CodeView( object ): linehl = 'CursorLine' ) - def _UndisplayPC( self ): + def _UndisplayPC( self, clear_pc = True ): + if clear_pc: + self._current_frame = None if self._signs[ 'vimspectorPC' ]: signs.UnplaceSign( self._signs[ 'vimspectorPC' ], 'VimspectorCode' ) self._signs[ 'vimspectorPC' ] = None @@ -74,7 +75,7 @@ class CodeView( object ): if not frame: return - self._UndisplayPC() + self._UndisplayPC( clear_pc = False ) # FIXME: Do we relly need to keep using up IDs ? self._signs[ 'vimspectorPC' ] = self._next_sign_id @@ -152,7 +153,7 @@ class CodeView( object ): signs.UnplaceSign( self._signs[ 'vimspectorPC' ], 'VimspectorCode' ) self._signs[ 'vimspectorPC' ] = None - self._current_frame = None + self._UndisplayPC() self._UndisplaySigns() self.current_syntax = None @@ -241,73 +242,11 @@ class CodeView( object ): def LaunchTerminal( self, params ): - # kind = params.get( 'kind', 'integrated' ) + self._terminal = terminal.LaunchTerminal( self._api_prefix, + params, + window_for_start = self._window, + existing_term = self._terminal ) - # FIXME: We don't support external terminals, and only open in the - # integrated one. - - cwd = params[ 'cwd' ] - args = params[ 'args' ] - env = params.get( 'env', {} ) - - term_options = { - 'vertical': 1, - 'norestore': 1, - 'cwd': cwd, - 'env': env, - } - - if self._window.valid: - window_for_start = self._window - else: - # TOOD: Where? Maybe we should just use botright vertical ... - window_for_start = vim.current.window - - if self._terminal_window is not None and self._terminal_window.valid: - assert self._terminal_buffer_number - window_for_start = self._terminal_window - if ( self._terminal_window.buffer.number == self._terminal_buffer_number - and int( utils.Call( 'vimspector#internal#{}term#IsFinished'.format( - self._api_prefix ), - self._terminal_buffer_number ) ) ): - term_options[ 'curwin' ] = 1 - else: - term_options[ 'vertical' ] = 0 - - buffer_number = None - terminal_window = None - with utils.LetCurrentWindow( window_for_start ): - # If we're making a vertical split from the code window, make it no more - # than 80 columns and no fewer than 10. Also try and keep the code window - # at least 82 columns - if term_options[ 'vertical' ] and not term_options.get( 'curwin', 0 ): - term_options[ 'term_cols' ] = max( - min ( int( vim.eval( 'winwidth( 0 )' ) ) - - settings.Int( 'code_minwidth' ), - settings.Int( 'terminal_maxwidth' ) ), - settings.Int( 'terminal_minwidth' ) - ) - - buffer_number = int( - utils.Call( - 'vimspector#internal#{}term#Start'.format( self._api_prefix ), - args, - term_options ) ) - terminal_window = vim.current.window - - if buffer_number is None or buffer_number <= 0: - # TODO: Do something better like reject the request? - raise ValueError( "Unable to start terminal" ) - - self._terminal_window = terminal_window - self._terminal_buffer_number = buffer_number - - vim.vars[ 'vimspector_session_windows' ][ 'terminal' ] = utils.WindowID( - self._terminal_window, - vim.current.tabpage ) - with utils.RestoreCursorPosition(): - with utils.RestoreCurrentWindow(): - with utils.RestoreCurrentBuffer( vim.current.window ): - vim.command( 'doautocmd User VimspectorTerminalOpened' ) - - return buffer_number + # FIXME: Change this tor return the PID rather than having debug_session + # work that out + return self._terminal.buffer_number diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 3956d7f..e072a23 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -31,6 +31,7 @@ from vimspector import ( breakpoints, utils, variables, settings, + terminal, installer ) from vimspector.vendor.json_minify import minify @@ -61,6 +62,7 @@ class DebugSession( object ): self._outputView = None self._breakpoints = breakpoints.ProjectBreakpoints() self._splash_screen = None + self._remote_term = None self._run_on_server_exit = None @@ -360,7 +362,6 @@ class DebugSession( object ): def OnServerStderr( self, data ): - self._logger.info( "Server stderr: %s", data ) if self._outputView: self._outputView.Print( 'server', data ) @@ -404,6 +405,7 @@ class DebugSession( object ): self._variablesView = None self._outputView = None self._codeView = None + self._remote_term = None self._uiTab = None # make sure that we're displaying signs in any still-open buffers @@ -760,13 +762,20 @@ class DebugSession( object ): commands = self._GetCommands( remote, 'attach' ) for command in commands: - cmd = remote_exec_cmd + command[ : ] + cmd = remote_exec_cmd + command for index, item in enumerate( cmd ): cmd[ index ] = item.replace( '%PID%', pid ) self._logger.debug( 'Running remote app: %s', cmd ) - self._outputView.RunJobWithOutput( 'Remote', cmd ) + self._remote_term = terminal.LaunchTerminal( + self._api_prefix, + { + 'args': cmd, + 'cwd': os.getcwd() + }, + self._codeView._window, + self._remote_term ) else: if atttach_config[ 'pidSelect' ] == 'ask': prop = atttach_config[ 'pidProperty' ] @@ -805,8 +814,14 @@ class DebugSession( object ): full_cmd.append( item.replace( '%CMD%', command_line ) ) self._logger.debug( 'Running remote app: %s', full_cmd ) - self._outputView.RunJobWithOutput( 'Remote{}'.format( index ), - full_cmd ) + self._remote_term = terminal.LaunchTerminal( + self._api_prefix, + { + 'args': full_cmd, + 'cwd': os.getcwd() + }, + self._codeView._window, + self._remote_term ) def _GetSSHCommand( self, remote ): diff --git a/python3/vimspector/terminal.py b/python3/vimspector/terminal.py new file mode 100644 index 0000000..a2ed264 --- /dev/null +++ b/python3/vimspector/terminal.py @@ -0,0 +1,82 @@ +from vimspector import utils, settings + +import vim + + +class Terminal: + window = None + buffer_number: int = None + + +def LaunchTerminal( api_prefix, + params, + window_for_start, + existing_term ): + if not existing_term: + term = Terminal() + else: + term = existing_term + + cwd = params[ 'cwd' ] + args = params[ 'args' ] + env = params.get( 'env', {} ) + + term_options = { + 'vertical': 1, + 'norestore': 1, + 'cwd': cwd, + 'env': env, + } + + if not window_for_start or not window_for_start.valid: + # TOOD: Where? Maybe we should just use botright vertical ... + window_for_start = vim.current.window + + if term.window is not None and term.window.valid: + assert term.buffer_number + window_for_start = term.window + if ( term.window.buffer.number == term.buffer_number + and int( utils.Call( 'vimspector#internal#{}term#IsFinished'.format( + api_prefix ), + term.buffer_number ) ) ): + term_options[ 'curwin' ] = 1 + else: + term_options[ 'vertical' ] = 0 + + buffer_number = None + terminal_window = None + with utils.LetCurrentWindow( window_for_start ): + # If we're making a vertical split from the code window, make it no more + # than 80 columns and no fewer than 10. Also try and keep the code window + # at least 82 columns + if term_options[ 'vertical' ] and not term_options.get( 'curwin', 0 ): + term_options[ 'term_cols' ] = max( + min ( int( vim.eval( 'winwidth( 0 )' ) ) + - settings.Int( 'code_minwidth' ), + settings.Int( 'terminal_maxwidth' ) ), + settings.Int( 'terminal_minwidth' ) + ) + + buffer_number = int( + utils.Call( + 'vimspector#internal#{}term#Start'.format( api_prefix ), + args, + term_options ) ) + terminal_window = vim.current.window + + if buffer_number is None or buffer_number <= 0: + # TODO: Do something better like reject the request? + raise ValueError( "Unable to start terminal" ) + + term.window = terminal_window + term.buffer_number = buffer_number + + vim.vars[ 'vimspector_session_windows' ][ 'terminal' ] = utils.WindowID( + term.window, + vim.current.tabpage ) + with utils.RestoreCursorPosition(): + with utils.RestoreCurrentWindow(): + with utils.RestoreCurrentBuffer( vim.current.window ): + vim.command( 'doautocmd User VimspectorTerminalOpened' ) + + return term