From dcdab6351648087ad349ea89937c50f937ecc6f4 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 8 Jan 2020 13:51:03 +0000 Subject: [PATCH 01/24] Remove use of bindeval() as it is not suported in neovim --- autoload/vimspector/internal/channel.vim | 28 ++++++------ autoload/vimspector/internal/job.vim | 54 ++++++++++++------------ python3/vimspector/debug_session.py | 15 +++---- python3/vimspector/utils.py | 14 ++++++ 4 files changed, 62 insertions(+), 49 deletions(-) diff --git a/autoload/vimspector/internal/channel.vim b/autoload/vimspector/internal/channel.vim index d0cb7d2..3e0d298 100644 --- a/autoload/vimspector/internal/channel.vim +++ b/autoload/vimspector/internal/channel.vim @@ -37,22 +37,11 @@ function! s:_OnClose( channel ) abort py3 _vimspector_session.OnServerExit( 0 ) endfunction -function! s:_Send( msg ) abort - call ch_sendraw( s:ch, a:msg ) - return 1 -endfunction - -function! vimspector#internal#channel#Timeout( id ) abort - py3 << EOF -_vimspector_session.OnRequestTimeout( vim.eval( 'a:id' ) ) -EOF -endfunction - function! vimspector#internal#channel#StartDebugSession( config ) abort if exists( 's:ch' ) echo 'Channel is already running' - return v:none + return v:false endif let l:addr = 'localhost:' . a:config[ 'port' ] @@ -70,10 +59,21 @@ function! vimspector#internal#channel#StartDebugSession( config ) abort if ch_status( s:ch ) !=# 'open' echom 'Unable to connect to debug adapter' redraw - return v:none + return v:false endif - return funcref( 's:_Send' ) + return v:true +endfunction + +function! vimspector#internal#channel#Send( msg ) abort + call ch_sendraw( s:ch, a:msg ) + return 1 +endfunction + +function! vimspector#internal#channel#Timeout( id ) abort + py3 << EOF +_vimspector_session.OnRequestTimeout( vim.eval( 'a:id' ) ) +EOF endfunction function! vimspector#internal#channel#StopDebugSession() abort diff --git a/autoload/vimspector/internal/job.vim b/autoload/vimspector/internal/job.vim index 26ba117..530acb3 100644 --- a/autoload/vimspector/internal/job.vim +++ b/autoload/vimspector/internal/job.vim @@ -39,35 +39,11 @@ function! s:_OnClose( channel ) abort redraw endfunction -function! s:_Send( msg ) abort - if ! exists( 's:job' ) - echom "Can't send message: Job was not initialised correctly" - redraw - return 0 - endif - - if job_status( s:job ) !=# 'run' - echom "Can't send message: Job is not running" - redraw - return 0 - endif - - let ch = job_getchannel( s:job ) - if ch ==# 'channel fail' - echom 'Channel was closed unexpectedly!' - redraw - return 0 - endif - - call ch_sendraw( ch, a:msg ) - return 1 -endfunction - function! vimspector#internal#job#StartDebugSession( config ) abort if exists( 's:job' ) echom 'Not starging: Job is already running' redraw - return v:none + return v:false endif let s:job = job_start( a:config[ 'command' ], @@ -91,10 +67,34 @@ function! vimspector#internal#job#StartDebugSession( config ) abort if job_status( s:job ) !=# 'run' echom 'Unable to start job, status is: ' . job_status( s:job ) redraw - return v:none + return v:false endif - return funcref( 's:_Send' ) + return v:true +endfunction + +function! vimspector#internal#job#Send( msg ) abort + if ! exists( 's:job' ) + echom "Can't send message: Job was not initialised correctly" + redraw + return 0 + endif + + if job_status( s:job ) !=# 'run' + echom "Can't send message: Job is not running" + redraw + return 0 + endif + + let ch = job_getchannel( s:job ) + if ch ==# 'channel fail' + echom 'Channel was closed unexpectedly!' + redraw + return 0 + endif + + call ch_sendraw( ch, a:msg ) + return 1 endfunction function! vimspector#internal#job#StopDebugSession() abort diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 8eec9f4..edaf75c 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -492,19 +492,18 @@ class DebugSession( object ): self._adapter[ 'cwd' ] = os.getcwd() vim.vars[ '_vimspector_adapter_spec' ] = self._adapter - channel_send_func = vim.bindeval( - "vimspector#internal#{}#StartDebugSession( " - " g:_vimspector_adapter_spec " - ")".format( self._connection_type ) ) - - if channel_send_func is None: + if not vim.eval( "vimspector#internal#{}#StartDebugSession( " + " g:_vimspector_adapter_spec " + ")".format( self._connection_type ) ): self._logger.error( "Unable to start debug server" ) else: self._connection = debug_adapter_connection.DebugAdapterConnection( self, - channel_send_func ) + lambda msg: utils.Call( + "vimspector#internal#{}#Send".format( self._connection_type ), + msg ) ) - self._logger.info( 'Debug Adapter Started' ) + self._logger.info( 'Debug Adapter Started' ) def _StopDebugAdapter( self, callback = None ): def handler( *args ): diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index ba930ba..6fea1c5 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -449,3 +449,17 @@ def ToUnicode( b ): if isinstance( b, bytes ): return b.decode( 'utf-8' ) return b + + +# Call a vimscript function with suplied arguments. +def Call( vimscript_function, *args ): + call = vimscript_function + '(' + for index, arg in enumerate( args ): + arg_name = 'vimspector_internal_arg_{}'.format( index ) + vim.vars[ arg_name ] = arg + call += 'g:' + arg_name + if index: + call += ',' + + call += ')' + vim.eval( call ) From d1e3b648d32a07e8fd2dc210267f44b85937174f Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 8 Jan 2020 14:00:05 +0000 Subject: [PATCH 02/24] Use eval for lists of buffers too --- python3/vimspector/utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 6fea1c5..79c8c67 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -57,19 +57,19 @@ def OpenFileInCurrentWindow( file_name ): def SetUpCommandBuffer( cmd, name ): - bufs = vim.bindeval( + bufs = vim.eval( 'vimspector#internal#job#StartCommandWithLog( {}, "{}" )'.format( json.dumps( cmd ), name ) ) if bufs is None: raise RuntimeError( "Unable to start job {}: {}".format( cmd, name ) ) - elif not all( b > 0 for b in bufs ): + elif not all( int( b ) > 0 for b in bufs ): raise RuntimeError( "Unable to get all streams for job {}: {}".format( name, cmd ) ) - return [ vim.buffers[ b ] for b in bufs ] + return [ vim.buffers[ int( b ) ] for b in bufs ] def CleanUpCommand( name ): From ee1bb009ea1e19afe1a3102fadf40830c5aa892b Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 8 Jan 2020 14:34:13 +0000 Subject: [PATCH 03/24] Wrap the terminal API in vimscript layer --- autoload/vimspector/internal/job.vim | 2 +- autoload/vimspector/internal/term.vim | 37 +++++++++++++++++++++++++++ python3/vimspector/code.py | 14 ++++------ python3/vimspector/debug_session.py | 4 +-- python3/vimspector/utils.py | 8 +++--- 5 files changed, 50 insertions(+), 15 deletions(-) create mode 100644 autoload/vimspector/internal/term.vim diff --git a/autoload/vimspector/internal/job.vim b/autoload/vimspector/internal/job.vim index 530acb3..dd76652 100644 --- a/autoload/vimspector/internal/job.vim +++ b/autoload/vimspector/internal/job.vim @@ -30,7 +30,7 @@ endfunction function! s:_OnExit( channel, status ) abort echom 'Channel exit with status ' . a:status redraw - unlet s:job + unlet s:job py3 _vimspector_session.OnServerExit( vim.eval( 'a:status' ) ) endfunction diff --git a/autoload/vimspector/internal/term.vim b/autoload/vimspector/internal/term.vim new file mode 100644 index 0000000..5a570fc --- /dev/null +++ b/autoload/vimspector/internal/term.vim @@ -0,0 +1,37 @@ +" vimspector - A multi-language debugging system for Vim +" Copyright 2018 Ben Jackson +" +" Licensed under the Apache License, Version 2.0 (the "License"); +" you may not use this file except in compliance with the License. +" You may obtain a copy of the License at +" +" http://www.apache.org/licenses/LICENSE-2.0 +" +" Unless required by applicable law or agreed to in writing, software +" distributed under the License is distributed on an "AS IS" BASIS, +" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +" See the License for the specific language governing permissions and +" limitations under the License. + + +" Boilerplate {{{ +let s:save_cpo = &cpoptions +set cpoptions&vim +" }}} + +function! vimspector#internal#term#Start( cmd, opts ) abort + return term_start( a:cmd, a:opts ) +endfunction + +function! vimspector#internal#term#IsFinished( bufno ) abort + return index( split( term_getstatus( a:bufno ), ',' ), 'finished' ) >= 0 +endfunction + +function! vimspector#internal#term#GetPID( bufno ) abort + return job_info( term_getjob( a:bufno ) ).process +endfunction + +" Boilerplate {{{ +let &cpoptions=s:save_cpo +unlet s:save_cpo +" }}} diff --git a/python3/vimspector/code.py b/python3/vimspector/code.py index 509008d..6893b85 100644 --- a/python3/vimspector/code.py +++ b/python3/vimspector/code.py @@ -214,8 +214,8 @@ class CodeView( object ): if self._terminal_window is not None: assert self._terminal_buffer_number if ( self._terminal_window.buffer.number == self._terminal_buffer_number - and 'finished' in vim.eval( 'term_getstatus( {} )'.format( - self._terminal_buffer_number ) ) ): + and int( utils.Call( 'vimspector#internal#term#IsFinished', + self._terminal_buffer_number ) ) ): window_for_start = self._terminal_window options[ 'curwin' ] = 1 @@ -224,13 +224,9 @@ class CodeView( object ): with utils.TemporaryVimOptions( { 'splitright': True, 'equalalways': False } ): with utils.LetCurrentWindow( window_for_start ): - # TODO/FIXME: Do something about closing this when we reset ? - vim_cmd = 'term_start( {}, {} )'.format( json.dumps( args ), - json.dumps( options ) ) - - self._logger.debug( 'Start terminal: {}'.format( vim_cmd ) ) - - buffer_number = int( vim.eval( vim_cmd ) ) + buffer_number = int( utils.Call( 'vimspector#internal#term#Start', + args, + options ) ) terminal_window = vim.current.window if buffer_number is None or buffer_number <= 0: diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index edaf75c..fc85c85 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -798,8 +798,8 @@ class DebugSession( object ): buffer_number = self._codeView.LaunchTerminal( params ) response = { - 'processId': vim.eval( 'job_info( term_getjob( {} ) )' - '.process'.format( buffer_number ) ) + 'processId': int( utils.Call( 'vimspector#internal#term#GetPID', + buffer_number ) ) } self._connection.DoResponse( message, None, response ) diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 79c8c67..850a759 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -455,11 +455,13 @@ def ToUnicode( b ): def Call( vimscript_function, *args ): call = vimscript_function + '(' for index, arg in enumerate( args ): + if index > 0: + call += ', ' + arg_name = 'vimspector_internal_arg_{}'.format( index ) vim.vars[ arg_name ] = arg call += 'g:' + arg_name - if index: - call += ',' call += ')' - vim.eval( call ) + _logger.debug( 'Calling: {}'.format( call ) ) + return vim.eval( call ) From 5aa33c19f7769115caa5168cd3ece970f407b0ec Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 8 Jan 2020 17:23:42 +0000 Subject: [PATCH 04/24] Remove unused ForceRead function --- autoload/vimspector/internal/channel.vim | 9 --------- autoload/vimspector/internal/job.vim | 9 --------- 2 files changed, 18 deletions(-) diff --git a/autoload/vimspector/internal/channel.vim b/autoload/vimspector/internal/channel.vim index 3e0d298..9825c5d 100644 --- a/autoload/vimspector/internal/channel.vim +++ b/autoload/vimspector/internal/channel.vim @@ -97,15 +97,6 @@ function! vimspector#internal#channel#Reset() abort endif endfunction -function! vimspector#internal#channel#ForceRead() abort - if exists( 's:ch' ) - let data = ch_readraw( s:ch, { 'timeout': 1000 } ) - if data !=# '' - call s:_OnServerData( s:ch, data ) - endif - endif -endfunction - " Boilerplate {{{ let &cpoptions=s:save_cpo unlet s:save_cpo diff --git a/autoload/vimspector/internal/job.vim b/autoload/vimspector/internal/job.vim index dd76652..1031f1d 100644 --- a/autoload/vimspector/internal/job.vim +++ b/autoload/vimspector/internal/job.vim @@ -115,15 +115,6 @@ function! vimspector#internal#job#Reset() abort call vimspector#internal#job#StopDebugSession() endfunction -function! vimspector#internal#job#ForceRead() abort - if exists( 's:job' ) - let data = ch_readraw( job_getchannel( s:job ), { 'timeout': 1000 } ) - if data !=# '' - call s:_OnServerData( job_getchannel( s:job ), data ) - endif - endif -endfunction - function! vimspector#internal#job#StartCommandWithLog( cmd, category ) abort if ! exists( 's:commands' ) let s:commands = {} From 18627b9244afd53221e7409a06bb1061058e4dc2 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 8 Jan 2020 17:26:38 +0000 Subject: [PATCH 05/24] Add a way to have multiple vim API layers --- autoload/vimspector/internal/job.vim | 2 +- autoload/vimspector/internal/state.vim | 3 ++- python3/vimspector/code.py | 14 +++++++++----- python3/vimspector/debug_session.py | 19 +++++++++++++------ python3/vimspector/output.py | 7 ++++--- python3/vimspector/utils.py | 10 ++++++---- 6 files changed, 35 insertions(+), 20 deletions(-) diff --git a/autoload/vimspector/internal/job.vim b/autoload/vimspector/internal/job.vim index 1031f1d..4ed9ea8 100644 --- a/autoload/vimspector/internal/job.vim +++ b/autoload/vimspector/internal/job.vim @@ -127,7 +127,7 @@ function! vimspector#internal#job#StartCommandWithLog( cmd, category ) abort let l:index = len( s:commands[ a:category ] ) call add( s:commands[ a:category ], job_start( - \ a:cmd, + \ a:cmd, \ { \ 'out_io': 'buffer', \ 'in_io': 'null', diff --git a/autoload/vimspector/internal/state.vim b/autoload/vimspector/internal/state.vim index 6478506..f268164 100644 --- a/autoload/vimspector/internal/state.vim +++ b/autoload/vimspector/internal/state.vim @@ -20,9 +20,10 @@ set cpoptions&vim " }}} function! vimspector#internal#state#Reset() abort + let prefix = '' py3 << EOF from vimspector import debug_session -_vimspector_session = debug_session.DebugSession() +_vimspector_session = debug_session.DebugSession( vim.eval( 'prefix' ) ) EOF endfunction diff --git a/python3/vimspector/code.py b/python3/vimspector/code.py index 6893b85..b1b7698 100644 --- a/python3/vimspector/code.py +++ b/python3/vimspector/code.py @@ -22,8 +22,9 @@ from vimspector import utils class CodeView( object ): - def __init__( self, window ): + def __init__( self, window, api_prefix ): self._window = window + self._api_prefix = api_prefix self._terminal_window = None self._terminal_buffer_number = None @@ -214,7 +215,8 @@ class CodeView( object ): if self._terminal_window is not None: assert self._terminal_buffer_number if ( self._terminal_window.buffer.number == self._terminal_buffer_number - and int( utils.Call( 'vimspector#internal#term#IsFinished', + and int( utils.Call( 'vimspector#internal#{}term#IsFinished'.format( + self._api_prefix ), self._terminal_buffer_number ) ) ): window_for_start = self._terminal_window options[ 'curwin' ] = 1 @@ -224,9 +226,11 @@ class CodeView( object ): with utils.TemporaryVimOptions( { 'splitright': True, 'equalalways': False } ): with utils.LetCurrentWindow( window_for_start ): - buffer_number = int( utils.Call( 'vimspector#internal#term#Start', - args, - options ) ) + buffer_number = int( + utils.Call( + 'vimspector#internal#{}term#Start'.format( self._api_prefix ), + args, + options ) ) terminal_window = vim.current.window if buffer_number is None or buffer_number <= 0: diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index fc85c85..11e602a 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -41,11 +41,14 @@ USER_CHOICES = {} class DebugSession( object ): - def __init__( self ): + def __init__( self, api_prefix ): self._logger = logging.getLogger( __name__ ) utils.SetUpLogging( self._logger ) + self._api_prefix = api_prefix + self._logger.info( "**** INITIALISING NEW VIMSPECTOR SESSION ****" ) + self._logger.info( "API is: {}".format( api_prefix ) ) self._logger.info( 'VIMSPECTOR_HOME = %s', VIMSPECTOR_HOME ) self._logger.info( 'gadgetDir = %s', install.GetGadgetDir( VIMSPECTOR_HOME, @@ -405,7 +408,7 @@ class DebugSession( object ): self._uiTab = vim.current.tabpage # Code window - self._codeView = code.CodeView( vim.current.window ) + self._codeView = code.CodeView( vim.current.window, self._api_prefix ) # Call stack with utils.TemporaryVimOptions( { 'splitright': False, @@ -441,7 +444,8 @@ class DebugSession( object ): vim.command( '10spl' ) vim.command( 'enew' ) self._outputView = output.OutputView( self._connection, - vim.current.window ) + vim.current.window, + self._api_prefix ) def ClearCurrentFrame( self ): self.SetCurrentFrame( None ) @@ -482,6 +486,8 @@ class DebugSession( object ): port = utils.AskForInput( 'Enter port to connect to: ' ) self._adapter[ 'port' ] = port + self._connection_type = self._api_prefix + self._connection_type + # TODO: Do we actually need to copy and update or does Vim do that? env = os.environ.copy() if 'env' in self._adapter: @@ -795,11 +801,12 @@ class DebugSession( object ): self._logger.debug( 'Defaulting working directory to %s', params[ 'cwd' ] ) - buffer_number = self._codeView.LaunchTerminal( params ) + term_id = self._codeView.LaunchTerminal( params ) response = { - 'processId': int( utils.Call( 'vimspector#internal#term#GetPID', - buffer_number ) ) + 'processId': int( utils.Call( + 'vimspector#internal#{}term#GetPID'.format( self._api_prefix ), + term_id ) ) } self._connection.DoResponse( message, None, response ) diff --git a/python3/vimspector/output.py b/python3/vimspector/output.py index d4cf1af..46c2583 100644 --- a/python3/vimspector/output.py +++ b/python3/vimspector/output.py @@ -40,10 +40,11 @@ def CategoryToBuffer( category ): class OutputView( object ): - def __init__( self, connection, window ): + def __init__( self, connection, window, api_prefix ): self._window = window self._connection = connection self._buffers = {} + self._api_prefix = api_prefix for b in set( BUFFER_MAP.values() ): self._CreateBuffer( b ) @@ -95,7 +96,7 @@ class OutputView( object ): def Clear( self ): for category, tab_buffer in self._buffers.items(): if tab_buffer.is_job: - utils.CleanUpCommand( category ) + utils.CleanUpCommand( category, self._api_prefix ) try: vim.command( 'bdelete! {0}'.format( tab_buffer.buf.number ) ) except vim.error as e: @@ -161,7 +162,7 @@ class OutputView( object ): cmd = [ 'tail', '-F', '-n', '+1', '--', file_name ] if cmd is not None: - out, err = utils.SetUpCommandBuffer( cmd, category ) + out, err = utils.SetUpCommandBuffer( cmd, category, self._api_prefix ) self._buffers[ category + '-out' ] = TabBuffer( out, len( self._buffers ) ) self._buffers[ category + '-out' ].is_job = True diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 850a759..809f393 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -56,9 +56,10 @@ def OpenFileInCurrentWindow( file_name ): return vim.buffers[ buffer_number ] -def SetUpCommandBuffer( cmd, name ): +def SetUpCommandBuffer( cmd, name, api_prefix ): bufs = vim.eval( - 'vimspector#internal#job#StartCommandWithLog( {}, "{}" )'.format( + 'vimspector#internal#{}job#StartCommandWithLog( {}, "{}" )'.format( + api_prefix, json.dumps( cmd ), name ) ) @@ -72,8 +73,9 @@ def SetUpCommandBuffer( cmd, name ): return [ vim.buffers[ int( b ) ] for b in bufs ] -def CleanUpCommand( name ): - return vim.eval( 'vimspector#internal#job#CleanUpCommand( "{}" )'.format( +def CleanUpCommand( name, api_prefix ): + return vim.eval( 'vimspector#internal#{}job#CleanUpCommand( "{}" )'.format( + api_prefix, name ) ) From 29c26996fb7da6d47994789db9a4f8dfe88de7ef Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 8 Jan 2020 17:27:08 +0000 Subject: [PATCH 06/24] Add neovim job/terminal APIs --- autoload/vimspector/internal/neojob.vim | 163 +++++++++++++++++++++++ autoload/vimspector/internal/neoterm.vim | 67 ++++++++++ autoload/vimspector/internal/state.vim | 5 + python3/vimspector/output.py | 2 +- python3/vimspector/utils.py | 2 +- 5 files changed, 237 insertions(+), 2 deletions(-) create mode 100644 autoload/vimspector/internal/neojob.vim create mode 100644 autoload/vimspector/internal/neoterm.vim diff --git a/autoload/vimspector/internal/neojob.vim b/autoload/vimspector/internal/neojob.vim new file mode 100644 index 0000000..64ef934 --- /dev/null +++ b/autoload/vimspector/internal/neojob.vim @@ -0,0 +1,163 @@ +" vimspector - A multi-language debugging system for Vim +" Copyright 2018 Ben Jackson +" +" Licensed under the Apache License, Version 2.0 (the "License"); +" you may not use this file except in compliance with the License. +" You may obtain a copy of the License at +" +" http://www.apache.org/licenses/LICENSE-2.0 +" +" Unless required by applicable law or agreed to in writing, software +" distributed under the License is distributed on an "AS IS" BASIS, +" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +" See the License for the specific language governing permissions and +" limitations under the License. + + +" Boilerplate {{{ +let s:save_cpo = &cpoptions +set cpoptions&vim +" }}} + + + +function! s:_OnEvent( chan_id, data, event ) abort + " In neovim, the data argument is a list. + if a:event ==# 'stdout' + py3 _vimspector_session.OnChannelData( '\n'.join( vim.eval( 'a:data' ) ) ) + elseif a:event ==# 'stderr' + py3 _vimspector_session.OnServerStderr( '\n'.join( vim.eval( 'a:data' ) ) ) + elseif a:event ==# 'exit' + echom 'Channel exit with status ' . a:data + redraw + unlet s:job + py3 _vimspector_session.OnServerExit( vim.eval( 'a:data' ) ) + endif +endfunction + +function! vimspector#internal#neojob#StartDebugSession( config ) abort + if exists( 's:job' ) + echom 'Not starging: Job is already running' + redraw + return v:false + endif + + let s:job = jobstart( a:config[ 'command' ], + \ { + \ 'on_stdout': funcref( 's:_OnEvent' ), + \ 'on_stderr': funcref( 's:_OnEvent' ), + \ 'on_exit': funcref( 's:_OnEvent' ), + \ 'cwd': a:config[ 'cwd' ], + \ } + \ ) + + " FIXME: Missing in neovim 0.4. But in master: + " \ 'env': a:config[ 'env' ], + " + + " FIXME: error handling ? + return v:true +endfunction + +function! s:JobIsRunning( job ) abort + return jobwait( [ s:job ], 0 )[ 0 ] == -1 +endfunction + +function! vimspector#internal#neojob#Send( msg ) abort + if ! exists( 's:job' ) + echom "Can't send message: Job was not initialised correctly" + redraw + return 0 + endif + + if !s:JobIsRunning( s:job ) + echom "Can't send message: Job is not running" + redraw + return 0 + endif + + call chansend( s:job, a:msg ) + return 1 +endfunction + +function! vimspector#internal#neojob#StopDebugSession() abort + if !exists( 's:job' ) + echom "Not stopping session: Job doesn't exist" + redraw + return + endif + + if s:JobIsRunning( s:job ) + echom 'Terminating job' + redraw + call jobstop( s:job ) + endif +endfunction + +function! vimspector#internal#neojob#Reset() abort + call vimspector#internal#neojob#StopDebugSession() +endfunction + +function! s:_OnCommandEvent( category, id, data, event ) abort + if a:data == [''] + return + endif + if a:event ==# 'stdout' + let buffer = s:commands[ a:category ][ a:id ].stdout + elseif a:event ==# 'stderr' + let buffer = s:commands[ a:category ][ a:id ].stderr + endif + + let last_line_list = getbufline( buffer, '$' ) + if len( last_line_list ) == 0 + let last_line = '' + else + let last_line = last_line_list[ 0 ] + endif + + call setbufline( buffer, '$', last_line . a:data[ 0 ] ) + call appendbufline( buffer, '$', a:data[ 1: ] ) +endfunction + +let s:commands = {} + +function! vimspector#internal#neojob#StartCommandWithLog( cmd, category ) abort + if ! has_key( s:commands, a:category ) + let s:commands[ a:category ] = {} + endif + + let stdout_buf = bufnr( '_vimspector_log_' . a:category . '_out', 1 ) + let stderr_buf = bufnr( '_vimspector_log_' . a:category . '_err', 1 ) + + let id = jobstart(a:cmd, + \ { + \ 'on_stdout': funcref( 's:_OnCommandEvent', + \ [ a:category ] ), + \ 'on_stderr': funcref( 's:_OnCommandEvent', + \ [ a:category ] ) + \ } ) + + let s:commands[ a:category ][ id ] = { + \ 'stdout': stdout_buf, + \ 'stderr': stderr_buf + \ } + + return [ stdout_buf, stderr_buf ] +endfunction + +function! vimspector#internal#neojob#CleanUpCommand( category ) abort + if ! has_key( s:commands, a:category ) + return + endif + + for id in keys( s:commands[ a:category ] ) + call jobstop( id ) + call jobwait( id ) + endfor + unlet! s:commands[ a:category ] +endfunction + +" Boilerplate {{{ +let &cpoptions=s:save_cpo +unlet s:save_cpo +" }}} diff --git a/autoload/vimspector/internal/neoterm.vim b/autoload/vimspector/internal/neoterm.vim new file mode 100644 index 0000000..ab71b2f --- /dev/null +++ b/autoload/vimspector/internal/neoterm.vim @@ -0,0 +1,67 @@ +" vimspector - A multi-language debugging system for Vim +" Copyright 2018 Ben Jackson +" +" Licensed under the Apache License, Version 2.0 (the "License"); +" you may not use this file except in compliance with the License. +" You may obtain a copy of the License at +" +" http://www.apache.org/licenses/LICENSE-2.0 +" +" Unless required by applicable law or agreed to in writing, software +" distributed under the License is distributed on an "AS IS" BASIS, +" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +" See the License for the specific language governing permissions and +" limitations under the License. + + +" Boilerplate {{{ +let s:save_cpo = &cpoptions +set cpoptions&vim +" }}} + +" Ids are unique throughtout the life of neovim, but obviously buffer numbers +" aren't +" +" FIXME: Tidy this map when buffers are closed ? +let s:buffer_to_id = {} + +function! vimspector#internal#neoterm#Start( cmd, opts ) abort + if ! get( a:opts, 'curwin', 0 ) + if get( a:opts, 'vertical', 0 ) + vsplit + else + split + endif + endif + + " FIXME: 'env' doesn't work + let id = termopen( a:cmd, { 'cwd': a:opts[ 'cwd' ] } ) + let bufnr = bufnr() + let s:buffer_to_id[ bufnr ] = id + return bufnr +endfunction + +function! s:JobIsRunning( job ) abort + return jobwait( [ a:job ], 0 )[ 0 ] == -1 +endfunction + +function! vimspector#internal#neoterm#IsFinished( bufno ) abort + if !has_key( s:buffer_to_id, a:bufno ) + return v:true + endif + + return !s:JobIsRunning( s:buffer_to_id[ a:bufno ] ) +endfunction + +function! vimspector#internal#neoterm#GetPID( bufno ) abort + if !has_key( s:buffer_to_id, a:bufno ) + return -1 + endif + + return jobpid( s:buffer_to_id[ a:bufno ] ) +endfunction + +" Boilerplate {{{ +let &cpoptions=s:save_cpo +unlet s:save_cpo +" }}} diff --git a/autoload/vimspector/internal/state.vim b/autoload/vimspector/internal/state.vim index f268164..11ed003 100644 --- a/autoload/vimspector/internal/state.vim +++ b/autoload/vimspector/internal/state.vim @@ -19,8 +19,13 @@ let s:save_cpo = &cpoptions set cpoptions&vim " }}} +let s:is_neovim = has( 'nvim' ) + function! vimspector#internal#state#Reset() abort let prefix = '' + if s:is_neovim + let prefix='neo' + endif py3 << EOF from vimspector import debug_session _vimspector_session = debug_session.DebugSession( vim.eval( 'prefix' ) ) diff --git a/python3/vimspector/output.py b/python3/vimspector/output.py index 46c2583..dd0c293 100644 --- a/python3/vimspector/output.py +++ b/python3/vimspector/output.py @@ -101,7 +101,7 @@ class OutputView( object ): vim.command( 'bdelete! {0}'.format( tab_buffer.buf.number ) ) except vim.error as e: # FIXME: For now just ignore the "no buffers were deleted" error - if 'E516' not in e: + if 'E516' not in str( e ): raise self._buffers = {} diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 809f393..a9f55df 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -104,7 +104,7 @@ def SetUpHiddenBuffer( buf, name ): def SetUpPromptBuffer( buf, name, prompt, callback, hidden=False ): # This feature is _super_ new, so only enable when available if not int( vim.eval( "exists( '*prompt_setprompt' )" ) ): - return SetUpScratchBuffer( buf, name ) + return SetUpHiddenBuffer( buf, name ) buf.options[ 'buftype' ] = 'prompt' buf.options[ 'swapfile' ] = False From 04bb03da0ab1ee0486cd1ac60df900f33ef2c131 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 8 Jan 2020 21:06:57 +0000 Subject: [PATCH 07/24] Add channel support for neovim --- autoload/vimspector/internal/channel.vim | 5 -- autoload/vimspector/internal/neochannel.vim | 85 +++++++++++++++++++++ autoload/vimspector/internal/neojob.vim | 2 +- 3 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 autoload/vimspector/internal/neochannel.vim diff --git a/autoload/vimspector/internal/channel.vim b/autoload/vimspector/internal/channel.vim index 9825c5d..4c3d1d9 100644 --- a/autoload/vimspector/internal/channel.vim +++ b/autoload/vimspector/internal/channel.vim @@ -25,11 +25,6 @@ _vimspector_session.OnChannelData( vim.eval( 'a:data' ) ) EOF endfunction -function! s:_OnServerError( channel, data ) abort - echom 'Channel received error: ' . a:data - redraw -endfunction - function! s:_OnClose( channel ) abort echom 'Channel closed' redraw diff --git a/autoload/vimspector/internal/neochannel.vim b/autoload/vimspector/internal/neochannel.vim new file mode 100644 index 0000000..22bc5d2 --- /dev/null +++ b/autoload/vimspector/internal/neochannel.vim @@ -0,0 +1,85 @@ +" vimspector - A multi-language debugging system for Vim +" Copyright 2020 Ben Jackson +" +" Licensed under the Apache License, Version 2.0 (the "License"); +" you may not use this file except in compliance with the License. +" You may obtain a copy of the License at +" +" http://www.apache.org/licenses/LICENSE-2.0 +" +" Unless required by applicable law or agreed to in writing, software +" distributed under the License is distributed on an "AS IS" BASIS, +" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +" See the License for the specific language governing permissions and +" limitations under the License. + + +" Boilerplate {{{ +let s:save_cpo = &cpoptions +set cpoptions&vim +" }}} + + + +function! s:_OnEvent( chan_id, data, event ) abort + if a:data == [''] + echom 'Channel closed' + redraw + unlet s:ch + py3 _vimspector_session.OnServerExit( 0 ) + else + py3 _vimspector_session.OnChannelData( '\n'.join( vim.eval( 'a:data' ) ) ) + endif +endfunction + +function! vimspector#internal#neochannel#StartDebugSession( config ) abort + if exists( 's:ch' ) + echom 'Not starging: Channel is already running' + redraw + return v:false + endif + + let addr = 'localhost:' . a:config[ 'port' ] + + let s:ch = sockconnect( 'tcp', addr, { 'on_data': funcref( 's:_OnEvent' ) } ) + if s:ch <= 0 + unlet s:ch + return v:false + endif + + return v:true +endfunction + +function! vimspector#internal#neochannel#Send( msg ) abort + if ! exists( 's:ch' ) + echom "Can't send message: Channel was not initialised correctly" + redraw + return 0 + endif + + call chansend( s:ch, a:msg ) + return 1 +endfunction + +function! vimspector#internal#neochannel#StopDebugSession() abort + if !exists( 's:ch' ) + echom "Not stopping session: Channel doesn't exist" + redraw + return + endif + + call chanclose( s:ch ) + " It doesn't look like we get a callback after chanclos. Who knows if we will + " subsequently receive data callbacks. + call s:_OnEvent( s:ch, [ '' ], 'data' ) +endfunction + +function! vimspector#internal#neochannel#Reset() abort + call vimspector#internal#neochannel#StopDebugSession() +endfunction + +" Boilerplate {{{ +let &cpoptions=s:save_cpo +unlet s:save_cpo +" }}} + diff --git a/autoload/vimspector/internal/neojob.vim b/autoload/vimspector/internal/neojob.vim index 64ef934..c88a319 100644 --- a/autoload/vimspector/internal/neojob.vim +++ b/autoload/vimspector/internal/neojob.vim @@ -1,5 +1,5 @@ " vimspector - A multi-language debugging system for Vim -" Copyright 2018 Ben Jackson +" Copyright 2020 Ben Jackson " " Licensed under the Apache License, Version 2.0 (the "License"); " you may not use this file except in compliance with the License. From 7456c26c2a833abe0cf29dd4ede071cc7222055b Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 9 Jan 2020 20:53:59 +0000 Subject: [PATCH 08/24] Add some :commands for basic usages --- autoload/vimspector.vim | 13 +++++ autoload/vimspector/internal/neojob.vim | 4 +- plugin/vimspector.vim | 65 +++++++++++++++++-------- python3/vimspector/debug_session.py | 3 ++ python3/vimspector/output.py | 3 ++ 5 files changed, 67 insertions(+), 21 deletions(-) diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index 0250b90..7e71695 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -96,6 +96,11 @@ function! vimspector#AddWatchPrompt( expr ) abort call vimspector#AddWatch( a:expr ) endfunction +function! vimspector#Evaluate( expr ) abort + py3 _vimspector_session.ShowOutput( 'Console' ) + py3 _vimspector_session.EvaluateConsole( vim.eval( 'a:expr' ) ) +endfunction + function! vimspector#EvaluateConsole( expr ) abort stopinsert setlocal nomodified @@ -110,6 +115,14 @@ function! vimspector#ListBreakpoints() abort py3 _vimspector_session.ListBreakpoints() endfunction +function! vimspector#CompleteOutput( ArgLead, CmdLine, CursorPos ) abort + return py3eval( '_vimspector_session.GetOutputBuffers()' ) +endfunction + +function! vimspector#CompleteExpr( ArgLead, CmdLine, CursorPos ) abort + return [] +endfunction + " Boilerplate {{{ let &cpoptions=s:save_cpo unlet s:save_cpo diff --git a/autoload/vimspector/internal/neojob.vim b/autoload/vimspector/internal/neojob.vim index c88a319..3c5e3b1 100644 --- a/autoload/vimspector/internal/neojob.vim +++ b/autoload/vimspector/internal/neojob.vim @@ -126,8 +126,8 @@ function! vimspector#internal#neojob#StartCommandWithLog( cmd, category ) abort let s:commands[ a:category ] = {} endif - let stdout_buf = bufnr( '_vimspector_log_' . a:category . '_out', 1 ) - let stderr_buf = bufnr( '_vimspector_log_' . a:category . '_err', 1 ) + let stdout_buf = bufnr( '_vimspector_log_' . a:category . '_out', v:true ) + let stderr_buf = bufnr( '_vimspector_log_' . a:category . '_err', v:true ) let id = jobstart(a:cmd, \ { diff --git a/plugin/vimspector.vim b/plugin/vimspector.vim index 13ffa3b..10eb374 100644 --- a/plugin/vimspector.vim +++ b/plugin/vimspector.vim @@ -26,6 +26,7 @@ if exists( 'g:loaded_vimpector' ) call s:restore_cpo() finish endif +"}}} " TODO: " - Check Vim version (for jobs) @@ -36,28 +37,54 @@ let g:loaded_vimpector = 1 let s:mappings = get( g:, 'vimspector_enable_mappings', '' ) +nnoremap VimspectorContinue :call vimspector#Continue() +nnoremap VimspectorStop :call vimspector#Stop() +nnoremap VimspectorRestart :call vimspector#Restart() +nnoremap VimspectorPause :call vimspector#Pause() +nnoremap VimspectorToggleBreakpoint + \ :call vimspector#ToggleBreakpoint() +nnoremap VimspectorAddFunctionBreakpoint + \ :call vimspector#AddFunctionBreakpoint( expand( '' ) ) +nnoremap VimspectorStopOver :call vimspector#StepOver() +nnoremap VimspectorStepInto :call vimspector#StepInto() +nnoremap VimspectorStepOut :call vimspector#StepOut() + if s:mappings ==# 'VISUAL_STUDIO' - nnoremap :call vimspector#Continue() - nnoremap :call vimspector#Stop() - nnoremap :call vimspector#Restart() - nnoremap :call vimspector#Pause() - nnoremap :call vimspector#ToggleBreakpoint() - nnoremap :call vimspector#AddFunctionBreakpoint( expand( '' ) ) - nnoremap :call vimspector#StepOver() - nnoremap :call vimspector#StepInto() - nnoremap :call vimspector#StepOut() + nmap VimspectorContinue + nmap VimspectorStop + nmap VimspectorRestart + nmap VimspectorPause + nmap VimspectorToggleBreakpoint + nmap VimspectorAddFunctionBreakpoint + nmap VimspectorStepOver + nmap VimspectorStepInto + nmap VimspectorStepOut elseif s:mappings ==# 'HUMAN' - nnoremap :call vimspector#Continue() - nnoremap :call vimspector#Stop() - nnoremap :call vimspector#Restart() - nnoremap :call vimspector#Pause() - nnoremap :call vimspector#ToggleBreakpoint() - nnoremap :call vimspector#AddFunctionBreakpoint( expand( '' ) ) - nnoremap :call vimspector#StepOver() - nnoremap :call vimspector#StepInto() - nnoremap :call vimspector#StepOut() + nmap VimspectorContinue + nmap VimspectorStop + nmap VimspectorRestart + nmap VimspectorPause + nmap VimspectorToggleBreakpoint + nmap VimspectorAddFunctionBreakpoint + nmap VimspectorStepOver + nmap VimspectorStepInto + nmap VimspectorStepOut endif -"}}} +command! -bar -nargs=1 -complete=customlist,vimspector#CompleteExpr + \ VimspectorWatch + \ call vimspector#AddWatch( ) +command! -bar -nargs=1 -complete=customlist,vimspector#CompleteOutput + \ VimspectorShowOutput + \ call vimspector#ShowOutput( ) +command! -bar -nargs=1 -complete=customlist,vimspector#CompleteExpr + \ VimspectorEval + \ call vimspector#Evaluate( ) +command! -bar + \ VimspectorReset + \ call vimspector#Reset() +" boilerplate {{{ call s:restore_cpo() +" }}} + diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 11e602a..a4d801b 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -403,6 +403,9 @@ class DebugSession( object ): def ShowOutput( self, category ): self._outputView.ShowOutput( category ) + def GetOutputBuffers( self ): + return self._outputView.GetCategories() + def _SetUpUI( self ): vim.command( 'tabnew' ) self._uiTab = vim.current.tabpage diff --git a/python3/vimspector/output.py b/python3/vimspector/output.py index dd0c293..fb90929 100644 --- a/python3/vimspector/output.py +++ b/python3/vimspector/output.py @@ -206,3 +206,6 @@ class OutputView( object ): tab_buffer.index, utils.Escape( category ), '*' if tab_buffer.flag else '' ) ) + + def GetCategories( self ): + return [ category for category in self._buffers.keys() ] From a00e6a19d6bf4bf80aaa81f21c783a8337dba7d3 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 9 Jan 2020 21:59:25 +0000 Subject: [PATCH 09/24] Fix output buffers. bufnr creates an _unloaded_ buffer, so we have to load it --- autoload/vimspector/internal/neojob.vim | 39 +++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/autoload/vimspector/internal/neojob.vim b/autoload/vimspector/internal/neojob.vim index 3c5e3b1..f8a687a 100644 --- a/autoload/vimspector/internal/neojob.vim +++ b/autoload/vimspector/internal/neojob.vim @@ -102,23 +102,52 @@ function! s:_OnCommandEvent( category, id, data, event ) abort if a:data == [''] return endif + if a:event ==# 'stdout' let buffer = s:commands[ a:category ][ a:id ].stdout elseif a:event ==# 'stderr' let buffer = s:commands[ a:category ][ a:id ].stderr endif + call bufload( buffer ) + let last_line_list = getbufline( buffer, '$' ) + if len( last_line_list ) == 0 let last_line = '' else let last_line = last_line_list[ 0 ] endif - call setbufline( buffer, '$', last_line . a:data[ 0 ] ) - call appendbufline( buffer, '$', a:data[ 1: ] ) + + call s:MakeBufferWritable( buffer ) + try + call setbufline( buffer, '$', last_line . a:data[ 0 ] ) + call appendbufline( buffer, '$', a:data[ 1: ] ) + finally + call s:MakeBufferReadOnly( buffer ) + call setbufvar( buffer, '&modified', 0 ) + endtry + endfunction +function! s:SetUpHiddenBuffer( buffer ) abort + call setbufvar( a:buffer, '&hidden', 1 ) + call setbufvar( a:buffer, '&bufhidden', 'hide' ) + call s:MakeBufferReadOnly( a:buffer ) +endfunction + +function! s:MakeBufferReadOnly( buffer ) abort + call setbufvar( a:buffer, '&modifiable', 0 ) + call setbufvar( a:buffer, '&readonly', 1 ) +endfunction + +function! s:MakeBufferWritable( buffer ) abort + call setbufvar( a:buffer, '&readonly', 0 ) + call setbufvar( a:buffer, '&modifiable', 1 ) +endfunction + + let s:commands = {} function! vimspector#internal#neojob#StartCommandWithLog( cmd, category ) abort @@ -129,6 +158,12 @@ function! vimspector#internal#neojob#StartCommandWithLog( cmd, category ) abort let stdout_buf = bufnr( '_vimspector_log_' . a:category . '_out', v:true ) let stderr_buf = bufnr( '_vimspector_log_' . a:category . '_err', v:true ) + " FIXME: This largely duplicates the same stuff in the python layer, but we + " don't want to potentially mess up Vim behaviour where the job output is + " attached to a buffer set up by Vim. So we sort o mimic that here. + call s:SetUpHiddenBuffer( stdout_buf ) + call s:SetUpHiddenBuffer( stderr_buf ) + let id = jobstart(a:cmd, \ { \ 'on_stdout': funcref( 's:_OnCommandEvent', From c898eb47b2c620eacd04406d94e22df81894dbc8 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 9 Jan 2020 22:36:30 +0000 Subject: [PATCH 10/24] Fix filtering VimspectorShowOutput --- autoload/vimspector.vim | 3 ++- plugin/vimspector.vim | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index 7e71695..c3ead44 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -116,7 +116,8 @@ function! vimspector#ListBreakpoints() abort endfunction function! vimspector#CompleteOutput( ArgLead, CmdLine, CursorPos ) abort - return py3eval( '_vimspector_session.GetOutputBuffers()' ) + let buffers = py3eval( '_vimspector_session.GetOutputBuffers()' ) + return join( buffers, "\n" ) endfunction function! vimspector#CompleteExpr( ArgLead, CmdLine, CursorPos ) abort diff --git a/plugin/vimspector.vim b/plugin/vimspector.vim index 10eb374..6034d53 100644 --- a/plugin/vimspector.vim +++ b/plugin/vimspector.vim @@ -74,7 +74,7 @@ endif command! -bar -nargs=1 -complete=customlist,vimspector#CompleteExpr \ VimspectorWatch \ call vimspector#AddWatch( ) -command! -bar -nargs=1 -complete=customlist,vimspector#CompleteOutput +command! -bar -nargs=1 -complete=custom,vimspector#CompleteOutput \ VimspectorShowOutput \ call vimspector#ShowOutput( ) command! -bar -nargs=1 -complete=customlist,vimspector#CompleteExpr From 149d48b68857ddb931e2486f9b782eabf8e3fb7e Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 9 Jan 2020 22:36:47 +0000 Subject: [PATCH 11/24] Scroll the output buffer when visible --- autoload/vimspector/internal/neojob.vim | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/autoload/vimspector/internal/neojob.vim b/autoload/vimspector/internal/neojob.vim index f8a687a..77d4d2c 100644 --- a/autoload/vimspector/internal/neojob.vim +++ b/autoload/vimspector/internal/neojob.vim @@ -119,7 +119,6 @@ function! s:_OnCommandEvent( category, id, data, event ) abort let last_line = last_line_list[ 0 ] endif - call s:MakeBufferWritable( buffer ) try call setbufline( buffer, '$', last_line . a:data[ 0 ] ) @@ -129,6 +128,17 @@ function! s:_OnCommandEvent( category, id, data, event ) abort call setbufvar( buffer, '&modified', 0 ) endtry + " if the buffer is visible, scroll it + let w = bufwinnr( buffer ) + if w > 0 + let cw = winnr() + try + execute w . 'wincmd w' + normal G + finally + execute cw . 'wincmd w' + endtry + endif endfunction function! s:SetUpHiddenBuffer( buffer ) abort From 6ee8f7875d71090097a864140b88b457c3140d01 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 15 Jan 2020 21:00:15 +0000 Subject: [PATCH 12/24] Tests: Import test framework changs from YCM --- run_tests | 49 ++++++++++++++++++++++++++++++++++++------ tests/.gitignore | 1 + tests/lib/run_test.vim | 1 - 3 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 tests/.gitignore diff --git a/run_tests b/run_tests index f216c58..5200bf1 100755 --- a/run_tests +++ b/run_tests @@ -1,8 +1,23 @@ #!/usr/bin/env bash +if [ "$1" == "--help" ]; then + echo "$(basename $0) " + echo "e.g.: " + echo " - run all tests: $0" + echo " - run specific tests script: $0 signature_help.test.vim" + echo " - run specific tests fun: $0 signature_help.test.vim:Test_signatures_TopLine\(\)" + exit 0 +fi + RUN_VIM="vim --clean --not-a-term" RUN_TEST="${RUN_VIM} -S lib/run_test.vim" +if [ $(node --version | awk 'BEGIN { FS="." } { print $1 }') != "v10" ]; then + echo "ERROR: Tests must be run against node v10 because python." >&2 + echo "You have $(node --version)" >&2 + exit 1 +fi + if [ -z "$VIMSPECTOR_MIMODE" ]; then if which lldb >/dev/null 2>&1; then export VIMSPECTOR_MIMODE=lldb @@ -24,8 +39,8 @@ set -e set +e echo "%DONE - built test programs" -pushd tests > /dev/null - +# Start +pushd $(dirname $0)/tests > /dev/null echo "Running Vimspector Vim tests" RESULT=0 @@ -39,23 +54,45 @@ fi for t in ${TESTS}; do echo "" echo "%RUN: $t" - rm -f messages debuglog # split on : into fileName and testName IFS=: read -s t T <<< "$t" - if ${RUN_TEST} --cmd 'au SwapExists * let v:swapchoice = "e"' $t $T; then + TESTLOGDIR=$(pwd)/logs/$t + + if ${RUN_TEST} --cmd 'au SwapExists * let v:swapchoice = "e"' $t $T \ + && [ -f $t.res ]; then echo "%PASS: $t PASSED" else - cat messages - echo "%FAIL: $t FAILED" + echo "%FAIL: $t FAILED - see $TESTLOGDIR" RESULT=1 fi + + rm -rf $TESTLOGDIR + mkdir -p $TESTLOGDIR + ${RUN_VIM} --version > ${TESTLOGDIR}/vimversion + for l in messages debuglog *.log; do + # In CI we can't view the output files, so we just have to cat them + if [ -f $l ]; then + if [ "$VIMSPECTOR_TEST_STDOUT" ]; then + echo "" + echo "" + echo "*** START: $l ***" + cat $l + echo "*** END: $l ***" + fi + mv $l $TESTLOGDIR + fi + done + + rm -f $t.res done +echo "Done running tests" popd > /dev/null echo "" echo "All done." + exit $RESULT diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..333c1e9 --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1 @@ +logs/ diff --git a/tests/lib/run_test.vim b/tests/lib/run_test.vim index f8cef56..226aa55 100644 --- a/tests/lib/run_test.vim +++ b/tests/lib/run_test.vim @@ -211,7 +211,6 @@ func AfterTheTest() let logfile = s:testid_filesafe . '.vimspector.log' call writefile( log, logfile, 's' ) call add( s:messages, 'Wrote log for failed test: ' . logfile ) - call extend( s:messages, log ) endif endfunc From d711d655aadb1d2fac3ee7549c910f0d9d66e2a9 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 15 Jan 2020 21:15:30 +0000 Subject: [PATCH 13/24] FixUp: Brokern StopOver mapping --- plugin/vimspector.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/vimspector.vim b/plugin/vimspector.vim index 6034d53..61c956a 100644 --- a/plugin/vimspector.vim +++ b/plugin/vimspector.vim @@ -45,7 +45,7 @@ nnoremap VimspectorToggleBreakpoint \ :call vimspector#ToggleBreakpoint() nnoremap VimspectorAddFunctionBreakpoint \ :call vimspector#AddFunctionBreakpoint( expand( '' ) ) -nnoremap VimspectorStopOver :call vimspector#StepOver() +nnoremap VimspectorStepOver :call vimspector#StepOver() nnoremap VimspectorStepInto :call vimspector#StepInto() nnoremap VimspectorStepOut :call vimspector#StepOut() From f6eccf1314cc53e3327db4283757fbd012ba936f Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 15 Jan 2020 21:16:00 +0000 Subject: [PATCH 14/24] More: Import latest YCM test framework changes --- tests/lib/run_test.vim | 131 +++++++++++++++++++++++------------------ 1 file changed, 74 insertions(+), 57 deletions(-) diff --git a/tests/lib/run_test.vim b/tests/lib/run_test.vim index 226aa55..d8821ed 100644 --- a/tests/lib/run_test.vim +++ b/tests/lib/run_test.vim @@ -4,7 +4,7 @@ " " To execute only specific test functions, add a second argument. It will be " matched against the names of the Test_ funtion. E.g.: -" ../vim -u NONE -S runtest.vim test_channel.vim open_delay +" ../vim -Nu NONE vimrc -S lib/run_test.vim test_channel.vim open_delay " The output can be found in the "messages" file. " " The test script may contain anything, only functions that start with @@ -26,8 +26,16 @@ " It will be called after each Test_ function. " " When debugging a test it can be useful to add messages to v:errors: -" call add(v:errors, "this happened") +" call add(v:errors, "this happened") +" +" But for real debug logging: +" call ch_log( ",,,message..." ) +" Then view it in 'debuglog' +" Let a test take up to 1 minute +let s:single_test_timeout = 60000 + +" Restrict the runtimepath to the exact minimum needed for testing set rtp=$PWD/lib,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after if has('packages') let &packpath = &rtp @@ -37,7 +45,7 @@ call ch_logfile( 'debuglog', 'w' ) " For consistency run all tests with 'nocompatible' set. " This also enables use of line continuation. -set nocp viminfo+=nviminfo +set nocp " Use utf-8 by default, instead of whatever the system default happens to be. " Individual tests can overrule this at the top of the file. @@ -47,11 +55,23 @@ set encoding=utf-8 set nomore " Output all messages in English. -lang mess C +lang messages C " Always use forward slashes. set shellslash +func s:TestFailed() + let log = readfile( expand( '~/.vimspector.log' ) ) + let logfile = s:testid_filesafe . '_vimspector.log.testlog' + call writefile( log, logfile, 's' ) + call add( s:messages, 'Wrote log for failed test: ' . logfile ) +endfunc + +func! Abort( timer_id ) + call assert_report( 'Test timed out!!!' ) + qa! +endfunc + func RunTheTest(test) echo 'Executing ' . a:test @@ -107,40 +127,38 @@ func RunTheTest(test) call add(s:messages, 'Executing ' . a:test) let s:done += 1 + let timer = timer_start( s:single_test_timeout, funcref( 'Abort' ) ) - if a:test =~ 'Test_nocatch_' - " Function handles errors itself. This avoids skipping commands after the - " error. + try + let s:test = a:test + let s:testid = g:testpath . ':' . a:test + + let test_filesafe = substitute( a:test, '[)(,:]', '_', 'g' ) + let s:testid_filesafe = g:testpath . '_' . test_filesafe + + au VimLeavePre * call EarlyExit(s:test) exe 'call ' . a:test - else - try - let s:test = a:test - let s:testid = g:testpath . ':' . a:test - let test_filesafe = substitute( a:test, ')', '_', 'g' ) - let test_filesafe = substitute( test_filesafe, '(', '_', 'g' ) - let test_filesafe = substitute( test_filesafe, ',', '_', 'g' ) - let test_filesafe = substitute( test_filesafe, ':', '_', 'g' ) - let s:testid_filesafe = g:testpath . '_' . test_filesafe - au VimLeavePre * call EarlyExit(s:test) - exe 'call ' . a:test - au! VimLeavePre - catch /^\cskipped/ - call add(s:messages, ' Skipped') - call add(s:skipped, - \ 'SKIPPED ' . a:test - \ . ': ' - \ . substitute(v:exception, '^\S*\s\+', '', '')) - catch - call add(v:errors, - \ 'Caught exception in ' . a:test - \ . ': ' - \ . v:exception - \ . ' @ ' - \ . g:testpath - \ . ':' - \ . v:throwpoint) - endtry - endif + au! VimLeavePre + catch /^\cskipped/ + call add(s:messages, ' Skipped') + call add(s:skipped, + \ 'SKIPPED ' . a:test + \ . ': ' + \ . substitute(v:exception, '^\S*\s\+', '', '')) + catch + call add(v:errors, + \ 'Caught exception in ' . a:test + \ . ': ' + \ . v:exception + \ . ' @ ' + \ . g:testpath + \ . ':' + \ . v:throwpoint) + + call s:TestFailed() + endtry + + call timer_stop( timer ) " In case 'insertmode' was set and something went wrong, make sure it is " reset to avoid trouble with anything else. @@ -203,23 +221,16 @@ endfunc func AfterTheTest() if len(v:errors) > 0 let s:fail += 1 + call s:TestFailed() call add(s:errors, 'Found errors in ' . s:testid . ':') call extend(s:errors, v:errors) let v:errors = [] - - let log = readfile( expand( '~/.vimspector.log' ) ) - let logfile = s:testid_filesafe . '.vimspector.log' - call writefile( log, logfile, 's' ) - call add( s:messages, 'Wrote log for failed test: ' . logfile ) endif endfunc func EarlyExit(test) " It's OK for the test we use to test the quit detection. - if a:test != 'Test_zz_quit_detected()' - call add(v:errors, 'Test caused Vim to exit: ' . a:test) - endif - + call add(v:errors, 'Test caused Vim to exit: ' . a:test) call FinishTesting() endfunc @@ -232,17 +243,19 @@ func FinishTesting() if s:fail == 0 " Success, create the .res file so that make knows it's done. - exe 'split ' . fnamemodify(g:testname, ':r') . '.res' - write + call writefile( [], g:testname . '.res', 's' ) endif if len(s:errors) > 0 " Append errors to test.log - split test.log - call append(line('$'), '') - call append(line('$'), 'From ' . g:testpath . ':') - call append(line('$'), s:errors) - write + let l = [] + if filereadable( 'test.log' ) + let l = readfile( 'test.log' ) + endif + call writefile( l->extend( [ '', 'From ' . g:testpath . ':' ] ) + \ ->extend( s:errors ), + \ 'test.log', + \ 's' ) endif if s:done == 0 @@ -263,11 +276,14 @@ func FinishTesting() call extend(s:messages, s:skipped) " Append messages to the file "messages" - split messages - call append(line('$'), '') - call append(line('$'), 'From ' . g:testpath . ':') - call append(line('$'), s:messages) - write + let l = [] + if filereadable( 'messages' ) + let l = readfile( 'messages' ) + endif + call writefile( l->extend( [ '', 'From ' . g:testpath . ':' ] ) + \ ->extend( s:messages ), + \ 'messages', + \ 's' ) if s:fail > 0 cquit! @@ -316,6 +332,7 @@ endif for s:test in sort(s:tests) " Silence, please! set belloff=all + call RunTheTest(s:test) call AfterTheTest() endfor From 3b975002894c88d54af33a1dec7eb7168a86c68f Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 15 Jan 2020 21:44:15 +0000 Subject: [PATCH 15/24] Make sure the buffer is modifiable when updating the console --- python3/vimspector/output.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/python3/vimspector/output.py b/python3/vimspector/output.py index fb90929..38ce6d3 100644 --- a/python3/vimspector/output.py +++ b/python3/vimspector/output.py @@ -117,17 +117,19 @@ class OutputView( object ): def Evaluate( self, frame, expression ): console = self._buffers[ 'Console' ].buf - utils.AppendToBuffer( console, 'Evaluating: ' + expression ) + with utils.ModifiableScratchBuffer( console ): + utils.AppendToBuffer( console, 'Evaluating: ' + expression ) def print_result( message ): - utils.AppendToBuffer( console, - 'Evaluated: ' + expression ) + with utils.ModifiableScratchBuffer( console ): + utils.AppendToBuffer( console, + 'Evaluated: ' + expression ) - result = message[ 'body' ][ 'result' ] - if result is None: - result = 'null' + result = message[ 'body' ][ 'result' ] + if result is None: + result = 'null' - utils.AppendToBuffer( console, ' Result: ' + result ) + utils.AppendToBuffer( console, ' Result: ' + result ) request = { 'command': 'evaluate', From 2252a2bf02f9dce2fa96c83effa94ebff8ea4995 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 15 Jan 2020 21:44:41 +0000 Subject: [PATCH 16/24] Delete the watches and vars buffers when resetting --- python3/vimspector/variables.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/python3/vimspector/variables.py b/python3/vimspector/variables.py index f0ff99e..759abdf 100644 --- a/python3/vimspector/variables.py +++ b/python3/vimspector/variables.py @@ -105,6 +105,9 @@ class VariablesView( object ): for k, v in self._oldoptions.items(): vim.options[ k ] = v + vim.command( 'bdelete! ' + str( self._watch.win.buffer.number ) ) + vim.command( 'bdelete! ' + str( self._vars.win.buffer.number ) ) + def LoadScopes( self, frame ): def scopes_consumer( message ): old_scopes = self._scopes From c2b0cc8f18203a930d0c409844ae50a2dd9f7e75 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 15 Jan 2020 21:45:13 +0000 Subject: [PATCH 17/24] Attempt to make the output windows a little less rubbish on neovim --- autoload/vimspector/internal/neojob.vim | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/autoload/vimspector/internal/neojob.vim b/autoload/vimspector/internal/neojob.vim index 77d4d2c..339b5f2 100644 --- a/autoload/vimspector/internal/neojob.vim +++ b/autoload/vimspector/internal/neojob.vim @@ -111,17 +111,17 @@ function! s:_OnCommandEvent( category, id, data, event ) abort call bufload( buffer ) - let last_line_list = getbufline( buffer, '$' ) - - if len( last_line_list ) == 0 - let last_line = '' - else - let last_line = last_line_list[ 0 ] - endif + let numlines = py3eval( "len( vim.buffers[ int( vim.eval( 'buffer' ) ) ] )" ) + let last_line = getbufline( buffer, '$' )[ 0 ] call s:MakeBufferWritable( buffer ) try - call setbufline( buffer, '$', last_line . a:data[ 0 ] ) + if numlines == 1 && last_line ==# '' + call setbufline( buffer, 1, a:data[ 0 ] ) + else + call setbufline( buffer, '$', last_line . a:data[ 0 ] ) + endif + call appendbufline( buffer, '$', a:data[ 1: ] ) finally call s:MakeBufferReadOnly( buffer ) @@ -134,7 +134,7 @@ function! s:_OnCommandEvent( category, id, data, event ) abort let cw = winnr() try execute w . 'wincmd w' - normal G + normal Gz. finally execute cw . 'wincmd w' endtry @@ -144,6 +144,7 @@ endfunction function! s:SetUpHiddenBuffer( buffer ) abort call setbufvar( a:buffer, '&hidden', 1 ) call setbufvar( a:buffer, '&bufhidden', 'hide' ) + call setbufvar( a:buffer, '&wrap', 0 ) call s:MakeBufferReadOnly( a:buffer ) endfunction From 099ffc2af92722ac704f32f1b690bffb94e3eb39 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 15 Jan 2020 23:14:40 +0000 Subject: [PATCH 18/24] Disable swap files in the neovim buffers too --- autoload/vimspector/internal/neojob.vim | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/autoload/vimspector/internal/neojob.vim b/autoload/vimspector/internal/neojob.vim index 339b5f2..bfe987b 100644 --- a/autoload/vimspector/internal/neojob.vim +++ b/autoload/vimspector/internal/neojob.vim @@ -48,11 +48,11 @@ function! vimspector#internal#neojob#StartDebugSession( config ) abort \ 'on_stderr': funcref( 's:_OnEvent' ), \ 'on_exit': funcref( 's:_OnEvent' ), \ 'cwd': a:config[ 'cwd' ], + \ 'env': a:config[ 'env' ], \ } \ ) " FIXME: Missing in neovim 0.4. But in master: - " \ 'env': a:config[ 'env' ], " " FIXME: error handling ? @@ -82,14 +82,12 @@ endfunction function! vimspector#internal#neojob#StopDebugSession() abort if !exists( 's:job' ) - echom "Not stopping session: Job doesn't exist" - redraw return endif if s:JobIsRunning( s:job ) - echom 'Terminating job' - redraw + echom 'Terminating job' + redraw call jobstop( s:job ) endif endfunction @@ -145,6 +143,7 @@ function! s:SetUpHiddenBuffer( buffer ) abort call setbufvar( a:buffer, '&hidden', 1 ) call setbufvar( a:buffer, '&bufhidden', 'hide' ) call setbufvar( a:buffer, '&wrap', 0 ) + call setbufvar( a:buffer, '&swapfile', 0 ) call s:MakeBufferReadOnly( a:buffer ) endfunction From 1e8bd384b91f24d976dc6a4773212fadea62e69e Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 15 Jan 2020 23:23:22 +0000 Subject: [PATCH 19/24] FixUp: importing ycm test lib changs' --- run_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run_tests b/run_tests index 5200bf1..812aad5 100755 --- a/run_tests +++ b/run_tests @@ -71,7 +71,7 @@ for t in ${TESTS}; do rm -rf $TESTLOGDIR mkdir -p $TESTLOGDIR ${RUN_VIM} --version > ${TESTLOGDIR}/vimversion - for l in messages debuglog *.log; do + for l in messages debuglog test.log *.testlog; do # In CI we can't view the output files, so we just have to cat them if [ -f $l ]; then if [ "$VIMSPECTOR_TEST_STDOUT" ]; then From 355f0f0e0c09569f0dba29a12be55075da4d16dc Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 17 Jan 2020 00:02:24 +0000 Subject: [PATCH 20/24] Implement command line completion for watch/eval --- autoload/vimspector.vim | 5 +++- plugin/vimspector.vim | 4 +-- .../vimspector/debug_adapter_connection.py | 27 +++++++++++++++++++ python3/vimspector/debug_session.py | 20 ++++++++++++++ 4 files changed, 53 insertions(+), 3 deletions(-) diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index c3ead44..f2b39d5 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -121,7 +121,10 @@ function! vimspector#CompleteOutput( ArgLead, CmdLine, CursorPos ) abort endfunction function! vimspector#CompleteExpr( ArgLead, CmdLine, CursorPos ) abort - return [] + return join( py3eval( '_vimspector_session.GetCompletionsSync( ' + \.' vim.eval( "a:CmdLine" ),' + \.' int( vim.eval( "a:CursorPos" ) ) )' ), + \ "\n" ) endfunction " Boilerplate {{{ diff --git a/plugin/vimspector.vim b/plugin/vimspector.vim index 61c956a..0c71090 100644 --- a/plugin/vimspector.vim +++ b/plugin/vimspector.vim @@ -71,13 +71,13 @@ elseif s:mappings ==# 'HUMAN' nmap VimspectorStepOut endif -command! -bar -nargs=1 -complete=customlist,vimspector#CompleteExpr +command! -bar -nargs=1 -complete=custom,vimspector#CompleteExpr \ VimspectorWatch \ call vimspector#AddWatch( ) command! -bar -nargs=1 -complete=custom,vimspector#CompleteOutput \ VimspectorShowOutput \ call vimspector#ShowOutput( ) -command! -bar -nargs=1 -complete=customlist,vimspector#CompleteExpr +command! -bar -nargs=1 -complete=custom,vimspector#CompleteExpr \ VimspectorEval \ call vimspector#Evaluate( ) command! -bar diff --git a/python3/vimspector/debug_adapter_connection.py b/python3/vimspector/debug_adapter_connection.py index 73a4549..295b83d 100644 --- a/python3/vimspector/debug_adapter_connection.py +++ b/python3/vimspector/debug_adapter_connection.py @@ -65,6 +65,33 @@ class DebugAdapterConnection( object ): if not self._SendMessage( msg ): self._AbortRequest( request, 'Unable to send message' ) + + def DoRequestSync( self, msg, timeout = 5000 ): + result = {} + + def handler( msg ): + result[ 'response' ] = msg + + def failure_handler( reason, msg ): + result[ 'response' ] = msg + result[ 'exception' ] = RuntimeError( reason ) + + self.DoRequest( handler, msg, failure_handler, timeout ) + + bug_catcher = 1000 + while not result and bug_catcher >= 0: + vim.command( 'sleep 10m' ) + bug_catcher -= 10 + + if result.get( 'exception' ) is not None: + raise result[ 'exception' ] + + if result.get( 'response' ) is None: + raise RuntimeError( "No response" ) + + return result[ 'response' ] + + def OnRequestTimeout( self, timer_id ): request_id = None for seq, request in self._outstanding_requests.items(): diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index a4d801b..474e3d0 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -406,6 +406,26 @@ class DebugSession( object ): def GetOutputBuffers( self ): return self._outputView.GetCategories() + def GetCompletionsSync( self, text_line, column_in_bytes ): + if not self._server_capabilities.get( 'supportsCompletionsRequest' ): + return [] + + response = self._connection.DoRequestSync( { + 'command': 'completions', + 'arguments': { + 'frameId': self._stackTraceView.GetCurrentFrame()[ 'id' ], + # TODO: encoding ? bytes/codepoints + 'text': text_line, + 'column': column_in_bytes + } + } ) + # TODO: + # - start / length + # - sortText + return [ i.get( 'text' ) or i[ 'label' ] + for i in response[ 'body' ][ 'targets' ] ] + + def _SetUpUI( self ): vim.command( 'tabnew' ) self._uiTab = vim.current.tabpage From 7ca51f8f080d41e9ab3af0debade6a978513f8f6 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sun, 19 Jan 2020 10:22:43 +0000 Subject: [PATCH 21/24] FixUp: Node <10 not node=10 --- run_tests | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/run_tests b/run_tests index 812aad5..1c59f76 100755 --- a/run_tests +++ b/run_tests @@ -12,8 +12,10 @@ fi RUN_VIM="vim --clean --not-a-term" RUN_TEST="${RUN_VIM} -S lib/run_test.vim" -if [ $(node --version | awk 'BEGIN { FS="." } { print $1 }') != "v10" ]; then - echo "ERROR: Tests must be run against node v10 because python." >&2 +NODE_VERSION_MAJ=$(node --version \ + | awk 'BEGIN { FS="." } { print substr( $1, 2 ) }') +if [ ${NODE_VERSION_MAJ} -gt "10" ]; then + echo "ERROR: Tests must be run against node 10 or earlier because python." >&2 echo "You have $(node --version)" >&2 exit 1 fi From ef4a6fc10cfcb8c2ae21d552599b9b834ab6df18 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sun, 19 Jan 2020 10:28:34 +0000 Subject: [PATCH 22/24] FixUp: use normal! to avoid user mappings, thanks vint! --- autoload/vimspector/internal/neojob.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/vimspector/internal/neojob.vim b/autoload/vimspector/internal/neojob.vim index bfe987b..5650029 100644 --- a/autoload/vimspector/internal/neojob.vim +++ b/autoload/vimspector/internal/neojob.vim @@ -132,7 +132,7 @@ function! s:_OnCommandEvent( category, id, data, event ) abort let cw = winnr() try execute w . 'wincmd w' - normal Gz. + normal! Gz. finally execute cw . 'wincmd w' endtry From 6cf4f9f9ab175527f11c66dd490ba4d5c52728b2 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sun, 19 Jan 2020 20:07:18 +0000 Subject: [PATCH 23/24] FixUp: Some comments --- autoload/vimspector/internal/neojob.vim | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/autoload/vimspector/internal/neojob.vim b/autoload/vimspector/internal/neojob.vim index 5650029..5b95fea 100644 --- a/autoload/vimspector/internal/neojob.vim +++ b/autoload/vimspector/internal/neojob.vim @@ -31,6 +31,8 @@ function! s:_OnEvent( chan_id, data, event ) abort echom 'Channel exit with status ' . a:data redraw unlet s:job + " This causes terminal spam in neovim due to + " https://github.com/neovim/neovim/issues/11725 py3 _vimspector_session.OnServerExit( vim.eval( 'a:data' ) ) endif endfunction @@ -52,10 +54,7 @@ function! vimspector#internal#neojob#StartDebugSession( config ) abort \ } \ ) - " FIXME: Missing in neovim 0.4. But in master: - " - - " FIXME: error handling ? + " FIXME: env might not work: Missing in neovim 0.4. But in master: return v:true endfunction From 5ee8ffc3f69a261ee8e1c675739b9effa836e546 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sun, 19 Jan 2020 20:16:52 +0000 Subject: [PATCH 24/24] Catch E325 in neovim --- autoload/vimspector/internal/neojob.vim | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/autoload/vimspector/internal/neojob.vim b/autoload/vimspector/internal/neojob.vim index 5b95fea..f885337 100644 --- a/autoload/vimspector/internal/neojob.vim +++ b/autoload/vimspector/internal/neojob.vim @@ -106,7 +106,12 @@ function! s:_OnCommandEvent( category, id, data, event ) abort let buffer = s:commands[ a:category ][ a:id ].stderr endif - call bufload( buffer ) + try + call bufload( buffer ) + catch /E325/ + " Ignore E325/ATTENTION + endtry + let numlines = py3eval( "len( vim.buffers[ int( vim.eval( 'buffer' ) ) ] )" ) let last_line = getbufline( buffer, '$' )[ 0 ]