From cb0fdc7613db4be80e70854135403be1a1f95c12 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 26 Feb 2021 19:21:40 +0000 Subject: [PATCH 01/73] Add a way to have adapter specific message handlers --- python3/vimspector/custom/java.py | 34 +++++++++++++++++++ .../vimspector/debug_adapter_connection.py | 32 ++++++++--------- python3/vimspector/debug_session.py | 16 ++++++++- python3/vimspector/gadgets.py | 3 +- support/test/java/test_project/pom.xml | 4 +-- 5 files changed, 67 insertions(+), 22 deletions(-) create mode 100644 python3/vimspector/custom/java.py diff --git a/python3/vimspector/custom/java.py b/python3/vimspector/custom/java.py new file mode 100644 index 0000000..ebfec35 --- /dev/null +++ b/python3/vimspector/custom/java.py @@ -0,0 +1,34 @@ +# vimspector - A multi-language debugging system for Vim +# Copyright 2021 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. + +from vimspector.debug_session import DebugSession +from vimspector import utils + + +class JavaDebugAdapter( object ): + def __init__( self, debug_session: DebugSession ): + self.debug_session = debug_session + + def OnEvent_hotcodereplace( self, message ): + # Hack for java debug server hot-code-replace + if utils.Call( 'confirm', + 'Code has changed, hot reload?', + '&Yes,&No', + 1, + 'Question' ) == 1: + self.debug_session._connection.DoRequest( None, { + 'command': 'redefineClasses', + 'arguments': {}, + } ) diff --git a/python3/vimspector/debug_adapter_connection.py b/python3/vimspector/debug_adapter_connection.py index 283c40c..df2ef13 100644 --- a/python3/vimspector/debug_adapter_connection.py +++ b/python3/vimspector/debug_adapter_connection.py @@ -29,14 +29,14 @@ class PendingRequest( object ): class DebugAdapterConnection( object ): - def __init__( self, handler, send_func ): + def __init__( self, handlers, send_func ): self._logger = logging.getLogger( __name__ ) utils.SetUpLogging( self._logger ) self._Write = send_func self._SetState( 'READ_HEADER' ) self._buffer = bytes() - self._handler = handler + self._handlers = handlers self._next_message_id = 0 self._outstanding_requests = {} @@ -124,7 +124,7 @@ class DebugAdapterConnection( object ): def Reset( self ): self._Write = None - self._handler = None + self._handlers = None while self._outstanding_requests: _, request = self._outstanding_requests.popitem() @@ -237,7 +237,7 @@ class DebugAdapterConnection( object ): def _OnMessageReceived( self, message ): - if not self._handler: + if not self._handlers: return if message[ 'type' ] == 'response': @@ -270,25 +270,21 @@ class DebugAdapterConnection( object ): self._logger.error( 'Request failed: {0}'.format( reason ) ) if request.failure_handler: request.failure_handler( reason, message ) - elif 'OnFailure' in dir( self._handler ): - self._handler.OnFailure( reason, request.msg, message ) else: - utils.UserMessage( 'Request failed: {0}'.format( reason ) ) + for h in self._handlers: + if 'OnFailure' in dir( h ): + h.OnFailure( reason, request.msg, message ) + elif message[ 'type' ] == 'event': method = 'OnEvent_' + message[ 'event' ] - if method in dir( self._handler ): - getattr( self._handler, method )( message ) - else: - utils.UserMessage( 'Unhandled event: {0}'.format( message[ 'event' ] ), - persist = True ) + for h in self._handlers: + if method in dir( h ): + getattr( h, method )( message ) elif message[ 'type' ] == 'request': method = 'OnRequest_' + message[ 'command' ] - if method in dir( self._handler ): - getattr( self._handler, method )( message ) - else: - utils.UserMessage( - 'Unhandled request: {0}'.format( message[ 'command' ] ), - persist = True ) + for h in self._handlers: + if method in dir( h ): + getattr( h, method )( message ) def _KillTimer( request ): diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 6fb0b16..ae7de72 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -21,6 +21,7 @@ import shlex import subprocess import functools import vim +import importlib from vimspector import ( breakpoints, code, @@ -781,8 +782,21 @@ class DebugSession( object ): self._splash_screen, "Unable to start adapter" ) else: + if 'custom_handler' in self._adapter: + spec = self._adapter[ 'custom_handler' ] + if isinstance( spec, dict ): + module = spec[ 'module' ] + cls = spec[ 'class' ] + else: + module, cls = spec.rsplit( '.', 1 ) + + CustomHandler = getattr( importlib.import_module( module ), cls ) + handlers = [ CustomHandler( self ), self ] + else: + handlers = [ self ] + self._connection = debug_adapter_connection.DebugAdapterConnection( - self, + handlers, lambda msg: utils.Call( "vimspector#internal#{}#Send".format( self._connection_type ), msg ) ) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index d1b6872..5c61074 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -159,7 +159,8 @@ GADGETS = { "port": "${DAPPort}", "configuration": { "cwd": "${workspaceRoot}" - } + }, + 'custom_handler': 'vimspector.custom.java.JavaDebugAdapter' } }, }, diff --git a/support/test/java/test_project/pom.xml b/support/test/java/test_project/pom.xml index 890e7e8..e6dc4d3 100644 --- a/support/test/java/test_project/pom.xml +++ b/support/test/java/test_project/pom.xml @@ -4,7 +4,7 @@ TestApplication 1 - 8 - 8 + 11 + 11 From f92f2c5d93c20fe9b4789ed3949ad8f2d5cbeca9 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 2 Mar 2021 10:48:55 +0000 Subject: [PATCH 02/73] Print hotcodereplace messages --- python3/vimspector/custom/java.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/python3/vimspector/custom/java.py b/python3/vimspector/custom/java.py index ebfec35..0dfa89c 100644 --- a/python3/vimspector/custom/java.py +++ b/python3/vimspector/custom/java.py @@ -23,12 +23,18 @@ class JavaDebugAdapter( object ): def OnEvent_hotcodereplace( self, message ): # Hack for java debug server hot-code-replace - if utils.Call( 'confirm', - 'Code has changed, hot reload?', - '&Yes,&No', - 1, - 'Question' ) == 1: - self.debug_session._connection.DoRequest( None, { - 'command': 'redefineClasses', - 'arguments': {}, - } ) + body = message.get( 'body' ) or {} + + if body.get( 'type' ) != 'hotcodereplace': + 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': {}, + } ) + elif body.get( 'message' ): + utils.UserMessage( 'Hot code replace: ' + body[ 'message' ] ) + From f4831657b848911a9c20a021080b0389b49463d7 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 4 Mar 2021 21:44:54 +0000 Subject: [PATCH 03/73] Use popup for confirmations (note these have to be async) --- autoload/vimspector/internal/neopopup.vim | 22 ++++++++ autoload/vimspector/internal/popup.vim | 31 +++++++++++ python3/vimspector/custom/java.py | 17 +++--- python3/vimspector/debug_session.py | 63 ++++++++++++++--------- python3/vimspector/utils.py | 29 ++++++++++- 5 files changed, 129 insertions(+), 33 deletions(-) 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 ae7de72..9f6e863 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -804,39 +804,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 e7cb537..5aefc37 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 ): From 32360236ff93f924b579933acbb249ba62ca6615 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 5 Mar 2021 21:09:39 +0000 Subject: [PATCH 04/73] Allow forcing selection from the menu with F5 --- autoload/vimspector.vim | 4 ++-- plugin/vimspector.vim | 3 +++ python3/vimspector/debug_session.py | 7 ++++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index e94a177..c4a1756 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -41,11 +41,11 @@ function! s:Enabled() abort return s:enabled endfunction -function! vimspector#Launch() abort +function! vimspector#Launch( ... ) abort if !s:Enabled() return endif - py3 _vimspector_session.Start() + py3 _vimspector_session.Start( *vim.eval( 'a:000' ) ) endfunction function! vimspector#LaunchWithSettings( settings ) abort diff --git a/plugin/vimspector.vim b/plugin/vimspector.vim index 53855ef..24f8914 100644 --- a/plugin/vimspector.vim +++ b/plugin/vimspector.vim @@ -35,6 +35,8 @@ let s:mappings = get( g:, 'vimspector_enable_mappings', '' ) nnoremap VimspectorContinue \ :call vimspector#Continue() +nnoremap VimspectorLaunch + \ :call vimspector#Launch( v:true ) nnoremap VimspectorStop \ :call vimspector#Stop() nnoremap VimspectorRestart @@ -79,6 +81,7 @@ if s:mappings ==# 'VISUAL_STUDIO' nmap VimspectorStepOut elseif s:mappings ==# 'HUMAN' nmap VimspectorContinue + nmap VimspectorLaunch nmap VimspectorStop nmap VimspectorRestart nmap VimspectorPause diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 9f6e863..03874f3 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -100,7 +100,7 @@ class DebugSession( object ): return launch_config_file, configurations - def Start( self, launch_variables = None ): + def Start( self, force_choose=False, launch_variables = None ): # We mutate launch_variables, so don't mutate the default argument. # https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments if launch_variables is None: @@ -135,6 +135,11 @@ class DebugSession( object ): if 'configuration' in launch_variables: configuration_name = launch_variables.pop( 'configuration' ) + elif force_choose: + # Always display the menu + configuration_name = utils.SelectFromList( + 'Which launch configuration?', + sorted( configurations.keys() ) ) elif ( len( configurations ) == 1 and next( iter( configurations.values() ) ).get( "autoselect", True ) ): configuration_name = next( iter( configurations.keys() ) ) From c2353b388d027e35be9b069b60214e8395a8ed54 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 5 Mar 2021 21:10:08 +0000 Subject: [PATCH 05/73] WIP: Data breakpoints (though can't find a server which supports them) --- autoload/vimspector.vim | 8 +++++ python3/vimspector/breakpoints.py | 39 ++++++++++++++++++++++ python3/vimspector/debug_session.py | 15 +++++++++ python3/vimspector/variables.py | 27 +++++++++++++++ support/test/go/hello_world/hello-world.go | 19 +++++++++++ 5 files changed, 108 insertions(+) diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index c4a1756..39af248 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -220,6 +220,14 @@ function! vimspector#SetVariableValue( ... ) abort endif endfunction +function! vimspector#AddDataBreakpoint( ... ) abort + if !s:Enabled() + return + endif + " TODO: how to set options? + py3 _vimspector_session.AddDataBreakpoint( {} ) +endfunction + function! vimspector#DeleteWatch() abort if !s:Enabled() return diff --git a/python3/vimspector/breakpoints.py b/python3/vimspector/breakpoints.py index 7aa50ce..5c21140 100644 --- a/python3/vimspector/breakpoints.py +++ b/python3/vimspector/breakpoints.py @@ -45,6 +45,7 @@ class ProjectBreakpoints( object ): self._func_breakpoints = [] self._exception_breakpoints = None self._configured_breakpoints = {} + self._data_breakponts = [] # FIXME: Remove this. Remove breakpoints nonesense from code.py self._breakpoints_handler = None @@ -270,6 +271,18 @@ class ProjectBreakpoints( object ): # TODO: We don't really have aanything to update here, but if we're going to # have a UI list of them we should update that at this point + # but note that while debugging, this is when we actually _send_ the + # breakpoints. + self.UpdateUI() + + + def AddDataBreakpoint( self, dataId, options ): + self._data_breakponts.append( { + 'state': 'ENABLED', + 'dataId': dataId, + 'options': options, + } ) + self.UpdateUI() @@ -402,6 +415,27 @@ class ProjectBreakpoints( object ): failure_handler = response_received ) + if self._data_breakponts and self._server_capabilities[ + 'supportsDataBreakpoints' ]: + awaiting += 1 + breakpoints = [] + for bp in self._data_breakponts: + if bp[ 'state' ] != 'ENABLED': + continue + data_bp = {} + data_bp.update( bp[ 'options' ] ) + data_bp[ 'dataId' ] = bp[ 'dataId' ] + breakpoints.append( data_bp ) + + self._connection.DoRequest( + lambda msg: response_handler( None, None ), + { + 'command': 'setDataBreakpoints', + 'arguments': breakpoints, + }, + failure_handler = response_received + ) + if self._exception_breakpoints: awaiting = awaiting + 1 self._connection.DoRequest( @@ -494,6 +528,11 @@ class ProjectBreakpoints( object ): file_name, bp[ 'line' ] ) + # TODO could/should we show a sign in the variables view when there's a data + # brakpoint on the variable? Not sure how best to actually do that, but + # maybe the variable view can pass that info when calling AddDataBreakpoint, + # such as the variablesReference/name + def _SignToLine( self, file_name, bp ): if 'sign_id' not in bp: diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 03874f3..80fe75f 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -535,6 +535,21 @@ class DebugSession( object ): def SetVariableValue( self, new_value = None, buf = None, line_num = None ): self._variablesView.SetVariableValue( new_value, buf, line_num ) + @IfConnected() + def AddDataBreakpoint( self, opts, buf = None, line_num = None ): + def add_bp( breakpoint_info ): + if breakpoint_info[ 'dataId' ] is None: + utils.UserMessage( + "Can't set data breakpoint here: { breakpoint_info[ 'description' ] }" + ) + return + + # TODO: Ask the user about the possible DataBreakpointAccessType's and add + # that in to opts here + self._breakpoints.AddDataBreakpoint( breakpoint_info[ 'dataId' ], opts ) + + self._variablesView.GetDataBreakpointInfo( add_bp, buf, line_num ) + @IfConnected() def AddWatch( self, expression ): self._variablesView.AddWatch( self._stackTraceView.GetCurrentFrame(), diff --git a/python3/vimspector/variables.py b/python3/vimspector/variables.py index 8dcb493..8d8498a 100644 --- a/python3/vimspector/variables.py +++ b/python3/vimspector/variables.py @@ -580,6 +580,33 @@ class VariablesView( object ): }, failure_handler = failure_handler ) + def GetDataBreakpointInfo( self, + then, + buf = None, + line_num = None ): + variable: Variable + view: View + + if not self._server_capabilities.get( 'supportsDataBreakpoints' ): + return None + + variable, view = self._GetVariable( buf, line_num ) + if variable is None: + return None + + arguments = { + 'name': variable.variable[ 'name' ], + } + if variable.IsContained(): + arguments[ 'variablesReference' ] = ( + variable.container.VariablesReference() ) + + self._connection.DoRequest( lambda msg: then( msg[ 'body' ] ), { + 'command': 'dataBreakpointInfo', + 'arguments': arguments, + } ) + + def _DrawVariables( self, view, variables, indent, is_short = False ): assert indent > 0 diff --git a/support/test/go/hello_world/hello-world.go b/support/test/go/hello_world/hello-world.go index 673d1b2..efff2c0 100644 --- a/support/test/go/hello_world/hello-world.go +++ b/support/test/go/hello_world/hello-world.go @@ -1,6 +1,25 @@ package main import "fmt" + +type Toaster struct { + Power int + Colour string +} + +type Test struct { + Test string + Toast Toaster +} + func main() { var v = "test" + test := Test{ + Test: "This is\na\ntest", + Toast: Toaster{ + Power: 10, + Colour: "green", + }, + } fmt.Println("hello world: " + v) + fmt.Println("Hi " + test.Test) } From af57d2dbdb6e0d6a5f7cec6914492da574ec806a Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 5 Mar 2021 21:19:37 +0000 Subject: [PATCH 06/73] Print server capabilities in a readable way --- python3/vimspector/debug_session.py | 4 ++++ python3/vimspector/output.py | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 80fe75f..8c671af 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -1049,6 +1049,10 @@ class DebugSession( object ): # def handle_initialize_response( msg ): self._server_capabilities = msg.get( 'body' ) or {} + self._outputView.Print( + 'server', + 'Server Capabilities:\n' + json.dumps( self._server_capabilities, + indent = 2 ) ) self._breakpoints.SetServerCapabilities( self._server_capabilities ) self._variablesView.SetServerCapabilities( self._server_capabilities ) self._Launch() diff --git a/python3/vimspector/output.py b/python3/vimspector/output.py index c453417..df1e0c6 100644 --- a/python3/vimspector/output.py +++ b/python3/vimspector/output.py @@ -64,8 +64,8 @@ class OutputView( object ): self._api_prefix = api_prefix VIEWS.add( self ) - def Print( self, categroy, text ): - self._Print( 'server', text.splitlines() ) + def Print( self, category, text ): + self._Print( category, text.splitlines() ) def OnOutput( self, event ): category = CategoryToBuffer( event.get( 'category' ) or 'output' ) From c012f9520ebf07d591f48174129467825fc2b766 Mon Sep 17 00:00:00 2001 From: Tony Dwire Date: Tue, 9 Mar 2021 19:45:27 -0600 Subject: [PATCH 07/73] Updated netcoredbg to 1.2.0-738 --- python3/vimspector/gadgets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index d1b6872..f6c3639 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -233,7 +233,7 @@ GADGETS = { 'format': 'tar', }, 'all': { - 'version': '1.2.0-635' + 'version': '1.2.0-738' }, 'macos': { 'file_name': 'netcoredbg-osx.tar.gz', From 38c843219e36ec381b44a14c32a44850d418bc41 Mon Sep 17 00:00:00 2001 From: Tony Dwire Date: Tue, 9 Mar 2021 19:55:38 -0600 Subject: [PATCH 08/73] Updated file name for netcoredbg to reflect new filename. Overrode version for macos since there is no new build for it yet. --- python3/vimspector/gadgets.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index f6c3639..ab4c1e4 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -237,11 +237,12 @@ GADGETS = { }, 'macos': { 'file_name': 'netcoredbg-osx.tar.gz', + 'version': '1.2.0-536', 'checksum': '71c773e34d358950f25119bade7e3081c4c2f9d71847bd49027ca5792e918beb', }, 'linux': { - 'file_name': 'netcoredbg-linux-bionic.tar.gz', + 'file_name': 'netcoredbg-linux-bionic-amd64.tar.gz', 'checksum': '', }, 'windows': { From 2a635294d0b549c8ab8f90cf2cacc8f597c2bad8 Mon Sep 17 00:00:00 2001 From: Tony Dwire Date: Tue, 9 Mar 2021 20:11:58 -0600 Subject: [PATCH 09/73] Fix wrong version number for macos version. --- python3/vimspector/gadgets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index ab4c1e4..6974367 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -237,7 +237,7 @@ GADGETS = { }, 'macos': { 'file_name': 'netcoredbg-osx.tar.gz', - 'version': '1.2.0-536', + 'version': '1.2.0-635', 'checksum': '71c773e34d358950f25119bade7e3081c4c2f9d71847bd49027ca5792e918beb', }, From 7d2770f3c486ba34acc7eab52dfc1df6af353056 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Mon, 8 Mar 2021 23:00:45 +0000 Subject: [PATCH 10/73] Add vertical (i.e. narrow) layout This puts the 3 utility windows at the top, horizontally split, with the code view below. The terminal window is drawn either vertically split (if there's room) or horizontally split otherwise. The output window remains at tht bottom. We add equivalent sizing options too, setting some defauts that roughly work on my macbook pro. We try to guess the best layout to use. In particular we go into 'narrow' mode if there are not enough horizonal columns to fit the sidebar, code and at least the minimum terminal size. We also try to move the terminal to be horizontally spit (i.e. vertically stacked) if we can fit the max number of lines, but only the min number of columns. This is all a little heuristic, but when testing it myself, it feels good and tends to pick a good option by default. Users can always customise the ui mode (g:vimspector_ui_mode and all the various specific width options) --- python3/vimspector/debug_session.py | 91 +++++++ python3/vimspector/settings.py | 19 +- python3/vimspector/terminal.py | 55 ++++- tests/lib/autoload/vimspector/test/setup.vim | 56 +++++ tests/ui.test.vim | 247 +++++++++++++++++++ 5 files changed, 461 insertions(+), 7 deletions(-) diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 6fb0b16..4a89cdf 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -655,6 +655,37 @@ class DebugSession( object ): vim.command( 'tab split' ) self._uiTab = vim.current.tabpage + mode = settings.Get( 'ui_mode' ) + + self._logger.debug( 'ui_mode = %s', mode ) + + if mode == 'auto': + # Go vertical if there isn't enough horizontal space for at least: + # the left bar width + # + the code min width + # + the terminal min width + # + enough space for a sign column and number column? + min_width = ( settings.Int( 'sidebar_width' ) + + 1 + 2 + 3 + + settings.Int( 'code_minwidth' ) + + 1 + settings.Int( 'terminal_minwidth' ) ) + + mode = ( 'vertical' + if vim.options[ 'columns' ] < min_width + else 'horizontal' ) + + self._logger.debug( 'min_width: %s, actual: %s - result: %s', + min_width, + vim.options[ 'columns' ], + mode ) + + if mode == 'vertical': + self._SetUpUIVertical() + else: + self._SetUpUIHorizontal() + + + def _SetUpUIHorizontal( self ): # Code window code_window = vim.current.window self._codeView = code.CodeView( code_window, self._api_prefix ) @@ -695,6 +726,66 @@ class DebugSession( object ): # TODO: If/when we support multiple sessions, we'll need some way to # indicate which tab was created and store all the tabs vim.vars[ 'vimspector_session_windows' ] = { + 'mode': 'horizontal', + 'tabpage': self._uiTab.number, + 'code': utils.WindowID( code_window, self._uiTab ), + 'stack_trace': utils.WindowID( stack_trace_window, self._uiTab ), + 'variables': utils.WindowID( vars_window, self._uiTab ), + 'watches': utils.WindowID( watch_window, self._uiTab ), + 'output': utils.WindowID( output_window, self._uiTab ), + 'eval': None # this is going to be updated every time eval popup is opened + } + with utils.RestoreCursorPosition(): + with utils.RestoreCurrentWindow(): + with utils.RestoreCurrentBuffer( vim.current.window ): + vim.command( 'doautocmd User VimspectorUICreated' ) + + + def _SetUpUIVertical( self ): + # Code window + code_window = vim.current.window + self._codeView = code.CodeView( code_window, self._api_prefix ) + + # Call stack + vim.command( + f'topleft { settings.Int( "topbar_height" ) }new' ) + stack_trace_window = vim.current.window + one_third = int( vim.eval( 'winwidth( 0 )' ) ) / 3 + self._stackTraceView = stack_trace.StackTraceView( self, + stack_trace_window ) + + + # Watches + vim.command( 'leftabove vertical new' ) + watch_window = vim.current.window + + # Variables + vim.command( 'leftabove vertical new' ) + vars_window = vim.current.window + + + with utils.LetCurrentWindow( vars_window ): + vim.command( f'{ one_third }wincmd |' ) + with utils.LetCurrentWindow( watch_window ): + vim.command( f'{ one_third }wincmd |' ) + with utils.LetCurrentWindow( stack_trace_window ): + vim.command( f'{ one_third }wincmd |' ) + + self._variablesView = variables.VariablesView( vars_window, + watch_window ) + + + # Output/logging + vim.current.window = code_window + vim.command( f'rightbelow { settings.Int( "bottombar_height" ) }new' ) + output_window = vim.current.window + self._outputView = output.DAPOutputView( output_window, + self._api_prefix ) + + # TODO: If/when we support multiple sessions, we'll need some way to + # indicate which tab was created and store all the tabs + vim.vars[ 'vimspector_session_windows' ] = { + 'mode': 'vertical', 'tabpage': self._uiTab.number, 'code': utils.WindowID( code_window, self._uiTab ), 'stack_trace': utils.WindowID( stack_trace_window, self._uiTab ), diff --git a/python3/vimspector/settings.py b/python3/vimspector/settings.py index 9ad9e41..e9e76ea 100644 --- a/python3/vimspector/settings.py +++ b/python3/vimspector/settings.py @@ -20,11 +20,20 @@ from vimspector import utils DEFAULTS = { # UI - 'bottombar_height': 10, - 'sidebar_width': 50, - 'code_minwidth': 82, - 'terminal_maxwidth': 80, - 'terminal_minwidth': 10, + 'ui_mode': 'auto', + 'bottombar_height': 10, + + # For ui_mode = 'horizontal': + 'sidebar_width': 50, + 'code_minwidth': 82, + 'terminal_maxwidth': 80, + 'terminal_minwidth': 10, + + # For ui_mode = 'vertical': + 'topbar_height': 15, + 'code_minheight': 20, + 'terminal_maxheight': 15, + 'terminal_minheight': 5, # Signs 'sign_priority': { diff --git a/python3/vimspector/terminal.py b/python3/vimspector/terminal.py index 6ffd56a..0c84704 100644 --- a/python3/vimspector/terminal.py +++ b/python3/vimspector/terminal.py @@ -23,12 +23,53 @@ def LaunchTerminal( api_prefix, env = params.get( 'env' ) or {} term_options = { - 'vertical': 1, 'norestore': 1, 'cwd': cwd, 'env': env, } + if settings.Get( 'ui_mode' ) == 'horizontal': + # force-horizontal + term_options[ 'vertical' ] = 1 + elif utils.GetVimValue( vim.vars[ 'vimspector_session_windows' ], + 'mode' ) == 'horizontal': + # horizontal, which means that we should have enough space for: + # - sidebar + # - code min + # - term min width + # - + 2 vertical spaders + # - + 3 columns for signs + term_options[ 'vertical' ] = 1 + + # if we don't have enough space for terminal_maxwidth, then see if we have + # enough vertically for terminal_maxheight, in which case, + # that seems a better fit + term_horiz_max = ( settings.Int( 'sidebar_width' ) + + 1 + 2 + 3 + + settings.Int( 'code_minwidth' ) + + 1 + settings.Int( 'terminal_maxwidth' ) ) + term_vert_max = ( settings.Int( 'bottombar_height' ) + 1 + + settings.Int( 'code_minheight' ) + 1 + + settings.Int( 'terminal_minheight' ) ) + + if ( vim.options[ 'columns' ] < term_horiz_max and + vim.options[ 'lines' ] >= term_vert_max ): + # Looks like it, let's try that layout + term_options[ 'vertical' ] = 0 + + + else: + # vertical - we need enough space horizontally for the code+terminal, but we + # may fit better with code above terminal + term_options[ 'vertical' ] = 0 + + term_horiz_max = ( settings.Int( 'code_minwidth' ) + 3 + + settings.Int( 'terminal_maxwidth' ) + 1 ) + + if vim.options[ 'columns' ] > term_horiz_max: + term_options[ 'vertical' ] = 1 + + 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 @@ -50,13 +91,23 @@ def LaunchTerminal( api_prefix, # 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 ): + if term_options.get( 'curwin', 0 ): + pass + elif term_options[ 'vertical' ]: term_options[ 'term_cols' ] = max( min ( int( vim.eval( 'winwidth( 0 )' ) ) - settings.Int( 'code_minwidth' ), settings.Int( 'terminal_maxwidth' ) ), settings.Int( 'terminal_minwidth' ) ) + else: + term_options[ 'term_rows' ] = max( + min ( int( vim.eval( 'winheight( 0 )' ) ) + - settings.Int( 'code_minheight' ), + settings.Int( 'terminal_maxheight' ) ), + settings.Int( 'terminal_minheight' ) + ) + buffer_number = int( utils.Call( diff --git a/tests/lib/autoload/vimspector/test/setup.vim b/tests/lib/autoload/vimspector/test/setup.vim index b0296e0..6ab220c 100644 --- a/tests/lib/autoload/vimspector/test/setup.vim +++ b/tests/lib/autoload/vimspector/test/setup.vim @@ -50,3 +50,59 @@ function! vimspector#test#setup#Reset() abort call popup_clear() endfunction +let s:g_stack = {} + +function! vimspector#test#setup#PushGlobal( name, value ) abort + if !has_key( s:g_stack, a:name ) + let s:g_stack[ a:name ] = [] + endif + + let old_value = get( g:, a:name, v:null ) + call add( s:g_stack[ a:name ], old_value ) + let g:[ a:name ] = a:value + + return old_value +endfunction + +function! vimspector#test#setup#PopGlobal( name ) abort + if !has_key( s:g_stack, a:name ) || len( s:g_stack[ a:name ] ) == 0 + return v:null + endif + + let old_value = s:g_stack[ a:name ][ -1 ] + call remove( s:g_stack[ a:name ], -1 ) + + if old_value is v:null + silent! call remove( g:, a:name ) + else + let g:[ a:name ] = old_value + endif + + return old_value +endfunction + +let s:o_stack = {} + +function! vimspector#test#setup#PushOption( name, value ) abort + if !has_key( s:o_stack, a:name ) + let s:o_stack[ a:name ] = [] + endif + + let old_value = v:null + execute 'let old_value = &' . a:name + call add( s:o_stack[ a:name ], old_value ) + execute 'set ' . a:name . '=' . a:value + return old_value +endfunction + +function! vimspector#test#setup#PopOption( name ) abort + if !has_key( s:o_stack, a:name ) || len( s:o_stack[ a:name ] ) == 0 + return v:null + endif + + let old_value = s:o_stack[ a:name ][ -1 ] + call remove( s:o_stack[ a:name ], -1 ) + + execute 'set ' . a:name . '=' . old_value + return old_value +endfunction diff --git a/tests/ui.test.vim b/tests/ui.test.vim index f251539..1f7789e 100644 --- a/tests/ui.test.vim +++ b/tests/ui.test.vim @@ -1,6 +1,7 @@ let s:fn='../support/test/python/simple_python/main.py' function! SetUp() + let g:vimspector_ui_mode = get( s:, 'vimspector_ui_mode', 'horizontal' ) call vimspector#test#setup#SetUpWithMappings( 'HUMAN' ) endfunction @@ -16,12 +17,17 @@ function! s:StartDebugging() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 23, 1 ) endfunction +function! SetUp_Test_StandardLayout() + call vimspector#test#setup#PushOption( 'columns', 200 ) +endfunction + function! Test_StandardLayout() call s:StartDebugging() call vimspector#StepOver() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 ) + call assert_equal( 'horizontal', g:vimspector_session_windows.mode ) call assert_equal( \ [ 'row', [ \ [ 'col', [ @@ -43,6 +49,247 @@ function! Test_StandardLayout() %bwipe! endfunction +function! TearDown_Test_StandardLayout() + call vimspector#test#setup#PopOption( 'columns' ) +endfunction + +function! SetUp_Test_NarrowLayout() + call vimspector#test#setup#PushOption( 'columns', 100 ) + let s:vimspector_ui_mode = 'vertical' +endfunction + +function! Test_NarrowLayout() + call s:StartDebugging() + + call vimspector#StepOver() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 ) + + call assert_equal( 'vertical', g:vimspector_session_windows.mode ) + call assert_equal( + \ [ 'col', [ + \ [ 'row', [ + \ [ 'leaf', g:vimspector_session_windows.variables ], + \ [ 'leaf', g:vimspector_session_windows.watches ], + \ [ 'leaf', g:vimspector_session_windows.stack_trace ], + \ ] ], + \ [ 'leaf', g:vimspector_session_windows.code ], + \ [ 'leaf', g:vimspector_session_windows.terminal ], + \ [ 'leaf', g:vimspector_session_windows.output ], + \ ] ], + \ winlayout( g:vimspector_session_windows.tabpage ) ) + + call vimspector#test#setup#Reset() + %bwipe! +endfunction + +function! TearDown_Test_NarrowLayout() + unlet s:vimspector_ui_mode + call vimspector#test#setup#PopOption( 'columns' ) +endfunction + +function! SetUp_Test_AutoLayoutTerminalVert() + let s:vimspector_ui_mode = 'auto' + call vimspector#test#setup#PushOption( 'columns', 250 ) + call vimspector#test#setup#PushOption( 'lines', 30 ) +endfunction + +function! Test_AutoLayoutTerminalVert() + call s:StartDebugging() + + call vimspector#StepOver() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 ) + + call assert_equal( 'horizontal', g:vimspector_session_windows.mode ) + call assert_equal( + \ [ 'row', [ + \ [ 'col', [ + \ [ 'leaf', g:vimspector_session_windows.variables ], + \ [ 'leaf', g:vimspector_session_windows.watches ], + \ [ 'leaf', g:vimspector_session_windows.stack_trace ], + \ ] ], + \ [ 'col', [ + \ [ 'row', [ + \ [ 'leaf', g:vimspector_session_windows.code ], + \ [ 'leaf', g:vimspector_session_windows.terminal ], + \ ] ], + \ [ 'leaf', g:vimspector_session_windows.output ], + \ ] ] + \ ] ], + \ winlayout( g:vimspector_session_windows.tabpage ) ) + + call vimspector#test#setup#Reset() + %bwipe! +endfunction + +function! TearDown_Test_AutoLayoutTerminalVert() + unlet s:vimspector_ui_mode + call vimspector#test#setup#PopOption( 'lines' ) + call vimspector#test#setup#PopOption( 'columns' ) +endfunction + +function! SetUp_Test_AutoLayoutTerminalHorizVert() + let s:vimspector_ui_mode = 'auto' + " Wide enough to be horizontal layout, but not wide enough to fully fit the + " terminal, with enough rows to fit the max terminal below + call vimspector#test#setup#PushOption( 'columns', + \ 50 + 82 + 3 + 2 + 12 ) + call vimspector#test#setup#PushOption( 'lines', 50 ) +endfunction + +function! Test_AutoLayoutTerminalHorizVert() + call s:StartDebugging() + + call vimspector#StepOver() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 ) + + call assert_equal( 'horizontal', g:vimspector_session_windows.mode ) + call assert_equal( + \ [ 'row', [ + \ [ 'col', [ + \ [ 'leaf', g:vimspector_session_windows.variables ], + \ [ 'leaf', g:vimspector_session_windows.watches ], + \ [ 'leaf', g:vimspector_session_windows.stack_trace ], + \ ] ], + \ [ 'col', [ + \ [ 'leaf', g:vimspector_session_windows.code ], + \ [ 'leaf', g:vimspector_session_windows.terminal ], + \ [ 'leaf', g:vimspector_session_windows.output ], + \ ] ] + \ ] ], + \ winlayout( g:vimspector_session_windows.tabpage ) ) + + call vimspector#test#setup#Reset() + %bwipe! +endfunction + +function! TearDown_Test_AutoLayoutTerminalHorizVert() + unlet s:vimspector_ui_mode + call vimspector#test#setup#PopOption( 'lines' ) + call vimspector#test#setup#PopOption( 'columns' ) +endfunction + +function! SetUp_Test_AutoLayoutTerminalHorizVertButNotEnoughLines() + let s:vimspector_ui_mode = 'auto' + " Wide enough to be horizontal layout, but not wide enough to fully fit the + " terminal, with enough rows to fit the max terminal below, but there are not + " enough lines to do this + call vimspector#test#setup#PushOption( 'columns', + \ 50 + 82 + 3 + 2 + 12 ) + call vimspector#test#setup#PushOption( 'lines', 20 ) +endfunction + +function! Test_AutoLayoutTerminalHorizVertButNotEnoughLines() + call s:StartDebugging() + + call vimspector#StepOver() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 ) + + call assert_equal( 'horizontal', g:vimspector_session_windows.mode ) + call assert_equal( + \ [ 'row', [ + \ [ 'col', [ + \ [ 'leaf', g:vimspector_session_windows.variables ], + \ [ 'leaf', g:vimspector_session_windows.watches ], + \ [ 'leaf', g:vimspector_session_windows.stack_trace ], + \ ] ], + \ [ 'col', [ + \ [ 'row', [ + \ [ 'leaf', g:vimspector_session_windows.code ], + \ [ 'leaf', g:vimspector_session_windows.terminal ], + \ ] ], + \ [ 'leaf', g:vimspector_session_windows.output ], + \ ] ], + \ ] ], + \ winlayout( g:vimspector_session_windows.tabpage ) ) + + call vimspector#test#setup#Reset() + %bwipe! +endfunction + +function! TearDown_Test_AutoLayoutTerminalHorizVertButNotEnoughLines() + unlet s:vimspector_ui_mode + call vimspector#test#setup#PopOption( 'lines' ) + call vimspector#test#setup#PopOption( 'columns' ) +endfunction + +function! SetUp_Test_AutoLayoutTerminalHoriz() + let s:vimspector_ui_mode = 'vertical' + " Vertical layout, but we split the terminal horizonally + call vimspector#test#setup#PushOption( 'columns', 200 ) + call vimspector#test#setup#PushOption( 'lines', 50 ) +endfunction + +function! Test_AutoLayoutTerminalHoriz() + call s:StartDebugging() + + call vimspector#StepOver() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 ) + + call assert_equal( 'vertical', g:vimspector_session_windows.mode ) + call assert_equal( + \ [ 'col', [ + \ [ 'row', [ + \ [ 'leaf', g:vimspector_session_windows.variables ], + \ [ 'leaf', g:vimspector_session_windows.watches ], + \ [ 'leaf', g:vimspector_session_windows.stack_trace ], + \ ] ], + \ [ 'row', [ + \ [ 'leaf', g:vimspector_session_windows.code ], + \ [ 'leaf', g:vimspector_session_windows.terminal ], + \ ] ], + \ [ 'leaf', g:vimspector_session_windows.output ], + \ ] ], + \ winlayout( g:vimspector_session_windows.tabpage ) ) + + call vimspector#test#setup#Reset() + %bwipe! +endfunction + +function! TearDown_Test_AutoLayoutTerminalHoriz() + unlet s:vimspector_ui_mode + call vimspector#test#setup#PopOption( 'lines' ) + call vimspector#test#setup#PopOption( 'columns' ) +endfunction + +function! SetUp_Test_AutoLayoutTerminalVertVert() + let s:vimspector_ui_mode = 'auto' + " Not wide enough to go horizontal, but wide enough to put the terminal and + " code vertically split + call vimspector#test#setup#PushOption( 'columns', 80 ) + call vimspector#test#setup#PushOption( 'lines', 30 ) +endfunction + +function! Test_AutoLayoutTerminalVertVert() + call s:StartDebugging() + + call vimspector#StepOver() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, 25, 1 ) + + call assert_equal( 'vertical', g:vimspector_session_windows.mode ) + call assert_equal( + \ [ 'col', [ + \ [ 'row', [ + \ [ 'leaf', g:vimspector_session_windows.variables ], + \ [ 'leaf', g:vimspector_session_windows.watches ], + \ [ 'leaf', g:vimspector_session_windows.stack_trace ], + \ ] ], + \ [ 'leaf', g:vimspector_session_windows.code ], + \ [ 'leaf', g:vimspector_session_windows.terminal ], + \ [ 'leaf', g:vimspector_session_windows.output ], + \ ] ], + \ winlayout( g:vimspector_session_windows.tabpage ) ) + + call vimspector#test#setup#Reset() + %bwipe! +endfunction + +function! TearDown_Test_AutoLayoutTerminalVertVert() + unlet s:vimspector_ui_mode + call vimspector#test#setup#PopOption( 'lines' ) + call vimspector#test#setup#PopOption( 'columns' ) +endfunction + + function! Test_CloseVariables() call s:StartDebugging() From 01ea50cb7062b8a27b8df029f5d1dd13c37b9784 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 11 Mar 2021 21:13:58 +0000 Subject: [PATCH 11/73] use --clean for minimal vimrc --- .github/ISSUE_TEMPLATE/bug_report.md | 4 ++-- CONTRIBUTING.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 1788c04..f01a833 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -17,12 +17,12 @@ assignees: '' > Please answer the following questions -* Does your issue reproduce using `vim -Nu /path/to/vimspector/support/minimal_vimrc` ? \[Yes/No] +* Does your issue reproduce using `vim --clean -Nu /path/to/vimspector/support/minimal_vimrc` ? \[Yes/No] * If you are using Neovim, does your issue reproduce using Vim? \[Yes/No] > List of steps to reproduce: -> 1. Run `vim -Nu /path/to/vimspector/support/minimal_vimrc` +> 1. Run `vim ---clean Nu /path/to/vimspector/support/minimal_vimrc` > 2. Open _this project_... > 3. Press _this sequence of keys_ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 578fd8f..1866974 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -83,7 +83,7 @@ in the issue report. The minimal vimrc is in `support/test/minimal_vimrc` and can be used as follows: ``` -vim -Nu /path/to/vimspector/support/minimal_vimrc +vim --clean -Nu /path/to/vimspector/support/minimal_vimrc ``` ## Pull Requests From 2615cff97ad871de6ced52be93e72c310838543e Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 11 Mar 2021 21:14:30 +0000 Subject: [PATCH 12/73] If there isn't enough vertical space, we get vim errors (not enough room), so don't do that --- python3/vimspector/debug_session.py | 14 +++++++++++--- tests/ui.test.vim | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 4a89cdf..16f69be 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -657,8 +657,6 @@ class DebugSession( object ): mode = settings.Get( 'ui_mode' ) - self._logger.debug( 'ui_mode = %s', mode ) - if mode == 'auto': # Go vertical if there isn't enough horizontal space for at least: # the left bar width @@ -670,13 +668,23 @@ class DebugSession( object ): + settings.Int( 'code_minwidth' ) + 1 + settings.Int( 'terminal_minwidth' ) ) + min_height = ( settings.Int( 'code_minheight' ) + 1 + + settings.Int( 'topbar_height' ) + 1 + + settings.Int( 'bottombar_height' ) + 1 + + 2 ) + mode = ( 'vertical' if vim.options[ 'columns' ] < min_width else 'horizontal' ) - self._logger.debug( 'min_width: %s, actual: %s - result: %s', + if vim.options[ 'lines' ] < min_height: + mode = 'horizontal' + + self._logger.debug( 'min_width/height: %s/%s, actual: %s/%s - result: %s', min_width, + min_height, vim.options[ 'columns' ], + vim.options[ 'lines' ], mode ) if mode == 'vertical': diff --git a/tests/ui.test.vim b/tests/ui.test.vim index 1f7789e..5ba2f9c 100644 --- a/tests/ui.test.vim +++ b/tests/ui.test.vim @@ -256,7 +256,7 @@ function! SetUp_Test_AutoLayoutTerminalVertVert() " Not wide enough to go horizontal, but wide enough to put the terminal and " code vertically split call vimspector#test#setup#PushOption( 'columns', 80 ) - call vimspector#test#setup#PushOption( 'lines', 30 ) + call vimspector#test#setup#PushOption( 'lines', 50 ) endfunction function! Test_AutoLayoutTerminalVertVert() From 6d3f3e207b84432d7dd0af7c08263c5140bd3dd1 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 10 Mar 2021 11:12:28 +0000 Subject: [PATCH 13/73] Fix default variable values having substitutions from the calculus --- python3/vimspector/utils.py | 8 +++++--- tests/python/Test_ExpandReferencesInDict.py | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index e7cb537..d8dd345 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -494,7 +494,6 @@ def _Substitute( template, mapping ): if mo.group( 'braceddefault' ) is not None: named = mo.group( 'defname' ) if named not in mapping: - '' raise MissingSubstitution( named, mo.group( 'default' ).replace( '\\}', '}' ) ) @@ -536,8 +535,11 @@ def ExpandReferencesInString( orig_s, if default_value is None and e.default_value is not None: try: default_value = _Substitute( e.default_value, mapping ) - except MissingSubstitution: - default_value = e.default_value + except MissingSubstitution as e2: + if e2.name in calculus: + default_value = calculus[ e2.name ]() + else: + default_value = e.default_value mapping[ key ] = AskForInput( 'Enter value for {}: '.format( key ), default_value ) diff --git a/tests/python/Test_ExpandReferencesInDict.py b/tests/python/Test_ExpandReferencesInDict.py index 4998350..15fb11b 100644 --- a/tests/python/Test_ExpandReferencesInDict.py +++ b/tests/python/Test_ExpandReferencesInDict.py @@ -35,6 +35,7 @@ class TestExpandReferencesInDict( unittest.TestCase ): 'one': '${one}', 'two': '${one} and ${two}', 'three': '${three}', + 'three_with_default': '${three_with_default:${three\\}}', # uses calculus 'four': '${four}', 'five': '${five}', 'list': [ '*${words}' ], @@ -58,6 +59,7 @@ class TestExpandReferencesInDict( unittest.TestCase ): 'one': 'one', 'two': 'one and TWO', 'three': '3', + 'three_with_default': '3', 'four': 'typed text', 'five': '5ive!', 'list': [ 'these', 'are', 'some', 'words' ], From a53d68f04301833b30a9a8e3acf02ba793c49d82 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 10 Mar 2021 12:29:40 +0000 Subject: [PATCH 14/73] Add up and down frame mappings --- autoload/vimspector.vim | 14 ++++ plugin/vimspector.vim | 5 ++ python3/vimspector/debug_session.py | 8 ++ python3/vimspector/stack_trace.py | 40 ++++++++++ tests/stack_trace.test.vim | 114 ++++++++++++++++++++++++++++ 5 files changed, 181 insertions(+) diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index e94a177..a547e5c 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -234,6 +234,20 @@ function! vimspector#GoToFrame() abort py3 _vimspector_session.ExpandFrameOrThread() endfunction +function! vimspector#UpFrame() abort + if !s:Enabled() + return + endif + py3 _vimspector_session.UpFrame() +endfunction + +function! vimspector#DownFrame() abort + if !s:Enabled() + return + endif + py3 _vimspector_session.DownFrame() +endfunction + function! vimspector#AddWatch( ... ) abort if !s:Enabled() return diff --git a/plugin/vimspector.vim b/plugin/vimspector.vim index 53855ef..37509a7 100644 --- a/plugin/vimspector.vim +++ b/plugin/vimspector.vim @@ -67,6 +67,11 @@ nnoremap VimspectorBalloonEval xnoremap VimspectorBalloonEval \ :call vimspector#ShowEvalBalloon( 1 ) +nnoremap VimspectorUpFrame + \ :call vimspector#UpFrame() +nnoremap VimspectorDownFrame + \ :call vimspector#DownFrame() + if s:mappings ==# 'VISUAL_STUDIO' nmap VimspectorContinue nmap VimspectorStop diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 16f69be..4d8c816 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -571,6 +571,14 @@ class DebugSession( object ): def ExpandFrameOrThread( self ): self._stackTraceView.ExpandFrameOrThread() + @IfConnected() + def UpFrame( self ): + self._stackTraceView.UpFrame() + + @IfConnected() + def DownFrame( self ): + self._stackTraceView.DownFrame() + def ToggleLog( self ): if self._HasUI(): return self.ShowOutput( 'Vimspector' ) diff --git a/python3/vimspector/stack_trace.py b/python3/vimspector/stack_trace.py index c32cead..ae14e68 100644 --- a/python3/vimspector/stack_trace.py +++ b/python3/vimspector/stack_trace.py @@ -367,6 +367,46 @@ class StackTraceView( object ): self._JumpToFrame( frame ) + + def _GetFrameOffset( self, delta ): + thread: Thread + for thread in self._threads: + if thread.id != self._current_thread: + continue + + if not thread.stacktrace: + return + + frame_idx = None + for index, frame in enumerate( thread.stacktrace ): + if frame == self._current_frame: + frame_idx = index + break + + if frame_idx is not None: + target_idx = frame_idx + delta + if target_idx >= 0 and target_idx < len( thread.stacktrace ): + return thread.stacktrace[ target_idx ] + + break + + + def UpFrame( self ): + frame = self._GetFrameOffset( 1 ) + if not frame: + utils.UserMessage( 'Top of stack' ) + else: + self._JumpToFrame( frame, 'up' ) + + + def DownFrame( self ): + frame = self._GetFrameOffset( -1 ) + if not frame: + utils.UserMessage( 'Bottom of stack' ) + else: + self._JumpToFrame( frame, 'down' ) + + def AnyThreadsRunning( self ): for thread in self._threads: if thread.state != Thread.TERMINATED: diff --git a/tests/stack_trace.test.vim b/tests/stack_trace.test.vim index 569376c..a65ea5e 100644 --- a/tests/stack_trace.test.vim +++ b/tests/stack_trace.test.vim @@ -356,3 +356,117 @@ function! Test_Multiple_Threads_Step() call vimspector#test#setup#Reset() %bwipe! endfunction + +function! Test_UpDownStack() + let fn='../support/test/python/simple_python/main.py' + exe 'edit ' . fn + call setpos( '.', [ 0, 6, 1 ] ) + + call vimspector#SetLineBreakpoint( fn, 15 ) + call vimspector#LaunchWithSettings( { 'configuration': 'run' } ) + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 ) + call WaitForAssert( {-> + \ AssertMatchist( + \ [ + \ '- Thread 1: MainThread (paused)', + \ ' 2: DoSomething@main.py:15', + \ ' 3: __init__@main.py:8', + \ ' 4: Main@main.py:23', + \ ' 5: @main.py:29', + \ ], + \ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ), + \ 1, + \ '$' ) + \ ) + \ } ) + + call vimspector#DownFrame() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 ) + call WaitForAssert( {-> + \ AssertMatchist( + \ [ + \ '- Thread 1: MainThread (paused)', + \ ' 2: DoSomething@main.py:15', + \ ' 3: __init__@main.py:8', + \ ' 4: Main@main.py:23', + \ ' 5: @main.py:29', + \ ], + \ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ), + \ 1, + \ '$' ) + \ ) + \ } ) + + call vimspector#UpFrame() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 ) + call WaitForAssert( {-> + \ AssertMatchist( + \ [ + \ '- Thread 1: MainThread (paused)', + \ ' 2: DoSomething@main.py:15', + \ ' 3: __init__@main.py:8', + \ ' 4: Main@main.py:23', + \ ' 5: @main.py:29', + \ ], + \ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ), + \ 1, + \ '$' ) + \ ) + \ } ) + + call feedkeys( "\VimspectorUpFrame", 'x' ) + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 23, 1 ) + call WaitForAssert( {-> + \ AssertMatchist( + \ [ + \ '- Thread 1: MainThread (paused)', + \ ' 2: DoSomething@main.py:15', + \ ' 3: __init__@main.py:8', + \ ' 4: Main@main.py:23', + \ ' 5: @main.py:29', + \ ], + \ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ), + \ 1, + \ '$' ) + \ ) + \ } ) + + call feedkeys( "\VimspectorDownFrame", 'x' ) + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 ) + call WaitForAssert( {-> + \ AssertMatchist( + \ [ + \ '- Thread 1: MainThread (paused)', + \ ' 2: DoSomething@main.py:15', + \ ' 3: __init__@main.py:8', + \ ' 4: Main@main.py:23', + \ ' 5: @main.py:29', + \ ], + \ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ), + \ 1, + \ '$' ) + \ ) + \ } ) + + call vimspector#DownFrame() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 ) + call WaitForAssert( {-> + \ AssertMatchist( + \ [ + \ '- Thread 1: MainThread (paused)', + \ ' 2: DoSomething@main.py:15', + \ ' 3: __init__@main.py:8', + \ ' 4: Main@main.py:23', + \ ' 5: @main.py:29', + \ ], + \ GetBufLine( winbufnr( g:vimspector_session_windows.stack_trace ), + \ 1, + \ '$' ) + \ ) + \ } ) + + + call vimspector#ClearBreakpoints() + call vimspector#test#setup#Reset() + %bwipe! +endfunction From 6b67d165b92d1fe858ebd427507836021e0f0623 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 12 Mar 2021 21:50:37 +0000 Subject: [PATCH 15/73] Update docs for new mappings --- README.md | 84 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 42d4765..2152a9c 100644 --- a/README.md +++ b/README.md @@ -656,18 +656,23 @@ personal and so you should work out what you like and use vim's powerful mapping features to set your own mappings. To that end, Vimspector defines the following `` mappings: -* `VimspectorContinue` -* `VimspectorStop` -* `VimspectorRestart` -* `VimspectorPause` -* `VimspectorToggleBreakpoint` -* `VimspectorToggleConditionalBreakpoint` -* `VimspectorAddFunctionBreakpoint` -* `VimspectorStepOver` -* `VimspectorStepInto` -* `VimspectorStepOut` -* `VimspectorRunToCursor` -* `VimspectorBalloonEval` +| Mapping | Function | API | +| --- | --- | --- | +| `VimspectorContinue` | When debugging, continue. Otherwise start debugging. | `vimspector#Continue()` | +| `VimspectorStop` | Stop debugging. | `vimspector#Stop()` | +| `VimpectorRestart` | Restart debugging with the same configuration. | `vimspector#Restart()` | +| `VimspectorPause` | Pause debuggee. | `vimspector#Pause()` | +| `VimspectorToggleBreakpoint` | Toggle line breakpoint on the current line. | `vimspector#ToggleBreakpoint()` | +| `VimspectorToggleConditionalBreakpoint` | Toggle conditional line breakpoint on the current line. | `vimspector#ToggleBreakpoint( { trigger expr, hit count expr } )` | +| `VimspectorAddFunctionBreakpoint` | Add a function breakpoint for the expression under cursor | `vimspector#AddFunctionBreakpoint( '' )` | +| `VimspectorRunToCursor` | Run to Cursor | `vimspector#RunToCursor()` | +| `VimspectorStepOver` | Step Over | `vimspector#StepOver()` | +| `VimspectorStepInto` | Step Into | `vimspector#StepInto()` | +| `VimspectorStepOut` | Step out of current function scope | `vimspector#StepOut()` | +| `VimspectorUpFrame` | Move up a frame in the current call stack | `vimspector#UpFrame()` | +| `VimspectorDownFrame` | Move down a frame in the current call stack | `vimspector#DownFrame()` | +| `VimspectorBalloonEval` | Evaluate expression under cursor (or visual) in popup | *internal* | + These map roughly 1-1 with the API functions below. @@ -695,17 +700,17 @@ loading vimspector**: let g:vimspector_enable_mappings = 'VISUAL_STUDIO' ``` -| Key | Function | API | -| --- | --- | --- | -| `F5` | When debugging, continue. Otherwise start debugging. | `vimspector#Continue()` | -| `Shift F5` | Stop debugging. | `vimspector#Stop()` | -| `Ctrl Shift F5` | Restart debugging with the same configuration. | `vimspector#Restart()` | -| `F6` | Pause debuggee. | `vimspector#Pause()` | -| `F9` | Toggle line breakpoint on the current line. | `vimspector#ToggleBreakpoint()` | -| `Shift F9` | Add a function breakpoint for the expression under cursor | `vimspector#AddFunctionBreakpoint( '' )` | -| `F10` | Step Over | `vimspector#StepOver()` | -| `F11` | Step Into | `vimspector#StepInto()` | -| `Shift F11` | Step out of current function scope | `vimspector#StepOut()` | +| Key | Mapping | Function +| --- | --- | --- +| `F5` | `VimspectorContinue` | When debugging, continue. Otherwise start debugging. +| `Shift F5` | `VimspectorStop` | Stop debugging. +| `Ctrl Shift F5` | `VimspectorRestart` | Restart debugging with the same configuration. +| `F6` | `VimspectorPause` | Pause debuggee. +| `F9` | `VimspectorToggleBreakpoint` | Toggle line breakpoint on the current line. +| `Shift F9` | `VimspectorAddFunctionBreakpoint` | Add a function breakpoint for the expression under cursor +| `F10` | `VimspectorStepOver` | Step Over +| `F11` | `VimspectorStepInto` | Step Into +| `Shift F11` | `VimspectorStepOut` | Step out of current function scope ## Human Mode @@ -720,19 +725,19 @@ loading vimspector**: let g:vimspector_enable_mappings = 'HUMAN' ``` -| Key | Function | API | -| --- | --- | --- | -| `F5` | When debugging, continue. Otherwise start debugging. | `vimspector#Continue()` | -| `F3` | Stop debugging. | `vimspector#Stop()` | -| `F4` | Restart debugging with the same configuration. | `vimspector#Restart()` | -| `F6` | Pause debuggee. | `vimspector#Pause()` | -| `F9` | Toggle line breakpoint on the current line. | `vimspector#ToggleBreakpoint()` | -| `F9` | Toggle conditional line breakpoint on the current line. | `vimspector#ToggleBreakpoint( { trigger expr, hit count expr } )` | -| `F8` | Add a function breakpoint for the expression under cursor | `vimspector#AddFunctionBreakpoint( '' )` | -| `F8` | Run to Cursor | `vimspector#RunToCursor()` | -| `F10` | Step Over | `vimspector#StepOver()` | -| `F11` | Step Into | `vimspector#StepInto()` | -| `F12` | Step out of current function scope | `vimspector#StepOut()` | +| Key | Mapping | Function +| --- | --- | --- +| `F5` | `VimspectorContinue` | When debugging, continue. Otherwise start debugging. +| `F3` | `VimspectorStop` | Stop debugging. +| `F4` | `VimspectorRestart` | Restart debugging with the same configuration. +| `F6` | `VimspectorPause` | Pause debuggee. +| `F9` | `VimspectorToggleBreakpoint` | Toggle line breakpoint on the current line. +| `F9` | `VimspectorToggleConditionalBreakpoint` | Toggle conditional line breakpoint on the current line. +| `F8` | `VimspectorAddFunctionBreakpoint` | Add a function breakpoint for the expression under cursor +| `F8` | `VimspectorRunToCursor` | Run to Cursor +| `F10` | `VimspectorStepOver` | Step Over +| `F11` | `VimspectorStepInto` | Step Into +| `F12` | `VimspectorStepOut` | Step out of current function scope In addition, I recommend adding a mapping to `VimspectorBalloonEval`, in normal and visual modes, for example: @@ -746,6 +751,13 @@ nmap di VimspectorBalloonEval xmap di VimspectorBalloonEval ``` +You may also wish to add mappings for up/down the stack, for example: + +```viml +nmap VimspectorUpFrame +nmap VimspectorDownFrame +``` + # Usage and API This section defines detailed usage instructions, organised by feature. For most From 6f88b400e1f0771d9f684ae8a2c495989f196e02 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 18 Mar 2021 13:51:32 +0000 Subject: [PATCH 16/73] Only disable mappings in the keyboard-version of the popup --- autoload/vimspector/internal/balloon.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/vimspector/internal/balloon.vim b/autoload/vimspector/internal/balloon.vim index 32d17ab..f7ed9d7 100644 --- a/autoload/vimspector/internal/balloon.vim +++ b/autoload/vimspector/internal/balloon.vim @@ -69,7 +69,6 @@ function! vimspector#internal#balloon#CreateTooltip( is_hover, ... ) abort \ 'resize': 1, \ 'close': 'button', \ 'callback': 'vimspector#internal#balloon#CloseCallback', - \ 'mapping': 0 \ } " When ambiwidth is single, use prettier characters for the border. This @@ -86,6 +85,7 @@ function! vimspector#internal#balloon#CreateTooltip( is_hover, ... ) abort let config[ 'filter' ] = 'vimspector#internal#balloon#CursorFilter' let config[ 'moved' ] = 'any' let config[ 'cursorline' ] = 1 + let config[ 'mapping' ] = 0 let s:popup_win_id = popup_atcursor( body, config ) endif From b92a89f0d49611e9476d8825c7d65c700505a387 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 26 Feb 2021 19:21:40 +0000 Subject: [PATCH 17/73] Add a way to have adapter specific message handlers --- python3/vimspector/custom/java.py | 34 +++++++++++++++++++ .../vimspector/debug_adapter_connection.py | 32 ++++++++--------- python3/vimspector/debug_session.py | 16 ++++++++- python3/vimspector/gadgets.py | 3 +- support/test/java/test_project/pom.xml | 4 +-- 5 files changed, 67 insertions(+), 22 deletions(-) create mode 100644 python3/vimspector/custom/java.py diff --git a/python3/vimspector/custom/java.py b/python3/vimspector/custom/java.py new file mode 100644 index 0000000..ebfec35 --- /dev/null +++ b/python3/vimspector/custom/java.py @@ -0,0 +1,34 @@ +# vimspector - A multi-language debugging system for Vim +# Copyright 2021 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. + +from vimspector.debug_session import DebugSession +from vimspector import utils + + +class JavaDebugAdapter( object ): + def __init__( self, debug_session: DebugSession ): + self.debug_session = debug_session + + def OnEvent_hotcodereplace( self, message ): + # Hack for java debug server hot-code-replace + if utils.Call( 'confirm', + 'Code has changed, hot reload?', + '&Yes,&No', + 1, + 'Question' ) == 1: + self.debug_session._connection.DoRequest( None, { + 'command': 'redefineClasses', + 'arguments': {}, + } ) diff --git a/python3/vimspector/debug_adapter_connection.py b/python3/vimspector/debug_adapter_connection.py index 283c40c..df2ef13 100644 --- a/python3/vimspector/debug_adapter_connection.py +++ b/python3/vimspector/debug_adapter_connection.py @@ -29,14 +29,14 @@ class PendingRequest( object ): class DebugAdapterConnection( object ): - def __init__( self, handler, send_func ): + def __init__( self, handlers, send_func ): self._logger = logging.getLogger( __name__ ) utils.SetUpLogging( self._logger ) self._Write = send_func self._SetState( 'READ_HEADER' ) self._buffer = bytes() - self._handler = handler + self._handlers = handlers self._next_message_id = 0 self._outstanding_requests = {} @@ -124,7 +124,7 @@ class DebugAdapterConnection( object ): def Reset( self ): self._Write = None - self._handler = None + self._handlers = None while self._outstanding_requests: _, request = self._outstanding_requests.popitem() @@ -237,7 +237,7 @@ class DebugAdapterConnection( object ): def _OnMessageReceived( self, message ): - if not self._handler: + if not self._handlers: return if message[ 'type' ] == 'response': @@ -270,25 +270,21 @@ class DebugAdapterConnection( object ): self._logger.error( 'Request failed: {0}'.format( reason ) ) if request.failure_handler: request.failure_handler( reason, message ) - elif 'OnFailure' in dir( self._handler ): - self._handler.OnFailure( reason, request.msg, message ) else: - utils.UserMessage( 'Request failed: {0}'.format( reason ) ) + for h in self._handlers: + if 'OnFailure' in dir( h ): + h.OnFailure( reason, request.msg, message ) + elif message[ 'type' ] == 'event': method = 'OnEvent_' + message[ 'event' ] - if method in dir( self._handler ): - getattr( self._handler, method )( message ) - else: - utils.UserMessage( 'Unhandled event: {0}'.format( message[ 'event' ] ), - persist = True ) + for h in self._handlers: + if method in dir( h ): + getattr( h, method )( message ) elif message[ 'type' ] == 'request': method = 'OnRequest_' + message[ 'command' ] - if method in dir( self._handler ): - getattr( self._handler, method )( message ) - else: - utils.UserMessage( - 'Unhandled request: {0}'.format( message[ 'command' ] ), - persist = True ) + for h in self._handlers: + if method in dir( h ): + getattr( h, method )( message ) def _KillTimer( request ): diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 4d8c816..31b4342 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -21,6 +21,7 @@ import shlex import subprocess import functools import vim +import importlib from vimspector import ( breakpoints, code, @@ -888,8 +889,21 @@ class DebugSession( object ): self._splash_screen, "Unable to start adapter" ) else: + if 'custom_handler' in self._adapter: + spec = self._adapter[ 'custom_handler' ] + if isinstance( spec, dict ): + module = spec[ 'module' ] + cls = spec[ 'class' ] + else: + module, cls = spec.rsplit( '.', 1 ) + + CustomHandler = getattr( importlib.import_module( module ), cls ) + handlers = [ CustomHandler( self ), self ] + else: + handlers = [ self ] + self._connection = debug_adapter_connection.DebugAdapterConnection( - self, + handlers, lambda msg: utils.Call( "vimspector#internal#{}#Send".format( self._connection_type ), msg ) ) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index d1b6872..5c61074 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -159,7 +159,8 @@ GADGETS = { "port": "${DAPPort}", "configuration": { "cwd": "${workspaceRoot}" - } + }, + 'custom_handler': 'vimspector.custom.java.JavaDebugAdapter' } }, }, diff --git a/support/test/java/test_project/pom.xml b/support/test/java/test_project/pom.xml index 890e7e8..e6dc4d3 100644 --- a/support/test/java/test_project/pom.xml +++ b/support/test/java/test_project/pom.xml @@ -4,7 +4,7 @@ TestApplication 1 - 8 - 8 + 11 + 11 From afb912dd089a6cfbbadfad2a55531ed00226889a Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 2 Mar 2021 10:48:55 +0000 Subject: [PATCH 18/73] Print hotcodereplace messages --- python3/vimspector/custom/java.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/python3/vimspector/custom/java.py b/python3/vimspector/custom/java.py index ebfec35..0dfa89c 100644 --- a/python3/vimspector/custom/java.py +++ b/python3/vimspector/custom/java.py @@ -23,12 +23,18 @@ class JavaDebugAdapter( object ): def OnEvent_hotcodereplace( self, message ): # Hack for java debug server hot-code-replace - if utils.Call( 'confirm', - 'Code has changed, hot reload?', - '&Yes,&No', - 1, - 'Question' ) == 1: - self.debug_session._connection.DoRequest( None, { - 'command': 'redefineClasses', - 'arguments': {}, - } ) + body = message.get( 'body' ) or {} + + if body.get( 'type' ) != 'hotcodereplace': + 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': {}, + } ) + elif body.get( 'message' ): + utils.UserMessage( 'Hot code replace: ' + body[ 'message' ] ) + From 63fd3165fb48fa0c5c8dd916aa3c3ae54878d304 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 4 Mar 2021 21:44:54 +0000 Subject: [PATCH 19/73] Use popup for confirmations (note these have to be async) --- autoload/vimspector/internal/neopopup.vim | 22 ++++++++ autoload/vimspector/internal/popup.vim | 31 +++++++++++ python3/vimspector/custom/java.py | 17 +++--- python3/vimspector/debug_session.py | 63 ++++++++++++++--------- python3/vimspector/utils.py | 29 ++++++++++- 5 files changed, 129 insertions(+), 33 deletions(-) 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 ): From 85bb8594ab916358a5605c259f89b036a119d6b9 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 5 Mar 2021 21:09:39 +0000 Subject: [PATCH 20/73] Allow forcing selection from the menu with F5 --- autoload/vimspector.vim | 4 ++-- plugin/vimspector.vim | 3 +++ python3/vimspector/debug_session.py | 7 ++++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index a547e5c..a0b6c42 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -41,11 +41,11 @@ function! s:Enabled() abort return s:enabled endfunction -function! vimspector#Launch() abort +function! vimspector#Launch( ... ) abort if !s:Enabled() return endif - py3 _vimspector_session.Start() + py3 _vimspector_session.Start( *vim.eval( 'a:000' ) ) endfunction function! vimspector#LaunchWithSettings( settings ) abort diff --git a/plugin/vimspector.vim b/plugin/vimspector.vim index 37509a7..75e2baa 100644 --- a/plugin/vimspector.vim +++ b/plugin/vimspector.vim @@ -35,6 +35,8 @@ let s:mappings = get( g:, 'vimspector_enable_mappings', '' ) nnoremap VimspectorContinue \ :call vimspector#Continue() +nnoremap VimspectorLaunch + \ :call vimspector#Launch( v:true ) nnoremap VimspectorStop \ :call vimspector#Stop() nnoremap VimspectorRestart @@ -84,6 +86,7 @@ if s:mappings ==# 'VISUAL_STUDIO' nmap VimspectorStepOut elseif s:mappings ==# 'HUMAN' nmap VimspectorContinue + nmap VimspectorLaunch nmap VimspectorStop nmap VimspectorRestart nmap VimspectorPause diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index ae16706..12e4563 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -100,7 +100,7 @@ class DebugSession( object ): return launch_config_file, configurations - def Start( self, launch_variables = None ): + def Start( self, force_choose=False, launch_variables = None ): # We mutate launch_variables, so don't mutate the default argument. # https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments if launch_variables is None: @@ -135,6 +135,11 @@ class DebugSession( object ): if 'configuration' in launch_variables: configuration_name = launch_variables.pop( 'configuration' ) + elif force_choose: + # Always display the menu + configuration_name = utils.SelectFromList( + 'Which launch configuration?', + sorted( configurations.keys() ) ) elif ( len( configurations ) == 1 and next( iter( configurations.values() ) ).get( "autoselect", True ) ): configuration_name = next( iter( configurations.keys() ) ) From 6b74e584d53b284a35c72f7ab5e8f1f2095fe7ea Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sat, 6 Mar 2021 20:24:24 +0000 Subject: [PATCH 21/73] Create a messagebox-like interface in vim --- autoload/vimspector/internal/balloon.vim | 6 +- autoload/vimspector/internal/neopopup.vim | 3 + autoload/vimspector/internal/popup.vim | 88 ++++++++++++++++++++--- python3/vimspector/utils.py | 6 +- 4 files changed, 87 insertions(+), 16 deletions(-) diff --git a/autoload/vimspector/internal/balloon.vim b/autoload/vimspector/internal/balloon.vim index f7ed9d7..b607e51 100644 --- a/autoload/vimspector/internal/balloon.vim +++ b/autoload/vimspector/internal/balloon.vim @@ -71,11 +71,7 @@ function! vimspector#internal#balloon#CreateTooltip( is_hover, ... ) abort \ 'callback': 'vimspector#internal#balloon#CloseCallback', \ } - " When ambiwidth is single, use prettier characters for the border. This - " would look silly when ambiwidth is double. - if &ambiwidth ==# 'single' && &encoding ==? 'utf-8' - let config[ 'borderchars' ] = [ '─', '│', '─', '│', '╭', '╮', '┛', '╰' ] - endif + let config = vimspector#internal#popup#SetBorderChars( config ) if a:is_hover let config[ 'filter' ] = 'vimspector#internal#balloon#MouseFilter' diff --git a/autoload/vimspector/internal/neopopup.vim b/autoload/vimspector/internal/neopopup.vim index cc25020..189c78c 100644 --- a/autoload/vimspector/internal/neopopup.vim +++ b/autoload/vimspector/internal/neopopup.vim @@ -83,6 +83,9 @@ endfunction function! vimspector#internal#neopopup#Confirm( confirm_id, \ text, \ default_value ) abort + + " Neovim doesn't have an equivalent of popup_dialog, and it's way too much + " effort to write one, so we just use confirm(). let result = confirm( a:text, '&Yes &No &Default', 3 ) " Map the results to what popup_menu_filter would return (ok s:ConfirmCallback diff --git a/autoload/vimspector/internal/popup.vim b/autoload/vimspector/internal/popup.vim index e8658ab..5978987 100644 --- a/autoload/vimspector/internal/popup.vim +++ b/autoload/vimspector/internal/popup.vim @@ -32,9 +32,32 @@ function! vimspector#internal#popup#HideSplash( id ) abort call popup_hide( a:id ) endfunction +let s:current_selection = 0 +let s:selections = [] +let s:text = [] + +function! s:UpdatePopup( id ) + let buf = copy( s:text ) + call extend( buf, s:DrawButtons() ) + call popup_settext( a:id, buf ) +endfunction + function! s:YesNoDefaultFilter( default_value, id, key ) abort - if a:key ==# "\" || a:key ==# 'D' || a:key ==# 'd' + if a:key ==# "\" + call popup_close( a:id, s:current_selection + 1 ) + return 1 + elseif a:key ==# 'D' || a:key ==# 'd' call popup_close( a:id, a:default_value ) + return 1 + elseif index( [ "\", "\" ], a:key ) >= 0 + let s:current_selection = ( s:current_selection + 1 ) % len( s:selections ) + call s:UpdatePopup( a:id ) + return 1 + elseif index( [ "\", "\" ], a:key ) >= 0 + let s:current_selection = s:current_selection == 0 + \ ? len( s:selections ) - 1: s:current_selection - 1 + call s:UpdatePopup( a:id ) + return 1 endif return popup_filter_yesno( a:id, a:key ) @@ -46,23 +69,68 @@ function! s:ConfirmCallback( confirm_id, id, result ) abort \ int( vim.eval( 'a:result' ) ) ) endfunction +function! s:SelectionPosition( idx ) abort + return a:idx == 0 ? 0 : len( join( s:selections[ : a:idx - 1 ], ' ' ) ) + 1 +endfunction + +function! s:DrawButtons() abort + return [ { + \ 'text': join( s:selections, ' ' ), + \ 'props': [ + \ { + \ 'col': s:SelectionPosition( s:current_selection ) + 1, + \ 'length': len( s:selections[ s:current_selection ] ), + \ 'type': 'VimspectorSelectedItem' + \ }, + \ ] + \ } ] +endfunction + function! vimspector#internal#popup#Confirm( \ confirm_id, \ text, + \ options, \ default_value ) abort - let text = a:text - if type( a:text ) != v:t_list - let text = [ a:text ] + + silent! call prop_type_add( 'VimspectorSelectedItem', { + \ 'highlight': 'PMenuSel' + \ } ) + + let lines = split( a:text, "\n", v:true ) + let buf = [] + for line in lines + call add( buf, { 'text': line, 'props': [] } ) + endfor + + call add( buf, { 'text': '', 'props': [] } ) + + let s:selections = a:options + let s:current_selection = ( a:default_value - 1 ) + + let s:text = copy( buf ) + call extend( buf, s:DrawButtons() ) + + let config = { + \ 'callback': function( 's:ConfirmCallback', [ a:confirm_id ] ), + \ 'filter': function( 's:YesNoDefaultFilter', [ a:default_value ] ), + \ 'mapping': v:false, + \ } + let config = vimspector#internal#popup#SetBorderChars( config ) + + return popup_dialog( buf, config ) +endfunction + +function! vimspector#internal#popup#SetBorderChars( config ) + " When ambiwidth is single, use prettier characters for the border. This + " would look silly when ambiwidth is double. + if &ambiwidth ==# 'single' && &encoding ==? 'utf-8' + let a:config[ 'borderchars' ] = [ '─', '│', '─', '│', '╭', '╮', '┛', '╰' ] 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 ] ) - \ } ) + return a:config endfunction + " Boilerplate {{{ let &cpoptions=s:save_cpo unlet s:save_cpo diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index c65a184..ca0b80a 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -390,13 +390,17 @@ def ConfirmCallback( confirm_id, result ): handler( result ) -def Confirm( api_prefix, prompt, handler, default_value = 1 ): +def Confirm( api_prefix, prompt, handler, default_value = 3, options = None ): global CONFIRM_ID + if not options: + options = [ '(Y)es', '(N)o', '(D)efault' ] + CONFIRM_ID += 1 CONFIRM[ CONFIRM_ID ] = handler Call( f'vimspector#internal#{ api_prefix }popup#Confirm', CONFIRM_ID, prompt, + options, default_value ) From 154e727b9693144439b37735b9e4f0aa44d58c16 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 11 Mar 2021 22:38:01 +0000 Subject: [PATCH 22/73] Make confirm dialog take arbitrary keys Confirm now takes the list of options, list of keys to select them and the default value. Returned values are always a 1-based index into the list (like SelectFromList) or -1 to mean esc/ctrl-c. This uses a nice popup dialog in vim and a crappy input on neovim. --- autoload/vimspector/internal/neopopup.vim | 41 ++++++++++++++++++----- autoload/vimspector/internal/popup.vim | 22 ++++++++---- python3/vimspector/custom/java.py | 16 ++++++--- python3/vimspector/debug_session.py | 10 ++++-- python3/vimspector/settings.py | 5 ++- python3/vimspector/utils.py | 16 ++++++--- 6 files changed, 82 insertions(+), 28 deletions(-) diff --git a/autoload/vimspector/internal/neopopup.vim b/autoload/vimspector/internal/neopopup.vim index 189c78c..9f35914 100644 --- a/autoload/vimspector/internal/neopopup.vim +++ b/autoload/vimspector/internal/neopopup.vim @@ -82,29 +82,52 @@ endfunction function! vimspector#internal#neopopup#Confirm( confirm_id, \ text, - \ default_value ) abort + \ options, + \ default_value, + \ keys ) abort " Neovim doesn't have an equivalent of popup_dialog, and it's way too much " effort to write one, so we just use confirm(). - let result = confirm( a:text, '&Yes &No &Default', 3 ) + let prompt = a:text + for opt in a:options + let prompt .= ' ' . opt + endfor + let prompt .= ': ' + + " Annoyingly we can't use confirm() here because for some reason it doesn't + " render properly in a channel callback. So we use input() and mimic dialog + " behaviour. + try + let result = input( prompt, a:keys[ a:default_value - 1 ] ) + catch /.*/ + let result = -1 + endtry " 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 + if result == '' " User pressed ESC/ctrl-c let result = -1 - elseif result == 3 - " Default - let result = a:default_value + else + let index = 1 + for k in a:keys + if k ==? result + let result = index + break + endif + let index += 2 + endfor + + if index >= len( a:keys ) + let result = -1 + endif 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 5978987..db2c2fd 100644 --- a/autoload/vimspector/internal/popup.vim +++ b/autoload/vimspector/internal/popup.vim @@ -42,13 +42,10 @@ function! s:UpdatePopup( id ) call popup_settext( a:id, buf ) endfunction -function! s:YesNoDefaultFilter( default_value, id, key ) abort +function! s:ConfirmKeyFilter( keys, id, key ) abort if a:key ==# "\" call popup_close( a:id, s:current_selection + 1 ) return 1 - elseif a:key ==# 'D' || a:key ==# 'd' - call popup_close( a:id, a:default_value ) - return 1 elseif index( [ "\", "\" ], a:key ) >= 0 let s:current_selection = ( s:current_selection + 1 ) % len( s:selections ) call s:UpdatePopup( a:id ) @@ -58,9 +55,19 @@ function! s:YesNoDefaultFilter( default_value, id, key ) abort \ ? len( s:selections ) - 1: s:current_selection - 1 call s:UpdatePopup( a:id ) return 1 + elseif a:key ==# "\" || a:key ==# "\" + call popup_close( a:id, -1 ) + return 1 endif - return popup_filter_yesno( a:id, a:key ) + let index = 1 + for key in a:keys + if a:key ==? key + call popup_close( a:id, index ) + return 1 + endif + let index += 1 + endfor endfunction function! s:ConfirmCallback( confirm_id, id, result ) abort @@ -90,7 +97,8 @@ function! vimspector#internal#popup#Confirm( \ confirm_id, \ text, \ options, - \ default_value ) abort + \ default_value, + \ keys ) abort silent! call prop_type_add( 'VimspectorSelectedItem', { \ 'highlight': 'PMenuSel' @@ -112,7 +120,7 @@ function! vimspector#internal#popup#Confirm( let config = { \ 'callback': function( 's:ConfirmCallback', [ a:confirm_id ] ), - \ 'filter': function( 's:YesNoDefaultFilter', [ a:default_value ] ), + \ 'filter': function( 's:ConfirmKeyFilter', [ a:keys ] ), \ 'mapping': v:false, \ } let config = vimspector#internal#popup#SetBorderChars( config ) diff --git a/python3/vimspector/custom/java.py b/python3/vimspector/custom/java.py index 83705c1..c2a2264 100644 --- a/python3/vimspector/custom/java.py +++ b/python3/vimspector/custom/java.py @@ -14,7 +14,7 @@ # limitations under the License. from vimspector.debug_session import DebugSession -from vimspector import utils +from vimspector import utils, settings class JavaDebugAdapter( object ): @@ -36,8 +36,16 @@ class JavaDebugAdapter( object ): 'arguments': {}, } ) - utils.Confirm( self.debug_session._api_prefix, - 'Code has changed, hot reload?', - handler ) + mode = settings.Get( 'java_hotcodereplace_mode' ) + if mode == 'ask': + utils.Confirm( self.debug_session._api_prefix, + 'Code has changed, hot reload?', + handler, + default_value = 1 ) + elif mode == 'always': + self.debug_session._connection.DoRequest( None, { + 'command': 'redefineClasses', + 'arguments': {}, + } ) 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 12e4563..255e072 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -949,10 +949,12 @@ class DebugSession( object ): def handle_choice( choice ): arguments = {} if choice == 1: + # yes arguments[ 'terminateDebuggee' ] = True - elif choice == 0: + elif choice == 2: + # no arguments[ 'terminateDebuggee' ] = False - elif choice == -1: + else: # Abort return @@ -961,7 +963,9 @@ class DebugSession( object ): utils.Confirm( self._api_prefix, "Terminate debuggee?", handle_choice, - default_value = 3 ) + default_value = 3, + options = [ '(Y)es', '(N)o', '(D)efault' ], + keys = [ 'y', 'n', 'd' ] ) def _PrepareAttach( self, adapter_config, launch_config ): diff --git a/python3/vimspector/settings.py b/python3/vimspector/settings.py index e9e76ea..a060543 100644 --- a/python3/vimspector/settings.py +++ b/python3/vimspector/settings.py @@ -59,7 +59,10 @@ DEFAULTS = { 'expand_or_jump': [ '', '<2-LeftMouse>' ], 'focus_thread': [ '' ], } - } + }, + + # Custom + 'java_hotcodereplace_mode': 'ask', } diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index ca0b80a..53ebd3b 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -390,18 +390,26 @@ def ConfirmCallback( confirm_id, result ): handler( result ) -def Confirm( api_prefix, prompt, handler, default_value = 3, options = None ): - global CONFIRM_ID +def Confirm( api_prefix, + prompt, + handler, + default_value = 2, + options: list = None, + keys: list = None ): if not options: - options = [ '(Y)es', '(N)o', '(D)efault' ] + options = [ '(Y)es', '(N)o' ] + if not keys: + keys = [ 'y', 'n' ] + global CONFIRM_ID CONFIRM_ID += 1 CONFIRM[ CONFIRM_ID ] = handler Call( f'vimspector#internal#{ api_prefix }popup#Confirm', CONFIRM_ID, prompt, options, - default_value ) + default_value, + keys ) def AppendToBuffer( buf, line_or_lines, modified=False ): From efc5c7686638efc4c047bf0f58ae58fbff0bd393 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 11 Mar 2021 22:45:59 +0000 Subject: [PATCH 23/73] Fix lints --- autoload/vimspector/internal/popup.vim | 5 +++-- python3/vimspector/utils.py | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/autoload/vimspector/internal/popup.vim b/autoload/vimspector/internal/popup.vim index db2c2fd..083fdf5 100644 --- a/autoload/vimspector/internal/popup.vim +++ b/autoload/vimspector/internal/popup.vim @@ -12,6 +12,7 @@ " 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. +scriptencoding utf-8 " Boilerplate {{{ @@ -36,7 +37,7 @@ let s:current_selection = 0 let s:selections = [] let s:text = [] -function! s:UpdatePopup( id ) +function! s:UpdatePopup( id ) abort let buf = copy( s:text ) call extend( buf, s:DrawButtons() ) call popup_settext( a:id, buf ) @@ -128,7 +129,7 @@ function! vimspector#internal#popup#Confirm( return popup_dialog( buf, config ) endfunction -function! vimspector#internal#popup#SetBorderChars( config ) +function! vimspector#internal#popup#SetBorderChars( config ) abort " When ambiwidth is single, use prettier characters for the border. This " would look silly when ambiwidth is double. if &ambiwidth ==# 'single' && &encoding ==? 'utf-8' diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 53ebd3b..5f836fc 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -378,6 +378,7 @@ def AskForInput( prompt, default_value = None, completion = None ): CONFIRM = {} CONFIRM_ID = 0 + def ConfirmCallback( confirm_id, result ): try: handler = CONFIRM.pop( confirm_id ) From c05335c79987dc3ab19f30c477ad1b435e1ab9bf Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 16 Mar 2021 19:15:56 +0000 Subject: [PATCH 24/73] Make default option work for terminate debugee --- python3/vimspector/debug_session.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 255e072..156cbfd 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -954,9 +954,10 @@ class DebugSession( object ): elif choice == 2: # no arguments[ 'terminateDebuggee' ] = False - else: + elif choice <= 0: # Abort return + # Else, use server default disconnect( arguments ) From a39017dd06869bdb2b38b30ec21f41cb684a8e8b Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 19 Mar 2021 18:23:48 +0000 Subject: [PATCH 25/73] Fix actually sending terminateDebugee, and fix neovim 1-based index reporting --- autoload/vimspector/internal/neopopup.vim | 10 ++++++---- python3/vimspector/debug_session.py | 9 +++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/autoload/vimspector/internal/neopopup.vim b/autoload/vimspector/internal/neopopup.vim index 9f35914..eb5a0dc 100644 --- a/autoload/vimspector/internal/neopopup.vim +++ b/autoload/vimspector/internal/neopopup.vim @@ -103,8 +103,10 @@ function! vimspector#internal#neopopup#Confirm( confirm_id, let result = -1 endtry - " Map the results to what popup_menu_filter would return (ok s:ConfirmCallback - " in popup.vim) + " Map the results to what the vim popup stuff would return (s:ConfirmCallback + " in popup.vim), i.e.: + " - 1-based index of selected item, or + " - -1 or 0 for cancellation if result == '' " User pressed ESC/ctrl-c let result = -1 @@ -115,10 +117,10 @@ function! vimspector#internal#neopopup#Confirm( confirm_id, let result = index break endif - let index += 2 + let index += 1 endfor - if index >= len( a:keys ) + if index > len( a:keys ) let result = -1 endif endif diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 156cbfd..2f132f9 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -916,7 +916,9 @@ class DebugSession( object ): self._logger.info( 'Debug Adapter Started' ) def _StopDebugAdapter( self, interactive = False, callback = None ): - def disconnect( arguments = {} ): + arguments = {} + + def disconnect(): self._splash_screen = utils.DisplaySplash( self._api_prefix, self._splash_screen, @@ -936,7 +938,7 @@ class DebugSession( object ): self._connection.DoRequest( handler, { 'command': 'disconnect', - 'arguments': {}, + 'arguments': arguments, }, failure_handler = handler, timeout = 5000 ) if not interactive: @@ -947,7 +949,6 @@ class DebugSession( object ): disconnect() else: def handle_choice( choice ): - arguments = {} if choice == 1: # yes arguments[ 'terminateDebuggee' ] = True @@ -959,7 +960,7 @@ class DebugSession( object ): return # Else, use server default - disconnect( arguments ) + disconnect() utils.Confirm( self._api_prefix, "Terminate debuggee?", From 1414f261a1700515eb67c429aa681cbd84eca4e5 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 19 Mar 2021 22:59:27 +0000 Subject: [PATCH 26/73] Documentation for hot code replace --- README.md | 18 +++++++++++++++++- autoload/vimspector/internal/neopopup.vim | 8 ++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2152a9c..952d07f 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ For detailed explanatin of the `.vimspector.json` format, see the * [Console autocompletion](#console-autocompletion) * [Log View](#log-view) * [Closing debugger](#closing-debugger) + * [Terminate debuggee](#terminate-debuggee) * [Debug profile configuration](#debug-profile-configuration) * [C, C , Rust, etc.](#c-c-rust-etc) * [C Remote debugging](#c-remote-debugging) @@ -76,6 +77,7 @@ For detailed explanatin of the `.vimspector.json` format, see the * [Debug cli application](#debug-cli-application) * [JavaScript, TypeScript, etc.](#javascript-typescript-etc) * [Java](#java) + * [Hot code replace](#hot-code-replace) * [Usage with YouCompleteMe](#usage-with-youcompleteme) * [Other LSP clients](#other-lsp-clients) * [Lua](#lua) @@ -91,7 +93,7 @@ For detailed explanatin of the `.vimspector.json` format, see the * [Example](#example) * [FAQ](#faq) - + @@ -1591,6 +1593,20 @@ editor plugin to use Java. I recommend [YouCompleteMe][], which has full support for jdt.ls, and most importantly a trivial way to load the debug adapter and to use it with Vimspector. +### Hot code replace + +When using the [java debug server][java-debug-server], Vimspector supports the +hot code replace custom feature. By default, when the underlying class files +change, vimspector asks the user if they wish to reload these classes at +runtime. + +This behaviour can be customised: + +* `let g:ycm_java_hotcodereplace_mode = 'ask'` - the default, ask the user for + each reload. +* `let g:ycm_java_hotcodereplace_mode = 'always'` - don't ask, always reload +* `let g:ycm_java_hotcodereplace_mode = 'never'` - don't ask, never reload + ### Usage with YouCompleteMe * Set up [YCM for java][YcmJava]. diff --git a/autoload/vimspector/internal/neopopup.vim b/autoload/vimspector/internal/neopopup.vim index eb5a0dc..a734ca3 100644 --- a/autoload/vimspector/internal/neopopup.vim +++ b/autoload/vimspector/internal/neopopup.vim @@ -87,16 +87,16 @@ function! vimspector#internal#neopopup#Confirm( confirm_id, \ keys ) abort " Neovim doesn't have an equivalent of popup_dialog, and it's way too much - " effort to write one, so we just use confirm(). + " effort to write one, so we just use confirm()... + " Annoyingly we can't use confirm() here because for some reason it doesn't + " render properly in a channel callback. So we use input() and mimic dialog + " behaviour. let prompt = a:text for opt in a:options let prompt .= ' ' . opt endfor let prompt .= ': ' - " Annoyingly we can't use confirm() here because for some reason it doesn't - " render properly in a channel callback. So we use input() and mimic dialog - " behaviour. try let result = input( prompt, a:keys[ a:default_value - 1 ] ) catch /.*/ From 842d9fbc2d39718943b5cf768996a0dcf1b04ffe Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 19 Mar 2021 17:50:29 +0000 Subject: [PATCH 27/73] Config for pyright language server --- .ycm_extra_conf.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py index f2e32ae..6f42505 100644 --- a/.ycm_extra_conf.py +++ b/.ycm_extra_conf.py @@ -42,7 +42,17 @@ def Settings( **kwargs ): return { 'sys_path': [ p.join( PATH_TO_THIS_DIR, 'python3' ) - ] + ], + 'ls': { + 'python': { + 'analysis': { + 'extraPaths': [ + p.join( PATH_TO_THIS_DIR, 'python3' ), + ], + 'useLibraryCodeForTypes': True + } + } + } } if IgnoreExtraConf: From 35e5b3d56e193ee6129eabedcd48fd17b8293b2d Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sat, 20 Mar 2021 15:55:22 +0000 Subject: [PATCH 28/73] Add vim doc based on README Use the following to recrate the doc: * clone https://github.com/ycm-core/vim-tools * create a venv and pip install the requierments * cd to vimspector dir * /path/to/vim-tools/html2vimdoc.py -f vimspector README.md > doc/vimspector.txt --- .gitignore | 1 + doc/vimspector.txt | 2394 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2395 insertions(+) create mode 100644 doc/vimspector.txt diff --git a/.gitignore b/.gitignore index 77f22a9..05dc8cd 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ support/test/csharp/*.exe* configurations/ venv/ test-base/ +tags diff --git a/doc/vimspector.txt b/doc/vimspector.txt new file mode 100644 index 0000000..8def87f --- /dev/null +++ b/doc/vimspector.txt @@ -0,0 +1,2394 @@ +*vimspector* vimspector - A multi language graphical debugger for Vim + +=============================================================================== +Contents ~ + + 1. Introduction |vimspector-introduction| + 2. Features and Usage |vimspector-features-usage| + 1. Supported debugging features |vimspector-supported-debugging-features| + 2. Supported languages |vimspector-supported-languages| + 3. Other languages |vimspector-other-languages| + 3. Installation |vimspector-installation| + 1. Quick Start |vimspector-quick-start| + 2. Dependencies |vimspector-dependencies| + 3. Neovim differences |vimspector-neovim-differences| + 4. Windows differences |vimspector-windows-differences| + 5. Trying it out |vimspector-trying-it-out| + 6. Cloning the plugin |vimspector-cloning-plugin| + 7. Install some gadgets |vimspector-install-gadgets| + 1. VimspectorInstall and VimspectorUpdate commands |vimspectorinstall-vimspectorupdate-commands| + 2. install_gadget.py |vimspector-install_gadget.py| + 8. Manual gadget installation |vimspector-manual-gadget-installation| + 1. The gadget directory |vimspector-gadget-directory| + 9. Upgrade |vimspector-upgrade| + 4. About |vimspector-about| + 1. Background |vimspector-background| + 2. Status |vimspector-status| + 1. Experimental |vimspector-experimental| + 3. Motivation |vimspector-motivation| + 4. License |vimspector-license| + 5. Sponsorship |vimspector-sponsorship| + 5. Mappings |vimspector-mappings| + 1. Visual Studio / VSCode |vimspector-visual-studio-vscode| + 2. Human Mode |vimspector-human-mode| + 6. Usage and API |vimspector-usage-api| + 1. Launch and attach by PID: |vimspector-launch-attach-by-pid| + 1. Launch with options |vimspector-launch-with-options| + 2. Debug configuration selection |vimspector-debug-configuration-selection| + 3. Get configurations |vimspector-get-configurations| + 2. Breakpoints |vimspector-breakpoints| + 1. Summary |vimspector-summary| + 2. Line breakpoints |vimspector-line-breakpoints| + 3. Conditional breakpoints |vimspector-conditional-breakpoints| + 4. Exception breakpoints |vimspector-exception-breakpoints| + 5. Clear breakpoints |vimspector-clear-breakpoints| + 6. Run to Cursor |vimspector-run-to-cursor| + 3. Stepping |vimspector-stepping| + 4. Variables and scopes |vimspector-variables-scopes| + 5. Variable or selection hover evaluation |vimspector-variable-or-selection-hover-evaluation| + 6. Watches |vimspector-watches| + 1. Watch autocompletion |vimspector-watch-autocompletion| + 7. Stack Traces |vimspector-stack-traces| + 8. Program Output |vimspector-program-output| + 1. Console |vimspector-console| + 2. Console autocompletion |vimspector-console-autocompletion| + 3. Log View |vimspector-log-view| + 9. Closing debugger |vimspector-closing-debugger| + 10. Terminate debuggee |vimspector-terminate-debuggee| + 7. Debug profile configuration |vimspector-debug-profile-configuration| + 1. C, C++, Rust, etc. |vimspector-c-c-rust-etc.| + 1. C++ Remote debugging |vimspector-c-remote-debugging| + 2. C++ Remote launch and attach |vimspector-c-remote-launch-attach| + 2. Rust |vimspector-rust| + 3. Python |vimspector-python| + 1. Python Remote Debugging |vimspector-python-remote-debugging| + 2. Python Remote launch and attach |vimspector-python-remote-launch-attach| + 3. Legacy: vscode-python |vimspector-legacy-vscode-python| + 4. TCL |vimspector-tcl| + 5. C♯ |vimspector-c| + 6. Go |vimspector-go| + 7. PHP |vimspector-php| + 1. Debug web application |vimspector-debug-web-application| + 2. Debug cli application |vimspector-debug-cli-application| + 8. JavaScript, TypeScript, etc. |vimspector-javascript-typescript-etc.| + 9. Java |vimspector-java| + 1. Usage with YouCompleteMe |vimspector-usage-with-youcompleteme| + 2. Other LSP clients |vimspector-other-lsp-clients| + 10. Lua |vimspector-lua| + 11. Other servers |vimspector-other-servers| + 8. Customisation |vimspector-customisation| + 1. Changing the default signs |vimspector-changing-default-signs| + 2. Sign priority |vimspector-sign-priority| + 3. Changing the default window sizes |vimspector-changing-default-window-sizes| + 4. Changing the terminal size |vimspector-changing-terminal-size| + 5. Custom mappings while debugging |vimspector-custom-mappings-while-debugging| + 6. Advanced UI customisation |vimspector-advanced-ui-customisation| + 7. Customising the WinBar |vimspector-customising-winbar| + 8. Example |vimspector-example| + 9. FAQ |vimspector-faq| + 10. References |vimspector-references| + +=============================================================================== + *vimspector-introduction* +Introduction ~ + +For a tutorial and usage overview, take a look at the Vimspector website [1]. + +For detailed explanatin of the '.vimspector.json' format, see the reference +guide [2]. + +Image: Build (see reference [3]) Image: Gitter [4] + +- Features and Usage + + - Supported debugging features + - Supported languages + - Other languages + +- Installation + + - Quick Start + - Dependencies + - Neovim differences + - Windows differences + - Trying it out + - Cloning the plugin + - Install some gadgets + - VimspectorInstall and VimspectorUpdate commands + - install_gadget.py + - Manual gadget installation + - The gadget directory + - Upgrade + +- About + + - Background + - Status + - Experimental + - Motivation + - License + - Sponsorship + +- Mappings + + - Visual Studio / VSCode + - Human Mode + +- Usage and API + + - Launch and attach by PID: + - Launch with options + - Debug configuration selection + - Get configurations + - Breakpoints + - Summary + - Line breakpoints + - Conditional breakpoints + - Exception breakpoints + - Clear breakpoints + - Run to Cursor + - Stepping + - Variables and scopes + - Variable or selection hover evaluation + - Watches + - Watch autocompletion + - Stack Traces + - Program Output + - Console + - Console autocompletion + - Log View + - Closing debugger + +- Debug profile configuration + + - C, C , Rust, etc. + - C Remote debugging + - C Remote launch and attach + - Rust + - Python + - Python Remote Debugging + - Python Remote launch and attach + - Legacy: vscode-python + - TCL + - C♯ + - Go + - PHP + - Debug web application + - Debug cli application + - JavaScript, TypeScript, etc. + - Java + - Usage with YouCompleteMe + - Other LSP clients + - Lua + - Other servers + +- Customisation + + - Changing the default signs + - Sign priority + - Changing the default window sizes + - Changing the terminal size + - Custom mappings while debugging + - Advanced UI customisation + - Customising the WinBar + - Example + +- FAQ + +=============================================================================== + *vimspector-features-usage* +Features and Usage ~ + +The plugin is a capable Vim graphical debugger for multiple languages. It's +mostly tested for c++, python and TCL, but in theory supports any language that +Visual Studio Code supports (but see caveats). + +The Vimspector website [1] has an overview of the UI, along with basic +instructions for configuration and setup. + +But for now, here's a (rather old) screenshot of Vimspector debugging Vim: + + Image: vimspector-vim-screenshot (see reference [6]) + +And a couple of brief demos: + + Image: asciicast [7] + + Image: asciicast [9] + +------------------------------------------------------------------------------- + *vimspector-supported-debugging-features* +Supported debugging features ~ + +- flexible configuration syntax that can be checked in to source control +- breakpoints (function, line and exception breakpoints) +- conditional breakpoints (function, line) +- step in/out/over/up, stop, restart +- run to cursor +- launch and attach +- remote launch, remote attach +- locals and globals display +- watch expressions with autocompletion +- variable inspection tooltip on hover +- set variable value in locals, watch and hover windows +- call stack display and navigation +- hierarchical variable value display popup (see + 'VimspectorBalloonEval') +- interactive debug console with autocompletion +- launch debuggee within Vim's embedded terminal +- logging/stdout display +- simple stable API for custom tooling (e.g. integrate with language server) + +------------------------------------------------------------------------------- + *vimspector-supported-languages* +Supported languages ~ + +The following table lists the languages that are "built-in" (along with their +runtime dependencies). They are categorised by their level of support: + +- 'Tested' : Fully supported, Vimspector regression tests cover them +- 'Supported' : Fully supported, frequently used and manually tested +- 'Experimental': Working, but not frequently used and rarely tested +- 'Legacy': No longer supported, please migrate your config + +======================================================================================================================================================== +| _Language_ | _Status_ | _Switch (for 'install_gadget.py')_ | _Adapter (for ':VimspectorInstall')_ | _Dependencies_ | +======================================================================================================================================================== +| C, C++, Rust etc. | Tested | '--all' or '--enable-c' (or cpp) | vscode-cpptools | mono-core | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Rust, C, C++, etc. | Supported | '--force-enable-rust' | CodeLLDB | Python 3 | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Python | Tested | '--all' or '--enable-python' | debugpy | Python 2.7 or Python 3 | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Go | Tested | '--enable-go' | vscode-go | Go, Delve [11] | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| TCL | Supported | '--all' or '--enable-tcl' | tclpro | TCL 8.5 | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Bourne Shell | Supported | '--all' or '--enable-bash' | vscode-bash-debug | Bash v?? | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Lua | Supported | '--all' or '--enable-lua' | local-lua-debugger-vscode | Node >=12.13.0, Npm, Lua interpreter | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Node.js | Supported | '--force-enable-node' | vscode-node-debug2 | 6 < Node < 12, Npm | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Javascript | Supported | '--force-enable-chrome' | debugger-for-chrome | Chrome | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Java | Supported | '--force-enable-java' | vscode-java-debug | Compatible LSP plugin (see later) | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| C# (dotnet core) | Experimental | '--force-enable-csharp' | netcoredbg | DotNet core | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| C# (mono) | Experimental | '--force-enable-csharp' | vscode-mono-debug | Mono | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| F#, VB, etc. | Experimental | '--force-enable-fsharp' (or vbnet) | netcoredbg | DotNet core | +-------------------------------------------------------------------------------------------------------------------------------------------------------- +| Python.legacy | Legacy | '--force-enable-python.legacy' | vscode-python | Node 10, Python 2.7 or Python 3 | +-------------------------------------------------------------------------------------------------------------------------------------------------------- + + +------------------------------------------------------------------------------- + *vimspector-other-languages* +Other languages ~ + +Vimspector should work for any debug adapter that works in Visual Studio Code. + +To use Vimspector with a language that's not "built-in", see this wiki page +[12]. + +=============================================================================== + *vimspector-installation* +Installation ~ + +------------------------------------------------------------------------------- + *vimspector-quick-start* +Quick Start ~ + +There are 2 installation methods: + +- Using a release tarball and vim packages +- Using a clone of the repo (e.g. package manager) + +Release tarballs come with debug adapters for the default languages +pre-packaged. To use a release tarball: + +1. Check the dependencies +2. Untar the release tarball for your OS into '$HOME/.vim/pack': +> + $ mkdir -p $HOME/.vim/pack + $ curl -L | tar -C $HOME/.vim/pack zxvf - +< +1. Add 'packadd! vimspector' to you '.vimrc' + +2. (optionally) Enable the default set of mappings: +> + let g:vimspector_enable_mappings = 'HUMAN' +< +1. Configure your project's debug profiles (create '.vimspector.json') + +Alternatively, you can clone the repo and select which gadgets are installed: + +1. Check the dependencies +2. Install the plugin as a Vim package. See ':help packages'. +3. Add 'packadd! vimspector' to you '.vimrc' +4. Install some 'gadgets' (debug adapters) - see ':VimspectorInstall ...' +5. Configure your project's debug profiles (create '.vimspector.json') + +If you prefer to use a plugin manager, see the plugin manager's docs. For +Vundle, use: +> + Plugin 'puremourning/vimspector' +< +The following sections expand on the above brief overview. + +------------------------------------------------------------------------------- + *vimspector-dependencies* +Dependencies ~ + +Vimspector requires: + +- One of: +- Vim 8.2 Huge build compiled with Python 3.6 or later +- Neovim 0.4.3 with Python 3.6 or later (experimental) +- One of the following operating systems: +- Linux +- macOS Mojave or later +- Windows (experimental) + +Why such a new vim ? Well 2 reasons: + +1. Because vimspector uses a lot of new Vim features +2. Because there are Vim bugs that vimspector triggers that will frustrate + you if you hit them. + +Why is neovim experimental? Because the author doesn't use neovim regularly, +and there are no regression tests for vimspector in neovim, so it may break +occasionally. Issue reports are handled on best-efforts basis, and PRs are +welcome to fix bugs. See also the next section descibing differences for neovim +vs vim. + +Why Windows support experimental? Because it's effort and it's not a priority +for the author. PRs are welcome to fix bugs. Windows will not be regularly +tested. + +Which Linux versions? I only test on Ubuntu 18.04 and later and RHEL 7. + +------------------------------------------------------------------------------- + *vimspector-neovim-differences* +Neovim differences ~ + +neovim doesn't implement some features Vimspector relies on: + +- WinBar - used for the buttons at the top of the code window and for + changing the output window's current output. + +- Prompt Buffers - used to send commands in the Console and add Watches. + (_Note_: prompt buffers are available in neovim nightly) + +- Balloons - this allows for the variable evaluation popup to be displayed + when hovering the mouse. See below for how to create a keyboard mapping + instead. + +Workarounds are in place as follows: + +- WinBar - There are mappings, ':VimspectorShowOutput' and ':VimspectorReset' + +- Prompt Buffers - There are ':VimspectorEval' and ':VimspectorWatch' + +- Balloons - There is the 'VimspectorBalloonEval' mapping. There is no + default mapping for this, so I recommend something like this to get + variable display in a popup: +> + " mnemonic 'di' = 'debug inspect' (pick your own, if you prefer!) + + " for normal mode - the word under the cursor + nmap di VimspectorBalloonEval + " for visual mode, the visually selected text + xmap di VimspectorBalloonEval +< +------------------------------------------------------------------------------- + *vimspector-windows-differences* +Windows differences ~ + +The following features are not implemented for Windows: + +- Tailing the vimspector log in the Output Window. + +------------------------------------------------------------------------------- + *vimspector-trying-it-out* +Trying it out ~ + +If you just want to try out vimspector without changing your vim config, there +are example projects for a number of languages in 'support/test', including: + +- Python ('support/test/python/simple_python') +- Go ('support/test/go/hello_world') +- Nodejs ('support/test/node/simple') +- Chrome ('support/test/chrome/') +- etc. + +To test one of these out, cd to the directory and run: +> + vim -Nu /path/to/vimspector/tests/vimrc --cmd "let g:vimspector_enable_mappings='HUMAN'" +< +Then press ''. + +There's also a C++ project in 'tests/testdata/cpp/simple/' with a 'Makefile' +which can be used to check everything is working. This is used by the +regression tests in CI so should always work, and is a good way to check if the +problem is your configuration rather than a bug. + +------------------------------------------------------------------------------- + *vimspector-cloning-plugin* +Cloning the plugin ~ + +If you're not using a release tarball, you'll need to clone this repo to the +appropriate place. + +1. Clone the plugin + +There are many Vim plugin managers, and I'm not going to state a particular +preference, so if you choose to use one, follow the plugin manager's +documentation. For example, for Vundle, use: +> + Plugin 'puremourning/vimspector' +< +If you don't use a plugin manager already, install vimspector as a Vim package +by cloning this repository into your package path, like this: +> + $ git clone https://github.com/puremourning/vimspector ~/.vim/pack/vimspector/opt/vimspector +< +1. Configure vimspector in your '.vimrc', for example to enable the standard + mapings: +> + let g:vimspector_enable_mappings = 'HUMAN' +< +1. Load vimspector at runtime. This can also be added to your '.vimrc' after + configuring vimspector: +> + packadd! vimspector +< +See support/doc/example_vimrc.vim for a minimal example. + +------------------------------------------------------------------------------- + *vimspector-install-gadgets* +Install some gadgets ~ + +Vimspector is a generic client for Debug Adapters. Debug Adapters (referred to +as 'gadgets' or 'adapters') are what actually do the work of talking to the +real debuggers. + +In order for Vimspector to be useful, you need to have some adapters installed. + +There are a few ways to do this: + +- If you downloaded a tarball, gadgets for main supported languages are + already installed for you. + +- Using ':VimspectorInstall ' (use TAB 'wildmenu' to see + the options, also accepts any 'install_gadget.py' option) + +- Using 'python3 install_gadget.py ' (use '--help' to see all options) + +- Attempting to launch a debug configuration; if the configured adapter can't + be found, vimspector will suggest installing one. + +- Using ':VimspectorUpdate' to install the latest supported versions of the + gadgets. + +Here's a demo of doing some installs and an upgrade: + + Image: asciicast [13] + +Both 'install_gadget.py' and ':VimspectorInstall' do the same set of things, +though the default behaviours are slightly different. For supported languages, +they will: + +- Download the relevant debug adapter at a version that's been tested from + the internet, either as a 'vsix' (Visusal Studio plugin), or clone from + GitHub. If you're in a corporate environment and this is a problem, you may + need to install the gadgets manually. + +- Perform any necessary post-installation actions, such as: + +- Building any binary components + +- Ensuring scripts are executable, because the VSIX packages are usually + broken in this regard. + +- Set up the 'gadgetDir' symlinks for the platform. + +For example, to install the tested debug adapter for a language, run: + +======================================================================================================================================== +| _To install_ | _Script_ | _Command_ | +======================================================================================================================================== +| '' | ':VimspectorInstall ' | +----------------------------------------------------------------------------------------- +| '', '', ... | ':VimspectorInstall ...' | +----------------------------------------------------------------------------------------- +| '' | './install_gadget.py --enable- ...' | ':VimspectorInstall --enable- ...' | +---------------------------------------------------------------------------------------------------------------------------------------- +| Supported adapters | './install_gadget.py --all' | ':VimspectorInstall --all' | +---------------------------------------------------------------------------------------------------------------------------------------- +| Supported adapters, but not TCL | './install_gadget.py --all --disable-tcl' | ':VimspectorInstall --all --disable-tcl' | +---------------------------------------------------------------------------------------------------------------------------------------- +| Supported and experimental adapters | './install_gadget.py --all --force-all' | ':VimspectorInstall --all' | +---------------------------------------------------------------------------------------------------------------------------------------- +| Adapter for specific debug config | Suggested by Vimspector when starting debugging | +----------------------------------------------------------------------------------------- + + +------------------------------------------------------------------------------- + *vimspectorinstall-vimspectorupdate-commands* +VimspectorInstall and VimspectorUpdate commands ~ + +':VimspectorInstall' runs 'install_gadget.py' in the background with some of +the options defaulted. + +':VimspectorUpdate' runs 'install_gadget.py' to re-install (i.e. update) any +gadgets already installed in your '.gadgets.json'. + +The output is minimal, to see the full output add '--verbose' to the command, +as in ':VimspectorInstall --verbose ...' or ':VimspectorUpdate --verbose ...'. + +If the installation is successful, the output window is closed (and the output +lost forever). Use a '!' to keep it open (e.g. ':VimspectorInstall! --verbose +--all' or ':VimspectorUpdate!' (etc.). + +If you know in advance which gadgets you want to install, for example so that +you can reproduce your config from source control, you can set +'g:vimspector_install_gadgets' to a list of gadgets. This will be used when: + +- Running ':VimspectorInstall' with no arguments, or +- Running ':VimspectorUpdate' + +For example: +> + let g:vimspector_install_gadgets = [ 'debugpy', 'vscode-cpptools', 'CodeLLDB' ] +< +------------------------------------------------------------------------------- + *vimspector-install_gadget.py* +install_gadget.py ~ + +By default 'install_gadget.py' will overwrite your '.gadgets.json' with the set +of adapters just installed, whereas ':VimspectorInstall' will _update_ it, +overwriting only newly changed or installed adapters. + +If you want to just add a new adapter using the script without destroying the +existing ones, add '--update-gadget-config', as in: +> + $ ./install_gadget.py --enable-tcl + $ ./install_gadget.py --enable-rust --update-gadget-config + $ ./install_gadget.py --enable-java --update-gadget-config +< +If you want to maintain 'configurations' outside of the vimspector repository +(this can be useful if you have custom gadgets or global configurations), you +can tell the installer to use a different basedir, then set +'g:vimspector_base_dir' to point to that directory, for example: +> + $ ./install_gadget.py --basedir $HOME/.vim/vimspector-config --all --force-all +< +Then add this to your '.vimrc': +> + let g:vimspector_base_dir=expand( '$HOME/.vim/vimspector-config' ) +< +When usnig ':VimspectorInstall', the 'g:vimspector_base_dir' setting is +respected unless '--basedir' is manually added (not recommended). + +See '--help' for more info on the various options. + +------------------------------------------------------------------------------- + *vimspector-manual-gadget-installation* +Manual gadget installation ~ + +If the language you want to debug is not in the supported list above, you can +probably still make it work, but it's more effort. + +You essentially need to get a working installation of the debug adapter, find +out how to start it, and configure that in an 'adapters' entry in either your +'.vimspector.json' or in '.gadgets.json'. + +The simplest way in practice is to install or start Visual Studio Code and use +its extension manager to install the relevant extension. You can then configure +the adapter manually in the 'adapters' section of your '.vimspector.json' or in +a 'gadgets.json'. + +PRs are always welcome to add supported languages (which roughly translates to +updating 'python/vimspector/gadgets.py' and testing it). + +------------------------------------------------------------------------------- + *vimspector-gadget-directory* +The gadget directory ~ + +Vimspector uses the following directory by default to look for a file named +'.gadgets.json': '/gadgets/'. + +This path is exposed as the vimspector _variable_ '${gadgetDir}'. This is +useful for configuring gadget command lines. + +Where os is one of: + +- 'macos' +- 'linux' +- 'windows' (though note: Windows is not supported) + +The format is the same as '.vimspector.json', but only the 'adapters' key is +used: + +Example: +> + { + "adapters": { + "lldb-vscode": { + "variables": { + "LLVM": { + "shell": "brew --prefix llvm" + } + }, + "attach": { + "pidProperty": "pid", + "pidSelect": "ask" + }, + "command": [ + "${LLVM}/bin/lldb-vscode" + ], + "env": { + "LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY": "YES" + }, + "name": "lldb" + }, + "vscode-cpptools": { + "attach": { + "pidProperty": "processId", + "pidSelect": "ask" + }, + "command": [ + "${gadgetDir}/vscode-cpptools/debugAdapters/OpenDebugAD7" + ], + "name": "cppdbg" + }, + "vscode-python": { + "command": [ + "node", + "${gadgetDir}/vscode-python/out/client/debugger/debugAdapter/main.js" + ], + "name": "vscode-python" + } + } + } +< +The gadget file is automatically written by 'install_gadget.py' (or +':VimspectorInstall'). + +Vimspector will also load any fies matching: +'/gadgets//.gadgets.d/*.json'. These have the same +format as '.gadgets.json' but are not overwritten when running +'install_gadget.py'. + +------------------------------------------------------------------------------- + *vimspector-upgrade* +Upgrade ~ + +After updating the Vimspector code (either via 'git pull' or whatever package +manager), run ':VimspectorUpdate' to update any already-installed gadgets. + +=============================================================================== + *vimspector-about* +About ~ + +------------------------------------------------------------------------------- + *vimspector-background* +Background ~ + +The motivation is that debugging in Vim is a pretty horrible experience, +particularly if you use multiple languages. With pyclewn no more and the +built-in termdebug plugin limited to gdb, I wanted to explore options. + +While Language Server Protocol is well known, the Debug Adapter Protocol is +less well known, but achieves a similar goal: language agnostic API abstracting +debuggers from clients. + +The aim of this project is to provide a simple but effective debugging +experience in Vim for multiple languages, by leveraging the debug adapters that +are being built for Visual Studio Code. + +The ability to do remote debugging is a must. This is key to my workflow, so +baking it in to the debugging experience is a top bill goal for the project. So +vimspector has first-class support for executing programs remotely and +attaching to them. This support is unique to vimspector and on top of +(complementary to) any such support in actual debug adapters. + +------------------------------------------------------------------------------- + *vimspector-status* +Status ~ + +Vimspector is a work in progress, and any feedback/contributions are more than +welcome. + +The backlog can be viewed on Trello [15]. + +------------------------------------------------------------------------------- + *vimspector-experimental* +Experimental ~ + +The plugin is currently _experimental_. That means that any part of it can (and +probably will) change, including things like: + +- breaking changes to the configuration +- keys, layout, functionality of the UI + +However, I commit to only doing this in the most extreme cases and to annouce +such changes on Gitter well in advance. There's nothing more annoying than +stuff just breaking on you. I get that. + +------------------------------------------------------------------------------- + *vimspector-motivation* +Motivation ~ + +A message from the author about the motivation for this plugin: + +Many development environments have a built-in debugger. I spend an inordinate +amount of my time in Vim. I do all my development in Vim and I have even +customised my workflows for building code, running tests etc. + +For many years I have observed myself, friends and colleagues have been writing +'printf', 'puts', 'print', etc. debugging statements in all sorts of files +simply because there is no _easy_ way to run a debugger for _whatever_ language +we happen to be developing in. + +I truly believe that interactive, graphical debugging environments are the best +way to understand and reason about both unfamiliar and familiar code, and that +the lack of ready, simple access to a debugger is a huge hidden productivity +hole for many. + +Don't get me wrong, I know there are literally millions of developers out there +that are more than competent at developing without a graphical debugger, but I +maintain that if they had the ability to _just press a key_ and jump into the +debugger, it would be faster and more enjoyable that just cerebral code +comprehension. + +I created Vimspector because I find changing tools frustrating. 'gdb' for c++, +'pdb' for python, etc. Each has its own syntax. Each its own lexicon. Each its +own foibles. + +I designed the configuration system in such a way that the configuration can be +committed to source control so that it _just works_ for any of your colleagues, +friends, collaborators or complete strangers. + +I made remote debugging a first-class feature because that's a primary use case +for me in my job. + +With Vimspector I can _just hit ''_ in all of the languages I develop in +and debug locally or remotely using the exact same workflow, mappings and UI. I +have integrated this with my Vim in such a way that I can hit a button and _run +the test under the cursor in Vimspector_. This kind of integration has +massively improved my workflow and productivity. It's even made the process of +learning a new codebase... fun. + +- Ben Jackson, Creator. + +------------------------------------------------------------------------------- + *vimspector-license* +License ~ + +Apache 2.0 [16] + +Copyright © 2018 Ben Jackson + +------------------------------------------------------------------------------- + *vimspector-sponsorship* +Sponsorship ~ + +If you like Vimspector so much that you're wiling to part with your hard-earned +cash, please consider donating to one of the following charities, which are +meaningful to the author of Vimspector (in order of preference): + +- Greyhound Rescue Wales [17] +- Cancer Research UK [18] +- ICCF Holland [19] +- Any charity of your choosing. + +=============================================================================== + *vimspector-mappings* +Mappings ~ + +By default, vimspector does not change any of your mappings. Mappings are very +personal and so you should work out what you like and use vim's powerful +mapping features to set your own mappings. To that end, Vimspector defines the +following '' mappings: + +================================================================================================================================================================================= +| _Mapping_ | _Function_ | _API_ | +================================================================================================================================================================================= +| 'VimspectorContinue' | When debugging, continue. Otherwise start debugging. | 'vimspector#Continue()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorStop' | Stop debugging. | 'vimspector#Stop()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimpectorRestart' | Restart debugging with the same configuration. | 'vimspector#Restart()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorPause' | Pause debuggee. | 'vimspector#Pause()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorToggleBreakpoint' | Toggle line breakpoint on the current line. | 'vimspector#ToggleBreakpoint()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorToggleConditionalBreakpoint' | Toggle conditional line breakpoint on the current line. | 'vimspector#ToggleBreakpoint( { trigger expr, hit count expr } )' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorAddFunctionBreakpoint' | Add a function breakpoint for the expression under cursor | "vimspector#AddFunctionBreakpoint( '' )" | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorRunToCursor' | Run to Cursor | 'vimspector#RunToCursor()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorStepOver' | Step Over | 'vimspector#StepOver()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorStepInto' | Step Into | 'vimspector#StepInto()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorStepOut' | Step out of current function scope | 'vimspector#StepOut()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorUpFrame' | Move up a frame in the current call stack | 'vimspector#UpFrame()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorDownFrame' | Move down a frame in the current call stack | 'vimspector#DownFrame()' | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +| 'VimspectorBalloonEval' | Evaluate expression under cursor (or visual) in popup | _internal_ | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + + +These map roughly 1-1 with the API functions below. + +For example, if you want '' to start/continue debugging, add this to some +appropriate place, such as your 'vimrc' (hint: run ':e $MYVIMRC'). +> + nmap VimspectorContinue +< +In addition, many users probably want to only enable certain Vimspector +mappings while debugging is active. This is also possible, though it requires +writing some vimscipt. + +That said, many people are familiar with particular debuggers, so the following +mappings can be enabled by setting 'g:vimspector_enable_mappings' to the +specified value. + +------------------------------------------------------------------------------- + *vimspector-visual-studio-vscode* +Visual Studio / VSCode ~ + +To use Visual Studio-like mappings, add the following to your 'vimrc' **before +loading vimspector**: +> + let g:vimspector_enable_mappings = 'VISUAL_STUDIO' +< +========================================================================================================================= +| _Key_ | _Mapping_ | _Function_ | +========================================================================================================================= +| 'F5' | 'VimspectorContinue' | When debugging, continue. Otherwise start debugging. | +------------------------------------------------------------------------------------------------------------------------- +| 'Shift F5' | 'VimspectorStop' | Stop debugging. | +------------------------------------------------------------------------------------------------------------------------- +| 'Ctrl Shift F5' | 'VimspectorRestart' | Restart debugging with the same configuration. | +------------------------------------------------------------------------------------------------------------------------- +| 'F6' | 'VimspectorPause' | Pause debuggee. | +------------------------------------------------------------------------------------------------------------------------- +| 'F9' | 'VimspectorToggleBreakpoint' | Toggle line breakpoint on the current line. | +------------------------------------------------------------------------------------------------------------------------- +| 'Shift F9' | 'VimspectorAddFunctionBreakpoint' | Add a function breakpoint for the expression under cursor | +------------------------------------------------------------------------------------------------------------------------- +| 'F10' | 'VimspectorStepOver' | Step Over | +------------------------------------------------------------------------------------------------------------------------- +| 'F11' | 'VimspectorStepInto' | Step Into | +------------------------------------------------------------------------------------------------------------------------- +| 'Shift F11' | 'VimspectorStepOut' | Step out of current function scope | +------------------------------------------------------------------------------------------------------------------------- + + +------------------------------------------------------------------------------- + *vimspector-human-mode* +Human Mode ~ + +If, like me, you only have 2 hands and 10 fingers, you probably don't like +Ctrl-Shift-F keys. Also, if you're running in a terminal, there's a real +possibility of terminfo being wrong for shifted-F-keys, particularly if your +'TERM' is 'screen-256color'. If these issues (number of hands, 'TERM' +variables) are unfixable, try the following mappings, by adding the following +**before loading vimspector**: +> + let g:vimspector_enable_mappings = 'HUMAN' +< +============================================================================================================================ +| _Key_ | _Mapping_ | _Function_ | +============================================================================================================================ +| 'F5' | 'VimspectorContinue' | When debugging, continue. Otherwise start debugging. | +---------------------------------------------------------------------------------------------------------------------------- +| 'F3' | 'VimspectorStop' | Stop debugging. | +---------------------------------------------------------------------------------------------------------------------------- +| 'F4' | 'VimspectorRestart' | Restart debugging with the same configuration. | +---------------------------------------------------------------------------------------------------------------------------- +| 'F6' | 'VimspectorPause' | Pause debuggee. | +---------------------------------------------------------------------------------------------------------------------------- +| 'F9' | 'VimspectorToggleBreakpoint' | Toggle line breakpoint on the current line. | +---------------------------------------------------------------------------------------------------------------------------- +| 'F9' | 'VimspectorToggleConditionalBreakpoint' | Toggle conditional line breakpoint on the current line. | +---------------------------------------------------------------------------------------------------------------------------- +| 'F8' | 'VimspectorAddFunctionBreakpoint' | Add a function breakpoint for the expression under cursor | +---------------------------------------------------------------------------------------------------------------------------- +| 'F8' | 'VimspectorRunToCursor' | Run to Cursor | +---------------------------------------------------------------------------------------------------------------------------- +| 'F10' | 'VimspectorStepOver' | Step Over | +---------------------------------------------------------------------------------------------------------------------------- +| 'F11' | 'VimspectorStepInto' | Step Into | +---------------------------------------------------------------------------------------------------------------------------- +| 'F12' | 'VimspectorStepOut' | Step out of current function scope | +---------------------------------------------------------------------------------------------------------------------------- + + +In addition, I recommend adding a mapping to 'VimspectorBalloonEval', in +normal and visual modes, for example: +> + " mnemonic 'di' = 'debug inspect' (pick your own, if you prefer!) + + " for normal mode - the word under the cursor + nmap di VimspectorBalloonEval + " for visual mode, the visually selected text + xmap di VimspectorBalloonEval +< +You may also wish to add mappings for up/down the stack, for example: +> + nmap VimspectorUpFrame + nmap VimspectorDownFrame +< +=============================================================================== + *vimspector-usage-api* +Usage and API ~ + +This section defines detailed usage instructions, organised by feature. For +most users, the mappings section contains the most common commands and default +usage. This section can be used as a reference to create your own mappings or +custom behaviours. + +------------------------------------------------------------------------------- + *vimspector-launch-attach-by-pid* +Launch and attach by PID: ~ + +- Create '.vimspector.json'. See below. +- ':call vimspector#Launch()' and select a configuration. + + Image: debug session (see reference [6]) + +------------------------------------------------------------------------------- + *vimspector-launch-with-options* +Launch with options ~ + +To launch a specific debug configuration, or specify replacement variables [20] +for the launch, you can use: + +- ':call vimspector#LaunchWithSettings( dict )' + +The argument is a 'dict' with the following keys: + +- 'configuration': (optional) Name of the debug configuration to launch +- '': (optional) Name of a variable to set + +This allows for some integration and automation. For example, if you have a +configuration named 'Run Test' that contains a replacement variable [20] named +'${Test}' you could write a mapping which ultimately executes: +> + vimspector#LaunchWithSettings( #{ configuration: 'Run Test' + \ Test: 'Name of the test' } ) +< +This would start the 'Run Test' configuration with '${Test}' set to "'Name of +the test'" and Vimspector would _not_ prompt the user to enter or confirm these +things. + +See our YouCompleteMe integration guide for another example where it can be +used to specify the port to connect the java debugger + +------------------------------------------------------------------------------- + *vimspector-debug-configuration-selection* +Debug configuration selection ~ + +Vimspector uses the following logic to choose a configuration to launch: + +1. If a configuration was specified in the launch options (as above), use + that. + +2. Otherwise if there's only one configuration and it doesn't have + 'autoselect' set to 'false', use that. + +3. Otherwise if there's exactly one configuration with 'default' set to + 'true' and without 'autoselect' set to 'false', use that. + +4. Otherwise, prompt the user to select a configuration. + +See the reference guide [21] for details. + +------------------------------------------------------------------------------- + *vimspector-get-configurations* +Get configurations ~ + +- Use 'vimspector#GetConfigurations()' to get a list of configurations + +For example, to get an array of configurations and fuzzy matching on the result +> + :call matchfuzzy(vimspector#GetConfigurations(), "test::case_1") +< +------------------------------------------------------------------------------- + *vimspector-breakpoints* +Breakpoints ~ + +See the mappings [22] section for the default mappings for working with +breakpoints. This section describes the full API in vimscript functions. + +------------------------------------------------------------------------------- + *vimspector-summary* +Summary ~ + +- Use 'vimspector#ToggleBreakpoint( { options dict } )' to set/disable/delete + a line breakpoint. The argument is optional (see below). + +- Use "vimspector#AddFunctionBreakpoint( '', { options dict} )" to add + a function breakpoint. The second argument is optional (see below). + +- Use 'vimspector#SetLineBreakpoint( file_name, line_num, { options dict } )' + to set a breakpoint at a specific file/line. The last argument is optional + (see below) + +- Use 'vimspector#ClearLineBreakpoint( file_name, line_num )' to remove a + breakpoint at a specific file/line + +- Use 'vimspector#ClearBreakpoints()' to clear all breakpoints + +Examples: + +- 'call vimspector#ToggleBreakpoint()' - toggle breakpoint on current line + +- "call vimspector#SetLineBreakpoint( 'some_file.py', 10 )" - set a + breakpoint on 'some_filepy:10' + +- "call vimspector#AddFunctionBreakpoint( 'main' )" - add a function + breakpoint on the 'main' function + +- "call vimspector#ToggleBreakpoint( { 'condition': 'i > 5' } )" - add a + breakpoint on the current line that triggers only when 'i > 5' is 'true' + +- "call vimspector#SetLineBreakpoint( 'some_file.py', 10, { 'condition': 'i > + 5' } )" - add a breakpoint at 'some_file.py:10' that triggers only when 'i + > 5' is 'true' + +- "call vimspector#ClearLineBreakpoint( 'some_file.py', 10 )" - delete the + breakpoint at 'some_file.py:10' + +- 'call vimspector#ClearBreakpoints()' - clear all breakpoints + +------------------------------------------------------------------------------- + *vimspector-line-breakpoints* +Line breakpoints ~ + +The simplest and most common form of breakpoint is a line breakpoint. Execution +is paused when the specified line is executed. + +For most debugging scenarios, users will just hit '' to create a line +breakpoint on the current line and '' to launch the application. + +------------------------------------------------------------------------------- + *vimspector-conditional-breakpoints* +Conditional breakpoints ~ + +Some debug adapters support conditional breakpoints. Note that vimspector does +not tell you if the debugger doesn't support conditional breakpoints (yet). A +conditional breakpoint is a breakpoint which only triggers if some expression +evaluates to true, or has some other constraints met. + +Some of these functions above take a single optional argument which is a +dictionary of options. The dictionary can have the following keys: + +- 'condition': An optional expression evaluated to determine if the + breakpoint should fire. Not supported by all debug adapters. For example, + to break when 'abc' is '10', enter something like 'abc == 10', depending on + the language. + +- 'hitCondition': An optional expression evaluated to determine a number of + times the breakpoint should be ignored. Should (probably?) not be used in + combination with 'condition'. Not supported by all debug adapters. For + example, to break on the 3rd time hitting this line, enter '3'. + +In both cases, the expression is evaluated by the debugger, so should be in +whatever dialect the debugger understands when evaluating expressions. + +When using the '' mapping, the user is prompted to enter these +expressions in a command line (with history). + +------------------------------------------------------------------------------- + *vimspector-exception-breakpoints* +Exception breakpoints ~ + +Exception breakpoints typically fire when an exception is throw or other error +condition occurs. Depending on the debugger, when starting debugging, you may +be asked a few questions about how to handle exceptions. These are "exception +breakpoints" and vimspector remembers your choices while Vim is still running. + +Typically you can accept the defaults (just keep pressing ''!) as most +debug adapter defaults are sane, but if you want to break on, say 'uncaught +exception' then answer 'Y' to that (for example). + +You can configure your choices in the '.vimspector.json'. See the configuration +guide [23] for details on that. + +------------------------------------------------------------------------------- + *vimspector-clear-breakpoints* +Clear breakpoints ~ + +Use 'vimspector#ClearBreakpoints()' to clear all breakpoints including the +memory of exception breakpoint choices. + +------------------------------------------------------------------------------- + *vimspector-run-to-cursor* +Run to Cursor ~ + +Use 'vimspector#RunToCursor' or '': this creates a temporary +breakpoint on the current line, then continues execution, clearing the +breakpoint when it is hit. + +------------------------------------------------------------------------------- + *vimspector-stepping* +Stepping ~ + +- Step in/out, finish, continue, pause etc. using the WinBar, or mappings. +- If you really want to, the API is 'vimspector#StepInto()' etc. + + Image: code window (see reference [24]) + +------------------------------------------------------------------------------- + *vimspector-variables-scopes* +Variables and scopes ~ + +- Current scope shows values of locals. +- Use '', or double-click with left mouse to expand/collapse (+, -). +- Set the value of the variable with '' (control + '') or + '' (if 'modifyOtherKeys' doesn't work for you) +- When changing the stack frame the locals window updates. +- While paused, hover to see values + + Image: locals window (see reference [25]) + +Scopes and variables are represented by the buffer 'vimspector.Variables'. + +------------------------------------------------------------------------------- + *vimspector-variable-or-selection-hover-evaluation* +Variable or selection hover evaluation ~ + +All rules for 'Variables and scopes' apply plus the following: + +- With mouse enabled, hover over a variable and get the value it evaluates + to. + +- Use your mouse to perform a visual selection of an expression (e.g. 'a + + b') and get its result. + +- Make a normal mode ('nmap') and visual mode ('xmap') mapping to + 'VimspectorBalloonEval' to manually trigger the popup. + +- Set the value of the variable with '' (control + '') or + '' (if 'modifyOtherKeys' doesn't work for you) + +- Use regular nagivation keys ('j', 'k') to choose the current selection; + '' (or leave the tooltip window) to close the tooltip. + + Image: variable eval hover (see reference [26]) + +------------------------------------------------------------------------------- + *vimspector-watches* +Watches ~ + +The watch window is used to inspect variables and expressions. Expressions are +evaluated in the selected stack frame which is "focussed" + +The watches window is a prompt buffer, where that's available. Enter insert +mode to add a new watch expression. + +- Add watches to the variables window by entering insert mode and typing the + expression. Commit with ''. + +- Alternatively, use ':VimspectorWatch '. Tab-completion for + expression is available in some debug adapters. + +- Expand result with '', or double-click with left mouse. + +- Set the value of the variable with '' (control + '') or + '' (if 'modifyOtherKeys' doesn't work for you) + +- Delete with ''. + + Image: watch window (see reference [27]) + +The watches are represented by the buffer 'vimspector.StackTrace'. + +------------------------------------------------------------------------------- + *vimspector-watch-autocompletion* +Watch autocompletion ~ + +The watch prompt buffer has its 'omnifunc' set to a function that will +calculate completion for the current expression. This is trivially used with +'' (see ':help ins-completion'), or integrated with your +favourite completion system. The filetype in the buffer is set to +'VimspectorPrompt'. + +For YouCompleteMe, the following config works well: +> + let g:ycm_semantic_triggers = { + \ 'VimspectorPrompt': [ '.', '->', ':', '<' ] + } +< +------------------------------------------------------------------------------- + *vimspector-stack-traces* +Stack Traces ~ + +The stack trace window shows the state of each program thread. Threads which +are stopped can be expanded to show the stack trace of that thread. + +Often, but not always, all threads are stopped when a breakpoint is hit. The +status of a thread is show in parentheses after the thread's name. Where +supported by the underlying debugger, threads can be paused and continued +individually from within the Stack Trace window. + +A particular thread, highlighted with the 'CursorLine' highlight group is the +"focussed" thread. This is the thread that receives commands like "Stop In", +"Stop Out", "Continue" and "Pause" in the code window. The focussed thread can +be changed manually to "switch to" that thread. + +- Use '', or double-click with left mouse to expand/collapse a thread + stack trace, or use the WinBar button. + +- Use '', or double-click with left mouse on a stack frame to jump to it. + +- Use the WinBar or 'vimspector#PauseContinueThread()' to individually pause + or continue the selected thread. + +- Use the "Focus" WinBar button, '' or + 'vimspector#SetCurrentThread()' to set the "focussed" thread to the + currently selected one. If the selected line is a stack frame, set the + focussed thread to the thread of that frame and jump to that frame in the + code window. + + Image: stack trace (see reference [28]) + +The stack trace is represented by the buffer 'vimspector.StackTrace'. + +------------------------------------------------------------------------------- + *vimspector-program-output* +Program Output ~ + +- In the outputs window, use the WinBar to select the output channel. +- Alternatively, use ':VimspectorShowOutput '. Use command-line + completion to see the categories. +- The debuggee prints to the stdout channel. +- Other channels may be useful for debugging. + + Image: output window (see reference [29]) + +If the output window is closed, a new one can be opened with +':VimspectorShowOutput ' (use tab-completion - 'wildmenu' to see the +options). + +------------------------------------------------------------------------------- + *vimspector-console* +Console ~ + +The console window is a prompt buffer, where that's available, and can be used +as an interactive CLI for the debug adapter. Support for this varies amongst +adapters. + +- Enter insert mode to enter a command to evaluate. +- Alternatively, ':VimspectorEval '. Completion is available with + some debug adapters. +- Commit the request with '' +- The request and subsequent result are printed. + +NOTE: See also Watches above. + +If the output window is closed, a new one can be opened with +':VimspectorShowOutput Console'. + +------------------------------------------------------------------------------- + *vimspector-console-autocompletion* +Console autocompletion ~ + +The console prompt buffer has its 'omnifunc' set to a function that will +calculate completion for the current command/expression. This is trivially used +with '' (see ':help ins-completion'), or integrated with your +favourite completion system. The filetype in the buffer is set to +'VimspectorPrompt'. + +For YouCompleteMe, the following config works well: +> + let g:ycm_semantic_triggers = { + \ 'VimspectorPrompt': [ '.', '->', ':', '<' ] + } +< +------------------------------------------------------------------------------- + *vimspector-log-view* +Log View ~ + +The Vimspector log file contains a full trace of the communication between +Vimspector and the debug adapter. This is the primary source of diagnostic +information when something goes wrong that's not a Vim traceback. + +If you just want to see the Vimspector log file, use ':VimspectorToggleLog', +which will tail it in a little window (doesn't work on Windows). + +------------------------------------------------------------------------------- + *vimspector-closing-debugger* +Closing debugger ~ + +To close the debugger, use: + +- 'Reset' WinBar button +- ':VimspectorReset' when the WinBar is not available. +- 'call vimspector#Reset()' + +------------------------------------------------------------------------------- + *vimspector-terminate-debuggee* +Terminate debuggee ~ + +If the debuggee is still running when stopping or resetting, then some debug +adapters allow you to specify what should happen to it when finishing +debugging. Typically, the default behaviour is sensible, and this is what +happens most of the time. These are the defaults according to DAP: + +- If the request was 'launch': terminate the debuggee +- If the request was 'attach': don't terminate the debuggee + +Some debug adapters allow you to choose what to do when disconnecting. If you +wish to control this behaviour, use ':VimspectorReset' or call +"vimspector#Reset( { 'interactive': v:true } )". If the debug adapter offers a +choice as to whether or not to terminate the debuggee, you will be prompted to +choose. The same applies for 'vimspector#Stop()' which can take an argument: +"vimspector#Stop( { 'interactive': v:true } )". + +=============================================================================== + *vimspector-debug-profile-configuration* +Debug profile configuration ~ + +For an introduction to the configuration of '.vimspector.json', take a look at +the Getting Started section of the Vimspector website [1]. + +For full explanation, including how to use variables, substitutions and how to +specify exception breakpoints, see the docs [2]. + +The JSON configuration file allows C-style comments: + +- '// comment to end of line ...' +- '/* inline comment ... */' + +Current tested with the following debug adapters. + +------------------------------------------------------------------------------- + *vimspector-c-c-rust-etc.* +C, C++, Rust, etc. ~ + +- vscode-cpptools [30] + +- On macOS, I _strongly_ recommend using CodeLLDB instead for C and C++ + projects. It's really excellent, has fewer dependencies and doesn't open + console apps in another Terminal window. + +Example '.vimspector.json' (works with both 'vscode-cpptools' and +'lldb-vscode'. For 'lldb-vscode' replace the name of the adapter with +'lldb-vscode': + +- vscode-cpptools Linux/MacOS: +> + { + "configurations": { + "Launch": { + "adapter": "vscode-cpptools", + "configuration": { + "request": "launch", + "program": "", + "args": [ ... ], + "cwd": "", + "environment": [ ... ], + "externalConsole": true, + "MIMode": "" + } + }, + "Attach": { + "adapter": "vscode-cpptools", + "configuration": { + "request": "attach", + "program": "", + "MIMode": "" + } + } + ... + } + } +< +- vscode-cpptools Windows + +**_NOTE FOR WINDOWS USERS:_** You need to install 'gdb.exe'. I recommend using +'scoop install gdb'. Vimspector cannot use the visual studio debugger due to +licensing. +> + { + "configurations": { + "Launch": { + "adapter": "vscode-cpptools", + "configuration": { + "request": "launch", + "program": "", + "stopAtEntry": true + } + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-c-remote-debugging* +C++ Remote debugging ~ + +The cpptools documentation describes how to attach cpptools to gdbserver using +'miDebuggerAddress'. Note that when doing this you should use the '"request": +"attach"'. + +------------------------------------------------------------------------------- + *vimspector-c-remote-launch-attach* +C++ Remote launch and attach ~ + +If you're feeling fancy, checkout the reference guide [31] for an example of +getting Vimspector to remotely launch and attach. + +- CodeLLDB (MacOS) + +CodeLLDB is superior to vscode-cpptools in a number of ways on macOS at least. + +See Rust. + +- lldb-vscode (MacOS) + +An alternative is to to use 'lldb-vscode', which comes with llvm. Here's how: + +- Install llvm (e.g. with HomeBrew: 'brew install llvm') +- Create a file named + '/path/to/vimspector/gadgets/macos/.gadgets.d/lldb-vscode.json': +> + { + "adapters": { + "lldb-vscode": { + "variables": { + "LLVM": { + "shell": "brew --prefix llvm" + } + }, + "attach": { + "pidProperty": "pid", + "pidSelect": "ask" + }, + "command": [ + "${LLVM}/bin/lldb-vscode" + ], + "env": { + "LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY": "YES" + }, + "name": "lldb" + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-rust* +Rust ~ + +Rust is supported with any gdb/lldb-based debugger. So it works fine with +'vscode-cpptools' and 'lldb-vscode' above. However, support for rust is best in +'CodeLLDB' [32]. + +- './install_gadget.py --force-enable-rust' or ':VimspectorInstall CodeLLDB' +- Example: 'support/test/rust/vimspector_test' +> + { + "configurations": { + "launch": { + "adapter": "CodeLLDB", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/target/debug/vimspector_test" + } + } + } + } +< +- Docs: https://github.com/vadimcn/vscode-lldb/blob/master/MANUAL.md + +------------------------------------------------------------------------------- + *vimspector-python* +Python ~ + +- Python: debugpy [33] + +- Install with 'install_gadget.py --enable-python' or ':VimspectorInstall + debugpy', ideally requires a working compiler and the python development + headers/libs to build a C python extension for performance. + +- Full options: + https://github.com/microsoft/debugpy/wiki/Debug-configuration-settings + +**Migrating from 'vscode-python'**: change '"adapter": "vscode-python"' to +'"adapter": "debugpy"'. +> + { + "configurations": { + ": Launch": { + "adapter": "debugpy", + "configuration": { + "name": ": Launch", + "type": "python", + "request": "launch", + "cwd": "", + "python": "/path/to/python/interpreter/to/use", + "stopOnEntry": true, + "console": "externalTerminal", + "debugOptions": [], + "program": "" + } + } + ... + } + } +< +------------------------------------------------------------------------------- + *vimspector-python-remote-debugging* +Python Remote Debugging ~ + +In order to use remote debugging with debugpy, you have to connect Vimspector +directly to the application that is being debugged. This is easy, but it's a +little different from how we normally configure things. Specifically, you need +to: + +- Start your application with debugpy, specifying the '--listen' argument. + See the debugpy documentation [34] for details. + +- Use the built-in "multi-session" adapter. This just asks for the host/port + to connect to. For example: +> + { + "configurations": { + "Python Attach": { + "adapter": "multi-session", + "configuration": { + "request": "attach", + "pathMappings": [ + // mappings here (optional) + ] + } + } + } + } +< +See details of the launch configuration [35] for explanation of things like +'pathMappings'. + +Additional documentation, including how to do this when the remote machine can +only be contacted via SSH are provided by debugpy [36]. + +------------------------------------------------------------------------------- + *vimspector-python-remote-launch-attach* +Python Remote launch and attach ~ + +If you're feeling fancy, checkout the reference guide [31] for an example of +getting Vimspector to remotely launch and attach. + +------------------------------------------------------------------------------- + *vimspector-legacy-vscode-python* +Legacy: vscode-python ~ + +- No longer installed by default - please pass '--force-enable-python.legacy' + if you just want to continue using your working setup. +- vscode-python [37] +- NOTE: You must be running 'node' 10. See this issue [38] +> + { + "configurations": { + ": Launch": { + "adapter": "vscode-python", + "configuration": { + "name": ": Launch", + "type": "python", + "request": "launch", + "cwd": "", + "stopOnEntry": true, + "console": "externalTerminal", + "debugOptions": [], + "program": "" + } + } + ... + } + } +< +------------------------------------------------------------------------------- + *vimspector-tcl* +TCL ~ + +- TCL (TclProDebug) + +See my fork of TclProDebug [39] for instructions. + +------------------------------------------------------------------------------- + *vimspector-c* +C♯ ~ + +- C# - dotnet core + +Install with 'install_gadget.py --force-enable-csharp' or ':VimspectorInstall +netcoredbg' +> + { + "configurations": { + "launch - netcoredbg": { + "adapter": "netcoredbg", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/csharp.dll", + "args": [], + "stopAtEntry": true, + "cwd": "${workspaceRoot}" + } + } + } + } +< +- C# - mono + +Install with 'install_gadget.py --force-enable-csharp' or ':VimspectorInstall +vscode-mono-debug'. + +**_Known not to work._** +> + { + "configurations": { + "launch - mono": { + "adapter": "vscode-mono-debug", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/csharp.dll", + "args": [], + "cwd": "${workspaceRoot}", + "runtimeExecutable": "mono", + "runtimeArgs": [], + "env": [], + "externalConsole": false, + "console": "integratedTerminal" + } + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-go* +Go ~ + +- Go + +Requires: + +- 'install_gadget.py --enable-go' or ':VimspectorInstall vscode-go' +- Delve [40] installed, e.g. 'go get -u github.com/go-delve/delve/cmd/dlv' +- Delve to be in your PATH, or specify the 'dlvToolPath' launch option +> + { + "configurations": { + "run": { + "adapter": "vscode-go", + "configuration": { + "request": "launch", + "program": "${fileDirname}", + "mode": "debug", + "dlvToolPath": "$HOME/go/bin/dlv" + } + } + } + } +< +See the vscode-go docs for troubleshooting information [41] + +------------------------------------------------------------------------------- + *vimspector-php* +PHP ~ + +This uses the php-debug, see +https://marketplace.visualstudio.com/items?itemName=felixfbecker.php-debug + +Requires: + +- (optional) Xdebug helper for chrome https://chrome.google.com/webstore/deta + il/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc + +- 'install_gadget.py --force-enable-php' or ':VimspectorInstall + vscode-php-debug' + +- configured php xdebug extension +> + zend_extension=xdebug.so + xdebug.remote_enable=on + xdebug.remote_handler=dbgp + xdebug.remote_host=localhost + xdebug.remote_port=9000 +< + replace 'localhost' with the ip of your workstation. + +lazy alternative +> + zend_extension=xdebug.so + xdebug.remote_enable=on + xdebug.remote_handler=dbgp + xdebug.remote_connect_back=true + xdebug.remote_port=9000 +< +- .vimspector.json +> + { + "configurations": { + "Listen for XDebug": { + "adapter": "vscode-php-debug", + "configuration": { + "name": "Listen for XDebug", + "type": "php", + "request": "launch", + "port": 9000, + "stopOnEntry": false, + "pathMappings": { + "/var/www/html": "${workspaceRoot}" + } + } + }, + "Launch currently open script": { + "adapter": "vscode-php-debug", + "configuration": { + "name": "Launch currently open script", + "type": "php", + "request": "launch", + "program": "${file}", + "cwd": "${fileDirname}", + "port": 9000 + } + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-debug-web-application* +Debug web application ~ + +append 'XDEBUG_SESSION_START=xdebug' to your query string +> + curl "http://localhost?XDEBUG_SESSION_START=xdebug" +< +or use the previously mentioned Xdebug Helper extension (which sets a +'XDEBUG_SESSION' cookie) + +------------------------------------------------------------------------------- + *vimspector-debug-cli-application* +Debug cli application ~ +> + export XDEBUG_CONFIG="idekey=xdebug" + php +< +------------------------------------------------------------------------------- + *vimspector-javascript-typescript-etc.* +JavaScript, TypeScript, etc. ~ + +- Node.js + +Requires: + +- 'install_gadget.py --force-enable-node' + +- For installation, a Node.js environment that is < node 12. I believe this + is an incompatibility with gulp. Advice, use [nvm][] with 'nvm install + --lts 10; nvm use --lts 10; ./install_gadget.py --force-enable-node ...' + +- Options described here: + https://code.visualstudio.com/docs/nodejs/nodejs-debugging + +- Example: 'support/test/node/simple' +> + { + "configurations": { + "run": { + "adapter": "vscode-node", + "configuration": { + "request": "launch", + "protocol": "auto", + "stopOnEntry": true, + "console": "integratedTerminal", + "program": "${workspaceRoot}/simple.js", + "cwd": "${workspaceRoot}" + } + } + } + } +< +- Chrome + +This uses the chrome debugger, see https://marketplace.visualstudio.com/items?i +temName=msjsdiag.debugger-for-chrome. + +It allows you to debug scripts running inside chrome from within Vim. + +- './install_gadget.py --force-enable-chrome' or ':VimspectorInstall + debugger-for-chrome' +- Example: 'support/test/chrome' +> + { + "configurations": { + "launch": { + "adapter": "chrome", + "configuration": { + "request": "launch", + "url": "http://localhost:1234/", + "webRoot": "${workspaceRoot}/www" + } + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-java* +Java ~ + +Vimspector works well with the java debug server [42], which runs as a jdt.ls +(Java Language Server) plugin, rather than a standalone debug adapter. + +Vimspector is not in the business of running language servers, only debug +adapters, so this means that you need a compatible Language Server Protocol +editor plugin to use Java. I recommend YouCompleteMe [43], which has full +support for jdt.ls, and most importantly a trivial way to load the debug +adapter and to use it with Vimspector. + +------------------------------------------------------------------------------- + *vimspector-usage-with-youcompleteme* +Usage with YouCompleteMe ~ + +- Set up YCM for java [43]. + +- Get Vimspector to download the java debug plugin: 'install_gadget.py + --force-enable-java ' or ':VimspectorInstall + java-debug-adapter' + +- Configure Vimspector for your project using the 'vscode-java' adapter, + e.g.: +> + { + "configurations": { + "Java Attach": { + "adapter": "vscode-java", + "configuration": { + "request": "attach", + "hostName": "${host}", + "port": "${port}", + "sourcePaths": [ + "${workspaceRoot}/src/main/java", + "${workspaceRoot}/src/test/java" + ] + } + } + } + } +< +- Tell YCM to load the debugger plugin. This should be the 'gadgets/' + directory, not any specific adapter. e.g. in '.vimrc' +> + " Tell YCM where to find the plugin. Add to any existing values. + let g:ycm_java_jdtls_extension_path = [ + \ '' + \ ] +< +- Create a mapping, such as '' to start the debug server and + launch vimspector, e.g. in '~/.vim/ftplugin/java.vim': +> + let s:jdt_ls_debugger_port = 0 + function! s:StartDebugging() + if s:jdt_ls_debugger_port <= 0 + " Get the DAP port + let s:jdt_ls_debugger_port = youcompleteme#GetCommandResponse( + \ 'ExecuteCommand', + \ 'vscode.java.startDebugSession' ) + + if s:jdt_ls_debugger_port == '' + echom "Unable to get DAP port - is JDT.LS initialized?" + let s:jdt_ls_debugger_port = 0 + return + endif + endif + + " Start debugging with the DAP port + call vimspector#LaunchWithSettings( { 'DAPPort': s:jdt_ls_debugger_port } ) + endfunction + + nnoremap :call StartDebugging() +< +You can then use '' to start debugging rather than just ''. + +If you see "Unable to get DAP port - is JDT.LS initialized?", try running +':YcmCompleter ExecuteCommand vscode.java.startDebugSession' and note the +output. If you see an error like 'ResponseFailedException: Request failed: +-32601: No delegateCommandHandler for vscode.java.startDebugSession', make sure +that: _Your YCM jdt.ls is actually working, see the YCM docs [44] for +troubleshooting_ The YCM jdt.ls has had time to initialize before you start the +debugger * That 'g:ycm_java_jdtls_extension_path' is set in '.vimrc' or prior +to YCM starting + +For the launch arguments, see the vscode document [45]. + +------------------------------------------------------------------------------- + *vimspector-other-lsp-clients* +Other LSP clients ~ + +See this issue [46] for more background. + +------------------------------------------------------------------------------- + *vimspector-lua* +Lua ~ + +Lua is supported through local-lua-debugger-vscode [47]. This debugger uses +stdio to communicate with the running process, so calls to 'io.read' will cause +problems. + +- './install_gadget.py --enable-lua' or ':VimspectorInstall + local-lua-debugger-vscode' +- Examples: 'support/test/lua/simple' and 'support/test/lua/love' +> + { + "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json#", + "configurations": { + "lua": { + "adapter": "lua-local", + "configuration": { + "request": "launch", + "type": "lua-local", + "cwd": "${workspaceFolder}", + "program": { + "lua": "lua", + "file": "${file}" + } + } + }, + "luajit": { + "adapter": "lua-local", + "configuration": { + "request": "launch", + "type": "lua-local", + "cwd": "${workspaceFolder}", + "program": { + "lua": "luajit", + "file": "${file}" + } + } + }, + "love": { + "adapter": "lua-local", + "configuration": { + "request": "launch", + "type": "lua-local", + "cwd": "${workspaceFolder}", + "program": { + "command": "love" + }, + "args": ["${workspaceFolder}"] + } + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-other-servers* +Other servers ~ + +- Java - vscode-javac. This works, but is not as functional as Java Debug + Server. Take a look at this comment [48] for instructions. + +=============================================================================== + *vimspector-customisation* +Customisation ~ + +There is very limited support for customisation of the UI. + +------------------------------------------------------------------------------- + *vimspector-changing-default-signs* +Changing the default signs ~ + +Vimsector uses the following signs internally. If they are defined before +Vimsector uses them, they will not be replaced. So to customise the signs, +define them in your 'vimrc'. + +============================================================================= +| _Sign_ | _Description_ | _Priority_ | +============================================================================= +| 'vimspectorBP' | Line breakpoint | 9 | +----------------------------------------------------------------------------- +| 'vimspectorBPCond' | Conditional line breakpoint | 9 | +----------------------------------------------------------------------------- +| 'vimspectorBPDisabled' | Disabled breakpoint | 9 | +----------------------------------------------------------------------------- +| 'vimspectorPC' | Program counter (i.e. current line) | 200 | +----------------------------------------------------------------------------- +| 'vimspectorPCBP' | Program counter and breakpoint | 200 | +----------------------------------------------------------------------------- + + +The default symbols are the equivalent of something like the following: +> + sign define vimspectorBP text=\ ● texthl=WarningMsg + sign define vimspectorBPCond text=\ ◆ texthl=WarningMsg + sign define vimspectorBPDisabled text=\ ● texthl=LineNr + sign define vimspectorPC text=\ ▶ texthl=MatchParen linehl=CursorLine + sign define vimspectorPCBP text=●▶ texthl=MatchParen linehl=CursorLine +< +If the signs don't display properly, your font probably doesn't contain these +glyphs. You can easily change them by defining the sign in your vimrc. For +example, you could put this in your 'vimrc' to use some simple ASCII symbols: +> + sign define vimspectorBP text=o texthl=WarningMsg + sign define vimspectorBPCond text=o? texthl=WarningMsg + sign define vimspectorBPDisabled text=o! texthl=LineNr + sign define vimspectorPC text=\ > texthl=MatchParen + sign define vimspectorPCBP text=o> texthl=MatchParen +< +------------------------------------------------------------------------------- + *vimspector-sign-priority* +Sign priority ~ + +Many different plugins provide signs for various purposes. Examples include +diagnostic signs for code errors, etc. Vim provides only a single priority to +determine which sign should be displayed when multiple signs are placed at a +single line. If you are finding that other signs are interfering with +vimspector's (or vice-versa), you can customise the priority used by vimspector +by setting the following dictionary: +> + let g:vimspector_sign_priority = { + \ '': , + \ } +< +For example: +> + let g:vimspector_sign_priority = { + \ 'vimspectorBP': 3, + \ 'vimspectorBPCond': 2, + \ 'vimspectorBPDisabled': 1, + \ 'vimspectorPC': 999, + \ } +< +All keys are optional. If a sign is not customised, the default priority it +used (as shown above). + +See ':help sign-priority'. The default priority is 10, larger numbers override +smaller ones. + +------------------------------------------------------------------------------- + *vimspector-changing-default-window-sizes* +Changing the default window sizes ~ + +**_Please Note_**: This customisation API is **_unstable_**, meaning that it +may change at any time. I will endeavour to reduce the impact of this and +announce changes in Gitter. + +The following options control the default sizes of the UI windows (all of them +are numbers) + +- 'g:vimspector_sidebar_width' (default: 50 columns): The width in columns of + the left utility windows (variables, watches, stack trace) + +- 'g:vimspector_bottombar_height' (default 10 lines): The height in rows of + the output window below the code window. + +Example: +> + let g:vimspector_sidebar_width = 75 + let g:vimspector_bottombar_height = 15 +< +------------------------------------------------------------------------------- + *vimspector-changing-terminal-size* +Changing the terminal size ~ + +The terminal is typically created as a vertical split to the right of the code +window, and that window is re-used for subsequent terminal buffers. The +following control the sizing of the terminal window used for debuggee +input/output when using Vim's built-in terminal. + +- 'g:vimspector_code_minwidth' (default: 82 columns): Minimum number of + columns to try and maintain for the code window when splitting to create + the terminal window. + +- 'g:vimspector_terminal_maxwidth' (default: 80 columns): Maximum number of + columns to use for the terminal. + +- 'g:vimspector_terminal_minwidth' (default: 10 columns): Minimum number of + columns to use when it is not possible to fit + 'g:vimspector_terminal_maxwidth' columns for the terminal. + +That's a lot of options, but essentially we try to make sure that there are at +least 'g:vimspector_code_minwidth' columns for the main code window and that +the terminal is no wider than 'g:vimspector_terminal_maxwidth' columns. +'g:vimspector_terminal_minwidth' is there to ensure that there's a reasonable +number of columns for the terminal even when there isn't enough horizontal +space to satisfy the other constraints. + +Example: +> + let g:vimspector_code_minwidth = 90 + let g:vimspector_terminal_maxwidth = 75 + let g:vimspector_terminal_minwidth = 20 +< +------------------------------------------------------------------------------- + *vimspector-custom-mappings-while-debugging* +Custom mappings while debugging ~ + +It's useful to be able to define mappings only while debugging and remove those +mappings when debugging is complete. For this purpose, Vimspector provides 2 +'User' autocommands: + +- 'VimspectorJumpedToFrame' - triggered whenever a 'break' event happens, or + when selecting a stack from to jump to. This can be used to create (for + example) buffer-local mappings for any files opened in the code window. + +- 'VimspectorDebugEnded' - triggered when the debug session is terminated + (actually when Vimspector is fully reset) + +An example way to use this is included in 'support/custom_ui_vimrc'. In there, +these autocommands are used to create buffer-local mappings for any files +visited while debugging and to clear them when completing debugging. This is +particularly useful for commands like 'VimspectorBalloonEval' which only +make sense while debugging (and only in the code window). Check the commented +section 'Custom mappings while debugging'. + +NOTE: This is a fairly advanced feature requiring some nontrivial vimscript. +It's possible that this feature will be incorporated into Vimspector in future +as it is a common requirement. + +------------------------------------------------------------------------------- + *vimspector-advanced-ui-customisation* +Advanced UI customisation ~ + +**_Please Note_**: This customisation API is **_unstable_**, meaning that it +may change at any time. I will endeavour to reduce the impact of this and +announce changes in Gitter. + +The above customisation of window sizes is limited intentionally to keep things +simple. Vimspector also provides a way for you to customise the UI without +restrictions, by running a 'User' autocommand just after creating the UI or +opening the terminal. This requires you to write some vimscript, but allows you +to do things like: + +- Hide a particular window or windows +- Move a particular window or windows +- Resize windows +- Have multiple windows for a particular buffer (say, you want 2 watch + windows) +- etc. + +You can essentially do anything you could do manually by writing a little +vimscript code. + +The 'User' autocommand is raised with 'pattern' set with the following values: + +- 'VimspectorUICreated': Just after setting up the UI for a debug session +- 'VimspectorTerminalOpened': Just after opening the terminal window for + program input/output. + +The following global variable is set up for you to get access to the UI +elements: 'g:vimspector_session_windows'. This is a 'dict' with the following +keys: + +- 'g:vimspector_session_windows.tagpage': The tab page for the session +- 'g:vimspector_session_windows.variables': Window ID of the variables + window, containing the 'vimspector.Variables' buffer. +- 'g:vimspector_session_windows.watches': Window ID of the watches window, + containing the 'vimspector.Watches' buffer. +- 'g:vimspector_session_windows.stack_trace': Window ID of the stack trade + window containing the 'vimspector.StackTrace' buffer. +- 'g:vimspector_session_windows.code': Window ID of the code window. +- 'g:vimspector_session_windows.output': Window ID of the output window. + +In addition, the following key is added when triggering the +'VimspectorTerminalOpened' event: + +- 'g:vimspector_session_windows.terminal': Window ID of the terminal window + +------------------------------------------------------------------------------- + *vimspector-customising-winbar* +Customising the WinBar ~ + +You can even customise the WinBar buttons by simply running the usual 'menu' +(and 'unmenu') commands. + +By default, Vimspector uses something a bit like this: +> + nnoremenu WinBar.■\ Stop :call vimspector#Stop( { 'interactive': v:false } ) + nnoremenu WinBar.▶\ Cont :call vimspector#Continue() + nnoremenu WinBar.▷\ Pause :call vimspector#Pause() + nnoremenu WinBar.↷\ Next :call vimspector#StepOver() + nnoremenu WinBar.→\ Step :call vimspector#StepInto() + nnoremenu WinBar.←\ Out :call vimspector#StepOut() + nnoremenu WinBar.⟲: :call vimspector#Restart() + nnoremenu WinBar.✕ :call vimspector#Reset( { 'interactive': v:false } ) +< +If you prefer a different layout or if the unicode symbols don't render +correctly in your font, you can customise this in the 'VimspectorUICreated' +autocommand, for example: +> + func! CustomiseUI() + call win_gotoid( g:vimspector_session_windows.code ) + " Clear the existing WinBar created by Vimspector + nunmenu WinBar + " Cretae our own WinBar + nnoremenu WinBar.Kill :call vimspector#Stop( { 'interactive': v:true } ) + nnoremenu WinBar.Continue :call vimspector#Continue() + nnoremenu WinBar.Pause :call vimspector#Pause() + nnoremenu WinBar.Step\ Over :call vimspector#StepOver() + nnoremenu WinBar.Step\ In :call vimspector#StepInto() + nnoremenu WinBar.Step\ Out :call vimspector#StepOut() + nnoremenu WinBar.Restart :call vimspector#Restart() + nnoremenu WinBar.Exit :call vimspector#Reset() + endfunction + + augroup MyVimspectorUICustomistaion + autocmd! + autocmd User VimspectorUICreated call s:CustomiseUI() + augroup END +< +------------------------------------------------------------------------------- + *vimspector-example* +Example ~ + +There is some example code in 'support/custom_ui_vimrc' showing how you can use +the window IDs to modify various aspects of the UI using some basic vim +commands, primarily 'win_gotoid' function and the 'wincmd' ex command. + +To try this out 'vim -Nu support/custom_ui_vimrc '. + +Here's a rather smaller example. A simple way to use this is to drop it into a +file named 'my_vimspector_ui.vim' in '~/.vim/plugin' (or paste into your +'vimrc'): +> + " Set the basic sizes + let g:vimspector_sidebar_width = 80 + let g:vimspector_code_minwidth = 85 + let g:vimspector_terminal_minwidth = 75 + + function! s:CustomiseUI() + " Customise the basic UI... + + " Close the output window + call win_gotoid( g:vimspector_session_windows.output ) + q + endfunction + + function s:SetUpTerminal() + " Customise the terminal window size/position + " For some reasons terminal buffers in Neovim have line numbers + call win_gotoid( g:vimspector_session_windows.terminal ) + set norelativenumber nonumber + endfunction + + augroup MyVimspectorUICustomistaion + autocmd! + autocmd User VimspectorUICreated call s:CustomiseUI() + autocmd User VimspectorTerminalOpened call s:SetUpTerminal() + augroup END +< +=============================================================================== + *vimspector-faq* +FAQ ~ + +1. Q: Does it work? A: Yeah. It's a bit unpolished. + +2. Q: Does it work with _this_ language? A: Probably, but it won't + necessarily be easy to work out what to put in the '.vimspector.json'. As + you can see above, some of the servers aren't really editor agnostic, and + require very-specific unique handling. + +3. How do I stop it starting a new Terminal.app on macOS? See this comment + [49] + +4. Can I specify answers to the annoying questions about exception + breakpoints in my '.vimspector.json' ? Yes, see here [23]. + +5. Do I have to specify the file to execute in '.vimspector.json', or could + it be the current vim file? You don't need to. You can specify $file for + the current active file. See here [20] for complete list of replacements + in the configuration file. + +6. You allow comments in '.vimspector.json', but Vim highlights these as + errors, do you know how to make this not-an-error? Yes, put this in + '~/.vim/after/syntax/json.vim': +> + syn region jsonComment start="/\*" end="\*/" + hi link jsonCommentError Comment + hi link jsonComment Comment +< +1. What is the difference between a 'gadget' and an 'adapter'? A gadget is + something you install with ':VimspectorInstall' or 'install_gadget.py', + an 'adapter' is something that Vimspector talks to (actually it's the + Vimspector config describing that thing). These are _usually_ one-to-one, + but in theory a single gadget can supply multiple 'adapter' configs. + Typically this happens when a 'gadget' supplies different 'adapter' + config for, say remote debugging, or debugging in a container, etc. + +2. The signs and winbar display funny symbols. How do I fix them? See this + and this + +3. What's this telemetry stuff all about? Are you sending my data to evil + companies? Debug adapters (for some reason) send telemetry data to + clients. Vimspector simply displays this information in the output + window. It _does not_ and _will not ever_ collect, use, forward or + otherwise share any data with any third parties. + +=============================================================================== + *vimspector-references* +References ~ + +[1] https://puremourning.github.io/vimspector-web/ +[2] https://puremourning.github.io/vimspector/configuration.html +[3] https://github.com/puremourning/vimspector/workflows/Build/badge.svg?branch=master +[4] https://gitter.im/vimspector/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge +[5] https://badges.gitter.im/vimspector/Lobby.svg +[6] https://puremourning.github.io/vimspector-web/img/vimspector-overview.png +[7] https://asciinema.org/a/VmptWmFHTNLPfK3DVsrR2bv8S +[8] https://asciinema.org/a/VmptWmFHTNLPfK3DVsrR2bv8S.svg +[9] https://asciinema.org/a/1wZJSoCgs3AvjkhKwetJOJhDh +[10] https://asciinema.org/a/1wZJSoCgs3AvjkhKwetJOJhDh.svg +[11] https://github.com/go-delve/delve +[12] https://github.com/puremourning/vimspector/wiki/languages +[13] https://asciinema.org/a/Hfu4ZvuyTZun8THNen9FQbTay +[14] https://asciinema.org/a/Hfu4ZvuyTZun8THNen9FQbTay.svg +[15] https://trello.com/b/yvAKK0rD/vimspector +[16] http://www.apache.org/licenses/LICENSE-2.0 +[17] https://greyhoundrescuewales.co.uk +[18] https://www.cancerresearchuk.org +[19] https://iccf.nl +[20] https://puremourning.github.io/vimspector/configuration.html#replacements-and-variables +[21] https://puremourning.github.io/vimspector/configuration.html#configuration-selection +[22] €mappings +[23] https://puremourning.github.io/vimspector/configuration.html#exception-breakpoints +[24] https://puremourning.github.io/vimspector-web/img/vimspector-code-window.png +[25] https://puremourning.github.io/vimspector-web/img/vimspector-locals-window.png +[26] https://puremourning.github.io/vimspector-web/img/vimspector-variable-eval-hover.png +[27] https://puremourning.github.io/vimspector-web/img/vimspector-watch-window.png +[28] https://puremourning.github.io/vimspector-web/img/vimspector-callstack-window.png +[29] https://puremourning.github.io/vimspector-web/img/vimspector-output-window.png +[30] https://github.com/Microsoft/vscode-cpptools +[31] https://puremourning.github.io/vimspector/configuration.html#remote-debugging-support +[32] https://github.com/vadimcn/vscode-lldb#features +[33] https://github.com/microsoft/debugpy +[34] https://github.com/microsoft/debugpy#debugpy-cli-usage +[35] https://github.com/microsoft/debugpy/wiki/Debug-configuration-settings +[36] https://github.com/microsoft/debugpy/wiki/Debugging-over-SSH +[37] https://github.com/Microsoft/vscode-python +[38] https://github.com/puremourning/vimspector/issues/105 +[39] https://github.com/puremourning/TclProDebug +[40] https://github.com/go-delve/delve/tree/master/Documentation/installation +[41] https://github.com/golang/vscode-go/blob/master/docs/debugging.md#troubleshooting +[42] https://github.com/Microsoft/java-debug +[43] https://github.com/ycm-core/YouCompleteMe#java-semantic-completion +[44] https://github.com/ycm-core/YouCompleteMe#troubleshooting +[45] https://code.visualstudio.com/docs/java/java-debugging +[46] https://github.com/puremourning/vimspector/issues/3 +[47] https://github.com/tomblind/local-lua-debugger-vscode +[48] https://github.com/puremourning/vimspector/issues/3#issuecomment-576916076 +[49] https://github.com/puremourning/vimspector/issues/90#issuecomment-577857322 + +vim: ft=help From 244d7d8fdfb073c8befbc777836b675459aae002 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Mon, 22 Mar 2021 14:45:21 +0000 Subject: [PATCH 29/73] Add the reference material to the vim doc too --- README.md | 2 +- doc/vimspector-ref.txt | 1085 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1086 insertions(+), 1 deletion(-) create mode 100644 doc/vimspector-ref.txt diff --git a/README.md b/README.md index 952d07f..6979e44 100644 --- a/README.md +++ b/README.md @@ -151,7 +151,7 @@ runtime dependencies). They are categorised by their level of support: | C, C++, Rust etc. | Tested | `--all` or `--enable-c` (or cpp) | vscode-cpptools | mono-core | | Rust, C, C++, etc. | Supported | `--force-enable-rust` | CodeLLDB | Python 3 | | Python | Tested | `--all` or `--enable-python` | debugpy | Python 2.7 or Python 3 | -| Go | Tested | `--enable-go` | vscode-go | Go, [Delve][] | +| Go | Tested | `--enable-go` | vscode-go | Node, Go, [Delve][] | | TCL | Supported | `--all` or `--enable-tcl` | tclpro | TCL 8.5 | | Bourne Shell | Supported | `--all` or `--enable-bash` | vscode-bash-debug | Bash v?? | | Lua | Supported | `--all` or `--enable-lua` | local-lua-debugger-vscode | Node >=12.13.0, Npm, Lua interpreter | diff --git a/doc/vimspector-ref.txt b/doc/vimspector-ref.txt new file mode 100644 index 0000000..367d409 --- /dev/null +++ b/doc/vimspector-ref.txt @@ -0,0 +1,1085 @@ +*vimspector-ref* + +=============================================================================== +Contents ~ + + 1. Introduction |vimspector-ref-introduction| + 2. title: Configuration |vimspector-ref-title-configuration| + 3. Concepts |vimspector-ref-concepts| + 1. Debug adapter configuration |vimspector-ref-debug-adapter-configuration| + 2. Debug profile configuration |vimspector-ref-debug-profile-configuration| + 3. Replacements and variables |vimspector-ref-replacements-variables| + 1. The splat operator |vimspector-ref-splat-operator| + 2. Default values |vimspector-ref-default-values| + 3. Coercing Types |vimspector-ref-coercing-types| + 4. Configuration Format |vimspector-ref-configuration-format| + 5. Files and locations |vimspector-ref-files-locations| + 6. Adapter configurations |vimspector-ref-adapter-configurations| + 7. Debug configurations |vimspector-ref-debug-configurations| + 1. Configuration selection |vimspector-ref-configuration-selection| + 1. Specifying a default configuration |vimspector-ref-specifying-default-configuration| + 2. Preventing automatic selection |vimspector-ref-preventing-automatic-selection| + 2. Exception Breakpoints |vimspector-ref-exception-breakpoints| + 8. Predefined Variables |vimspector-ref-predefined-variables| + 9. Remote Debugging Support |vimspector-ref-remote-debugging-support| + 1. Python (debugpy) Example |vimspector-ref-python-example| + 2. C-family (gdbserver) Example |vimspector-ref-c-family-example| + 3. Docker Example |vimspector-ref-docker-example| + 10. Appendix: Configuration file format |vimspector-ref-appendix-configuration-file-format| + 11. Appendix: Editor configuration |vimspector-ref-appendix-editor-configuration| + 12. References |vimspector-ref-references| + +=============================================================================== + *vimspector-ref-introduction* +Introduction ~ + +=============================================================================== + *vimspector-ref-title-configuration* +title: Configuration ~ + +This document defines the supported format for project and adapter +configuration for Vimspector. + +- Concepts + + - Debug adapter configuration + - Debug profile configuration + - Replacements and variables + - The splat operator + - Default values + - Coercing Types + +- Configuration Format +- Files and locations +- Adapter configurations +- Debug configurations + + - Configuration selection + + - Specifying a default configuration + - Preventing automatic selection + + - Exception Breakpoints + +- Predefined Variables +- Remote Debugging Support + + - Python (debugpy) Example + - C-family (gdbserver) Example + - Docker Example + +- Appendix: Configuration file format +- Appendix: Editor configuration + +=============================================================================== + *vimspector-ref-concepts* +Concepts ~ + +As Vimspector supports debugging arbitrary projects, you need to tell it a few +details about what you want to debug, and how to go about doing that. + +In order to debug things, Vimspector requires a Debug Adapter which bridges +between Vimspector and the actual debugger tool. Vimspector can be used with +any debug adapter that implements the Debug Adapter Protocol [1]. + +For each debugging session, you provide a _debug configuration_ which includes +things like: + +- The debug adapter to use (and possibly how to launch and configure it). +- How to connect to the remote host, if remote debugging. +- How to launch or attach to your process. + +Along with optional additional configuration for things like: + +- Exception breakpoints + +------------------------------------------------------------------------------- + *vimspector-ref-debug-adapter-configuration* +Debug adapter configuration ~ + +The adapter to use for a particular debug session can be specified inline +within the _debug configuration_, but more usually the debug adapter is defined +separately and just referenced from the _debug configuration_. + +The adapter configuration includes things like: + +- How to launch or connect to the debug adapter +- How to configure it for PID attachment +- How to set up remote debugging, such as how to launch the process remotely + (for example, under 'gdbserver', 'ptvsd', etc.) + +------------------------------------------------------------------------------- + *vimspector-ref-debug-profile-configuration* +Debug profile configuration ~ + +Projects can have many different debug profiles. For example you might have all +of the following, for a given source tree: + +- Remotely launch c++ the process, and break on 'main' +- Locally Python test and break exception +- Remotely attach to a c++ process +- Locally launch a bash script +- Attach to a JVM listening on a port + +Each of these represents a different use case and a different _debug +configuration_. As mentioned above, a _debug configuration_ is essentially: + +- The adapter to use + +- The type of session (launch or attach), and whether or not to do it + remotely + +- The configuration to pass to the adapter in order to launch or attach to + the process. + +The bulk of the configuration is the last of these, which comprises +adapter-specific options, as the Debug Adapter Protocol does not specify any +standard for launch or attach configuration. + +------------------------------------------------------------------------------- + *vimspector-ref-replacements-variables* +Replacements and variables ~ + +Vimspector _debug configuration_ is intended to be as general as possible, and +to be committed to source control so that debugging your applications becomes a +simple, quick and pain-free habit (e.g. answering questions like "what happens +if..." with "just hit F5 and step through!"). + +Therefore it's important to abstract certain details, like runtime and +build-time paths, and to parameterise the _debug configuration_. Vimspector +provides a simple mechanism to do this with '${replacement}' style +replacements. + +The values available within the '${...}' are defined below, but in summary the +following are supported: + +- Environment variables, such as '${PATH}' +- Predefined variables, such as '${workspaceRoot}', '${file}' etc. +- Configuration-defined variables, either provided by the adapter + configuration or debug configuration, or from running a simple shell + command. +- Anything else you like - the user will be asked to provide a value. + +If the latter 2 are confusing, for now, suffice to say that they are how +Vimspector allows parameterisation of debug sessions. The [Vimspector +website][website-getting-started] has a good example of where this sort of +thing is useful: accepting the name of a test to run. + +But for now, consider the following example snippet: +> + { + "configurations": { + "example-debug-configuration": { + // This is a single-line comment explaining the purpose + "adapter": "example-adapter-name", + "variables": { + "SecretToken": { // Variables should start with upper-case letters + "shell" : [ "cat", "${HOME}/.secret_token" ] + } + }, + "configuration": { + "request": "launch" /* or it could be "attach" */, + "program": [ + "${fileBasenameNoExtension}", + "-c", "configuration_file.cfg", + "-u", "${USER}", + "--test-identifier", "${TestIdentifier}", + "--secret-token", "${SecretToken}" + ] + }, + "breakpoints": { + "exception": { + "caught": "", + "uncaught": "Y" + } + } + } + } + } +< +In this (fictitious) example the 'program' launch configuration item contains +the following variable substitutions: + +- '${fileBasenameNoExtension}' - this is a Predefined Variable, set by + Vimspector to the base name of the file that's opened in Vim, with its + extension removed ('/path/to/xyz.cc' -> 'xyz'). + +- '${USER}' - this refers to the Environment Variable 'USER'. + +- '${TestIdentifier}' - this variable is not defined, so the user is asked to + provide a value interactively when starting debugging. Vimspector remembers + what they said and provides it as the default should they debug again. + +- '${SecretToken}' - this variable is provided by the configuration's + 'variables' block. Its value is taken from the 'strip''d result of running + the shell command. Note these variables can be supplied by both the debug + and adapter configurations and can be either static strings or shell + commands. + +------------------------------------------------------------------------------- + *vimspector-ref-splat-operator* +The splat operator ~ + +Often we want to create a single '.vimspector.json' entry which encompasses +many use cases, as it is tedious to write every use case/start up option in +JSON. This is why we have the replacement variables after all. + +Frequently debug adapters request command arguments as a JSON array, for +example: +> + "args": [ "one", "two three", "four" ], +< +To help with this sort of case, Vimspector supports a 'splat' operator for +replacement variables operating within lists. The syntax is: '"*${var}', which +means roughly "splice the contents of '${var}' into the list at this position". +'${var}' is parsed like a shell command (using python's 'shlex' parser) and +each word is added as a list item. + +For example: +> + "args": [ "*${CommandLineArgs}" ] +< +This would: + +- Ask the user to provide the variable 'CommandLineArgs'. Let's say they + entered 'one "two three" four' +- Split 'CommandLineArgs' like shell arguments: 'one', 'two three' and 'four' +- Set 'args' in the settings dict to: '[ "one", "two three", "four" ]' + +You can also combine with static values: +> + "args": [ "First", "*${CommandLineArgs}", "Last" ] +< +This would yield the intuitive result: '[ "First", "one", "two three", "four", +"Last" ]' + +------------------------------------------------------------------------------- + *vimspector-ref-default-values* +Default values ~ + +You can specify replacements with default values. In this case if the user has +not specified a value, they are prompted but with the default value +pre-populated, allowing them to just press return to accept the default. + +The syntax is '${variableName:default value}'. The default value can contain +any character, but to include a '}' you must escape it with a backslash. To +include a backslash in the JSON you must write '\\', as in: +> + { "key": "${value:default {\\} stuff}" } +< +The default value can also be a replacement variable. However, this _must_ be a +variable that's already defined, such as one of the predefined variables, or +one specified in a 'variables' block. In order to reference them, you _must_ +use '${var}' syntax and you _must_ escape the closing '}'. For example, the is +a common and useful case: +> + { + "configuration": { + "program": "${script:${file\\}}" + } + } +< +This will prompt the user to specify 'script', but it will default to the path +to the current file. + +------------------------------------------------------------------------------- + *vimspector-ref-coercing-types* +Coercing Types ~ + +Sometimes, you want to provide an option for a boolean parameter, or want to +allow the user to specify more than just strings. Vimspector allows you to do +this, ensuring that the resulting JSON is valid. This is done by interpreting a +value as a JSON string and substituting the resulting JSON value in its place. + +This is easier to explain with an example. Let's say we want to offer the +ability to break on entry, as an option for the user. The launch configuration +requires 'stopOnEntry' to be a bool. This doesn't work: +> + "stopOnEntry": "${StopOnEntry}" +< +The reason is that if the user types 'true', the resulting object is: +> + "stopOnEntry": "true" +< +The problem being that is a string, not a boolean. So Vimspector allows you to +re-interpret the string as a JSON value and use that instead. To do this, add +'#json' to the key's name. You can even add a default, like this: +> + "stopOnEntry#json": "${stopOnEntry:true}" +< +If the user accepts the default, the resulting string '"true"' is coerced to a +JSON value 'true', and the suffix is stripped fom the key, resulting in the +following: +> + "stopOnEntry#json": true +< +Which is what we need. + +If you happen to have a key that already ends in '#json' (unlikely!), then you +can force Vimspector to treat the value as a string by appending '#s', as in: +> + "unlikelyKeyName#json#s": "this is a string, not JSON data" +< +**_Advanced usage:_** + +The most common usage for this is for number and bool types, but it works for +objects too. If you want to be able to specify a whole object (e.g. a whole +'env' dict), then you can do that too: +> + "env#json": "${Environment:{\\}}" +< +The default value here is '{}' (note the '}' must be escaped!). The user can +then enter something like '{ "MYVAR": "MyValue", "OTHER": "Other" }' and the +resulting object would be: +> + "env": { + "MYVAR": "MyValue", + "OTHER": "Other" + } +< +It also works for lists, though the splat operator is usually more convenient +for that. + +=============================================================================== + *vimspector-ref-configuration-format* +Configuration Format ~ + +All Vimspector configuration is defined in a JSON object. The complete +specification of this object is available in the JSON Schema [2], but the basic +format for the configuration object is: +> + { + "adapters": { }, + "configurations": { } + } +< +The 'adapters' key is actually optional, as '' can be +embedded within '', though this is not recommended usage. + +=============================================================================== + *vimspector-ref-files-locations* +Files and locations ~ + +The above configuration object is constructed from a number of configuration +files, by merging objects in a specified order. + +In a minimal sense, the only file required is a '.vimspector.json' file in the +root of your project which defines the full configuration object [2], but it is +usually useful to split the 'adapters' configuration into a separate file (or +indeed one file per debug adapter). + +The following sections describe the files that are read and use the following +abbreviations: + +- '' means the path to the Vimspector installation (such as + '$HOME/.vim/pack/vimspector/start/vimspector') + +- '' is either 'macos' or 'linux' depending on the host operating system. + +- '' is the Vim filetype. Where multiple filetypes are in effect, + typically all filetypes are checked. + +=============================================================================== + *vimspector-ref-adapter-configurations* +Adapter configurations ~ + +Vimspector reads a series of files to build the 'adapters' object. The +'adapters' objects are merged in such a way that a definition for an adapter +named 'example-adapter' in a later file _completely replaces_ a previous +definition. + +- '/gadgets//.gadgets.json' - the file written by + 'install_gadget.py' and not usually edited by users. + +- '/gadgets//.gadgets.d/*.json' (sorted alphabetically). + These files are user-supplied and override the above. + +- The first such '.gadgets.json' file found in all parent directories of the + file open in Vim. + +- The '.vimspector.json' and any filetype-specific configurations (see below) + +In all cases, the required format is: +> + { + "$schema": "https://puremourning.github.io/vimspector/schema/gadgets.schema.json#", + "adapters": { + "": { + + } + } + } +< +Each adapters block can define any number of adapters. As mentioned, if the +same adapter name exists in multiple files, the last one read takes precedence +and _completely replaces_ the previous configuration. In particular that means +you can't just override one option, you have to override the whole block. + +Adapter configurations are re-read at the start of each debug session. + +The specification for the gadget object is defined in the [gadget schema][]. + +=============================================================================== + *vimspector-ref-debug-configurations* +Debug configurations ~ + +There are two locations for debug configurations for a project: + +- '/configurations///*.json' +- '.vimspector.json' in the project source + +Typically, the debug configurations are read from '.vimspector.json'. The file +is found (like '.gadgets.json' above) by recursively searching up the directory +hierarchy from the directory of the file open in Vim. The first file found is +read and no further searching is done. + +Only a single '.vimspector.json' is read. If one is found, the location of this +file is used for '${workspaceRoot}' and other workspace-relative paths. + +In addition, users can create filetype-specific configurations in the +Vimspector installation directory. This can be useful where the parameters for +the debug session for a particular filetype are always known in advance, or can +always be entered by the user. This allows for debugging to "just work" without +any modification to the project source (no need to add a '.vimspector.json'). +In this case, the '${workspaceRoot}' and workspace-relative paths are +interpreted relative to the file open in Vim. This isn't ideal, but there is no +other obvious way to default this variable. + +As with gadgets, any debug configurations appearing within '.vimspector.json' +override any that appear in the common configuration dir. + +Debug configurations are re-read at the start of each debug session, so +modifications are picked up without any restarts of Vim. + +The specification for the gadget object is defined in the schema [2], but a +typical example looks like this: +> + { + "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json#", + "configurations": { + "": { + "adapter": "", + "configuration": { + "request": "", + + } + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-ref-configuration-selection* +Configuration selection ~ + +When starting debugging, you can specify which debug configuration to launch +with "call vimspector#LaunchWithSettings( #{ configuration: 'name here' } )". + +Otherwise, if there's only one configuration found, Vimspector will use that +configuration, unless it contains a key '"autoselect": false'. + +If multiple debug configurations are found, and no explicit configuration was +selected on Launch, the user is prompted to select a configuration, unless a +single debug configuration is found with a key '"default": true'. + +------------------------------------------------------------------------------- + *vimspector-ref-specifying-default-configuration* +Specifying a default configuration ~ + +As noted, you can specify a default configuration with '"default": true': +> + { + "configurations": { + "use this one": { + "default": true, + "adapter": " ... ", + "configuation": { + // ... + } + }, + "don't use this one": { + // ... + } + } + } +< +If multiple configurations are found with 'default' set to 'true', then the +user is prompted anyway. + +------------------------------------------------------------------------------- + *vimspector-ref-preventing-automatic-selection* +Preventing automatic selection ~ + +If you don't want a configuration to be selected automatically, then set +'"autoselect": false'. This particularly useful for configurations in the +central (as opposed to project-local) directory. For example: +> + "configurations": { + "Don't use this by default!": { + "autoselect": false, + "adapter": " ... ", + "configuation": { + // ... + } + } + } +< +Setting 'autoselect' to 'false' overrides setting 'default' to 'true'. + +------------------------------------------------------------------------------- + *vimspector-ref-exception-breakpoints* +Exception Breakpoints ~ + +Debug adapters have arbitrary configuration for exception breakpoints. Normally +this is presented as a series of question to the user on starting the debug +session. The question includes the name of the exception breakpoint option, the +default and the list of valid responses (usually 'Y' or 'N'). + +You can pre-configure the answers to these questions in the 'breakpoints' +section of the debug configuration. For each question, take the name provided +and configure the response 'exception' mapping in the 'breakpoints' mapping. If +the configured response is empty string, the debug adapter default will be +used. + +Referring to the above example, the following tells the debug adapter to use +the default value for 'caught' exceptions and to break on 'uncaught' exception: +> + { + "configurations": { + "example-debug-configuration": { + "adapter": "example-adapter-name", + "breakpoints": { + "exception": { + "caught": "", + "uncaught": "Y" + } + }, + ... +< +The keys in the 'exception' mapping are what Vimspector includes in the prompt. +For example, when prompted with the following: +> + cpp_throw: Break on C++: on throw (Y/N/default: Y)? +< +The exception breakpoint "type" is 'cpp_throw' and the default is 'Y'. + +Similarly: +> + cpp_catch: Break on C++: on catch (Y/N/default: N)? +< +The exception breakpoint "type" is 'cpp_catch' and the default is 'N'. + +Use the following to set the values in configuration and not get asked: +> + "configurations": { + "example-debug-configuration": { + "adapter": "example-adapter-name", + "breakpoints": { + "exception": { + "cpp_throw": "Y", + "cpp_catch": "Y" + } + }, +< +To just accept the defaults for these exception breakpoint types, don't specify +a value, as in : +> + "configurations": { + "example-debug-configuration": { + "adapter": "example-adapter-name", + "breakpoints": { + "exception": { + "cpp_throw": "", + "cpp_catch": "" + } + }, +< +=============================================================================== + *vimspector-ref-predefined-variables* +Predefined Variables ~ + +The following variables are provided: + +- '${dollar}' - has the value '$', can be used to enter a literal dollar +- '$$' - a literal dollar +- '${workspaceRoot}' - the path of the folder where '.vimspector.json' was + found +- '${workspaceFolder}' - the path of the folder where '.vimspector.json' was + found +- '${gadgetDir}' - path to the OS-specific gadget dir ('/gadgets/') +- '${file}' - the current opened file +- '${relativeFile}' - the current opened file relative to 'workspaceRoot' +- '${fileBasename}' - the current opened file's 'basename' +- '${fileBasenameNoExtension}' - the current opened file's 'basename' with no + file extension +- '${fileDirname}' - the current opened file's 'dirname' +- '${fileExtname}' - the current opened file's extension +- '${cwd}' - the current working directory of the active window on launch +- '${unusedLocalPort}' - an unused local TCP port + +=============================================================================== + *vimspector-ref-remote-debugging-support* +Remote Debugging Support ~ + +Vimspector has in-built support for executing remote debuggers (such as +'gdbserver', 'debugpy', 'llvm-server' etc.). This is useful for environments +where the development is done on one host and the runtime is some other host, +account, container, etc. + +In order for it to work, you have to set up paswordless SSH between the local +and remote machines/accounts. Then just tell Vimspector how to remotely launch +and/or attach to the app. + +This is presented as examples with commentary, as it's a fairly advanced/niche +case. If you're not already familiar with remote debugging tools (such as +gdbserver) or not familiar with ssh or such, you might need to independently +research that. + +Vimspector's tools are intended to automate your existing process for setting +this up rather than to offer batteries-included approach. Ultimately, all +Vimspector is going to do is run your commands over SSH, or docker, and +co-ordinate with the adapter. + +------------------------------------------------------------------------------- + *vimspector-ref-python-example* +Python (debugpy) Example ~ + +Here is some examples using the Vimspector built-in remote support (using SSH) +to remotely launch and attach a python application and connect to it using +debugpy. + +The usage pattern is to hit '', enter 'host' (the host where your app +runs), 'account' (the account it runs under), and 'port' (a port that will be +opened on the remote host). Vimspector also supports exec'ing into Docker run +containers with 'container' (the container name or id your app is running in). +Vimspector then orchestrates the various tools to set you up. +> + { + "adapters": { + "python-remote": { + "port": "${port}", + "host": "${host}", + "launch": { + "remote": { + "host": "${host}", // Remote host to ssh to (mandatory if not using container) + "account": "${account}", // User to connect as (optional) + + // Optional.... Manual additional arguments for ssh + // "ssh": { + // "args": [ "-o", "StrictHostKeyChecking=no" ] + // }, + + // Command to launch the debugee and attach the debugger; + // %CMD% replaced with the remote-cmdLine configured in the launch + // configuration. (mandatory) + "runCommand": [ + "python", "-m", "debugpy", + "--listen", "0.0.0.0:${port}", + "--wait-for-client", + "%CMD%" + ] + + // Optional alternative to runCommand (if you need to run multiple + // commands) + // "runCommands": [ + // [ /* first command */ ], + // [ /* second command */ ] + // ] + + } + + // optional delay to wait after running runCommand(s). This is often + // needed because of the way docker handles TCP, or if you're using some + // wrapper (e.g. to start the JVM) + // "delay": "1000m" // format as per :help sleep + }, + "attach": { + "remote": { + "host": "${host}", // Remote host to ssh to (mandatory if not using container) + "account": "${account}", // User to connect as (optional) + // Command to get the PID of the process to attach (mandatory) + "pidCommand": [ + // + // Remember taht you can use ${var} to ask for input. I use this to + // call a custom command to returm the PID for a named service, so + // here's an examle: + // + "/path/to/secret/script/GetPIDForService", "${ServiceName}" + ], + + // Command to attach the debugger; %PID% replaced with output of + // pidCommand above (mandatory) + "attachCommand": [ + "python", "-m", "debugpy", "--listen", "0.0.0.0:${port}", + "--pid", "%PID%" + ] + + // Optional alternative to attachCommand (if you need to run multiple + // commands) + // "attachCommands": [ + // [ /* first command */ ], + // [ /* second command */ ] + // ], + + // Optional.... useful with buggy gdbservers to kill -TRAP %PID% + // "initCompleteCommand": [ + // /* optional command to run after initialized */ + // ] + + // Optional.... Manual additional arguments for ssh + // "ssh": { + // "args": [ "-o", "StrictHostKeyChecking=no" ] + // }, + } + // optional delay to wait after running runCommand(s). This is often + // needed because of the way docker handles TCP, or if you're using some + // wrapper (e.g. to start the JVM) + // "delay": "1000m" // format as per :help sleep + } + } + }, + "configurations": { + "remote-launch": { + "adapter": "python-remote", + + "remote-request": "launch", + "remote-cmdLine": [ + "${RemoteRoot}/${fileBasename}", "*${args}" + ], + + "configuration": { + "request": "attach", + "pathMappings": [ + { + "localRoot": "${workspaceRoot}", + "remoteRoot": "${RemoteRoot}" + } + ] + } + }, + "remote-attach": { + "variables": { + // Just an example of how to specify a variable manually rather than + // vimspector asking for input from the user + "ServiceName": "${fileBasenameNoExtention}" + }, + + "adapter": "python-remote", + "remote-request": "attach", + + "configuration": { + "request": "attach", + "pathMappings": [ + { + "localRoot": "${workspaceRoot}", + "remoteRoot": "${RemoteRoot}" + } + ] + } + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-ref-c-family-example* +C-family (gdbserver) Example ~ + +This example uses Vimspector to remotely launch or attach to a binary using +'gdbserver' and then instructs vscode-cpptools to attach to that 'gdbserver'. + +The approach is very similar to the above for python, just that we use +gdbserver and have to tell cpptools a few more options. +> + { + "adapters": { + "cpptools-remote": { + "command": [ + "${gadgetDir}/vscode-cpptools/debugAdapters/OpenDebugAD7" + ], + "name": "cppdbg", + "configuration": { + "type": "cppdbg" + }, + "launch": { + "remote": { + "host": "${host}", + "account": "${account}", + "runCommand": [ + "gdbserver", + "--once", + "--no-startup-with-shell", + "--disable-randomisation", + "0.0.0.0:${port}", + "%CMD%" + } + }, + "attach": { + "remote": { + "host": "${host}", + "account": "${account}", + "pidCommand": [ + "/path/to/secret/script/GetPIDForService", "${ServiceName}" + ], + "attachCommand": [ + "gdbserver", + "--once", + "--attach", + "0.0.0.0:${port}", + "%PID%" + ], + // + // If your application is started by a wrapper script, then you might + // need the followin. GDB can't pause an application because it only + // sends the signal to the process group leader. Or something. + // Basically, if you find that everything just hangs and the + // application never attaches, try using the following to manually + // force the trap signal. + // + "initCompleteCommand": [ + "kill", + "-TRAP", + "%PID%" + ] + } + } + } + }, + "configurations": { + "remote launch": { + "adapter": "cpptools-remote", + "remote-cmdLine": [ "/path/to/the/remote/executable", "args..." ], + "remote-request": "launch", + "configuration": { + "request": "attach", // yes, attach! + + "program": "/path/to/the/local/executable", + "MIMode": "gdb", + "miDebuggerAddress": "${host}:${port}" + } + }, + "remote attach": { + "adapter": "cpptools-remote", + "remote-request": "attach", + "configuration": { + "request": "attach", + + "program": "/path/to/the/local/executable", + "MIMode": "gdb", + "miDebuggerAddress": "${host}:${port}" + } + } + } +< +------------------------------------------------------------------------------- + *vimspector-ref-docker-example* +Docker Example ~ + +This example uses Vimspector to remotely launch or attach to a docker container +port. +> + { + "adapters": { + "python-remote": { + "port": "${port}", + "launch": { + "remote": { + "container": "${container}", // Docker container id or name to exec into to. + + // Command to launch the debugee and attach the debugger; + // %CMD% replaced with the remote-cmdLine configured in the launch + // configuration. (mandatory) + "runCommand": [ + "python", "-m", "debugpy", + "--listen", "0.0.0.0:${port}", + "--wait-for-client", + "%CMD%" + ] + + // Optional alternative to runCommand (if you need to run multiple + // commands) + // "runCommands": [ + // [ /* first command */ ], + // [ /* second command */ ] + // ] + + } + + // optional delay to wait after running runCommand(s). This is often + // needed because of the way docker handles TCP + "delay": "1000m" // format as per :help sleep + }, + "attach": { + "remote": { + "container": "${container}", // Docker container id or name to exec into. + // Command to get the PID of the process to attach (mandatory) + // This command gets appended to "docker exec ${container}" + "pidCommand": [ + // + // Remember taht you can use ${var} to ask for input. I use this to + // call a custom command to returm the PID for a named service, so + // here's an examle: + // + "sh", "-c", "pgrep", "-f", "${filename}" + ], + + // Command to attach the debugger; %PID% replaced with output of + // pidCommand above (mandatory) + "attachCommand": [ + "sh", "-c", "python", "-m", "debugpy", "--listen", "0.0.0.0:${port}", + "--pid", "%PID%" + ] + + // Optional alternative to attachCommand (if you need to run multiple + // commands) + // "attachCommands": [ + // [ /* first command */ ], + // [ /* second command */ ] + // ], + + // Optional.... useful with buggy gdbservers to kill -TRAP %PID% + // "initCompleteCommand": [ + // /* optional command to run after initialized */ + // ] + + } + + // optional delay to wait after running runCommand(s). This is often + // needed because of the way docker handles TCP, or if you're using some + // wrapper (e.g. to start the JVM) + "delay": "1000m" // format as per :help sleep + } + } + }, + "configurations": { + "remote-launch": { + "adapter": "python-remote", + + "remote-request": "launch", + "remote-cmdLine": [ + "${RemoteRoot}/${fileBasename}", "*${args}" + ], + + "configuration": { + "request": "attach", + "pathMappings": [ + { + "localRoot": "${workspaceRoot}", + "remoteRoot": "${RemoteRoot}" + } + ] + } + }, + "remote-attach": { + "variables": { + // Just an example of how to specify a variable manually rather than + // vimspector asking for input from the user + "FileName": "${fileName}" + }, + + "adapter": "python-remote", + "remote-request": "attach", + + "configuration": { + "request": "attach", + "pathMappings": [ + { + "localRoot": "${workspaceRoot}", + "remoteRoot": "${RemoteRoot}" + } + ] + } + } + } + } +< +=============================================================================== + *vimspector-ref-appendix-configuration-file-format* +Appendix: Configuration file format ~ + +The configuration files are text files which must be UTF-8 encoded. They +contain a single JSON object, along with optional comments. + +Comments are "c-style", i.e.: + +- '// single line comment ...' +- '/* inline comment */' + +There is much debate about whether JSON files should contain comments. I have +added them because they are useful in the context of configuration files. +Unforutnately this may mean your editor doesn't like them (they are strictly +invalid JSON) so it's up to you if you use them. + +Technically, Vimspector uses JSON minify [3] to strip comments before parsing +the JSON. + +=============================================================================== + *vimspector-ref-appendix-editor-configuration* +Appendix: Editor configuration ~ + +If you would like some assistance with writing the JSON files, and your editor +of choice has a way to use a language server, you can use the VSCode JSON +language server [4]. + +It is recommended to include the '$schema' declaration as in the above +examples, but if that isn't present, the following JSON language server +configuration [5] is recommened to load the schema from the Internet: +> + { + "json": { + "schemas": [ + { + "fileMatch": [ ".vimspector.json" ], + "url": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json" + }, + { + "fileMatch": [ ".gadgets.json", ".gadgets.d/*.json" ], + "url": "https://puremourning.github.io/vimspector/schema/gadgets.schema.json" + } + ] + } + } +< +If your language server client of choice happens to be YouCompleteMe [6], then +the following '.ycm_extra_conf.py' is good enough to get you going, after +following the instructions in the lsp-examples [7] repo to get the server set +up: +> + VIMSPECTOR_HOME = '/path/to/vimspector' # TODO: Change this + + def Settings( **kwargs ): + if kwargs[ 'language' ] == 'json': + return { + 'ls': { + 'json': { + 'schemas': [ + { + 'fileMatch': [ '.vimspector.json' ], + 'url': f'file://{VIMSPECTOR_HOME}/docs/schema/vimspector.schema.json' + }, + { + 'fileMatch': [ '.gadgets.json', '.gadgets.d/*.json' ], + 'url': f'file://{VIMSPECTOR_HOME}/docs/schema/gadgets.schema.json' + } + ] + } + } + } + + return None # Or your existing Settings definition.... +< +This configuration can be adapted to any other LSP-based editor configuration +and is provided just as an example. + +=============================================================================== + *vimspector-ref-references* +References ~ + +[1] https://microsoft.github.io/debug-adapter-protocol/ +[2] http://puremourning.github.io/vimspector/schema/vimspector.schema.json +[3] https://github.com/getify/JSON.minify +[4] https://github.com/vscode-langservers/vscode-json-languageserver +[5] https://github.com/vscode-langservers/vscode-json-languageserver#settings +[6] https://github.com/ycm-core/YouCompleteMe +[7] https://github.com/ycm-core/lsp-examples + +vim: ft=help From 054ea35428e5e8d6abe12b6a535a3b0426d4874e Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Mon, 22 Mar 2021 15:13:58 +0000 Subject: [PATCH 30/73] Add a way to test with dlv directly. Currrently not ready for the big time --- support/test/go/hello_world/.vimspector.json | 29 ++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/support/test/go/hello_world/.vimspector.json b/support/test/go/hello_world/.vimspector.json index 8ab5091..4613b98 100644 --- a/support/test/go/hello_world/.vimspector.json +++ b/support/test/go/hello_world/.vimspector.json @@ -1,4 +1,18 @@ { + "adapters": { + "dlv-dap": { + "variables": { + "port": "${unusedLocalPort}" + }, + "command": [ + "$HOME/go/bin/dlv", + "dap", + "--listen", + "127.0.0.1:${port}" + ], + "port": "${port}" + } + }, "configurations": { "run": { "adapter": "vscode-go", @@ -12,6 +26,21 @@ "env": { "GO111MODULE": "off" } } }, + "run-dap": { + "adapter": "dlv-dap", + "configuration": { + "request": "launch", + "env": { "GO111MODULE": "off" }, + + "mode": "debug", // debug|test + "program": "${workspaceRoot}/hello-world.go" + + // "args": [], + // "buildFlags": ... + // "stackTraceDepth": ..., + // "showGlobalVariables": true, + } + }, "run-exec": { // NOTE: To use this you _must_ disable optimistaion: // go build -o hello_world -gcflags="all=-N -l" From 0d9e7835a85d6b0e53faeac982d1a4599aaf6fd6 Mon Sep 17 00:00:00 2001 From: puh <-> Date: Mon, 29 Mar 2021 23:11:26 +0300 Subject: [PATCH 31/73] Update CodeLLDB --- python3/vimspector/gadgets.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 528f60c..d2c280b 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -453,12 +453,12 @@ GADGETS = { '${version}/${file_name}', }, 'all': { - 'version': 'v1.5.3', + 'version': 'v1.6.1', }, 'macos': { 'file_name': 'codelldb-x86_64-darwin.vsix', 'checksum': - '7505bc1cdfcfd1cb981e2996aec62d63577440709bac31dcadb41a3b4b44631a', + 'b1c998e7421beea9f3ba21aa5706210bb2249eba93c99b809247ee831075262f', 'make_executable': [ 'adapter/codelldb', 'lldb/bin/debugserver', @@ -469,7 +469,7 @@ GADGETS = { 'linux': { 'file_name': 'codelldb-x86_64-linux.vsix', 'checksum': - 'ce7efc3e94d775368e5942a02bf5c326b6809a0b4c389f79ffa6a8f6f6b72139', + 'f2a36cb6971fd95a467cf1a7620e160914e8f11bf82929932ee0aa5afbf6ae6a', 'make_executable': [ 'adapter/codelldb', 'lldb/bin/lldb', @@ -480,7 +480,7 @@ GADGETS = { 'windows': { 'file_name': 'codelldb-x86_64-windows.vsix', 'checksum': - '', + 'ca6a6525bf7719dc95265dc630b3cc817a8c0393b756fd242b710805ffdfb940', 'make_executable': [] }, 'adapters': { From d70d51a614a11f03a64294a48aca134634053713 Mon Sep 17 00:00:00 2001 From: Tony Dwire Date: Wed, 7 Apr 2021 11:50:26 -0500 Subject: [PATCH 32/73] Updated netcoredbg to 1.2.0-761 to enable mac support of async/await --- python3/vimspector/gadgets.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index d2c280b..8be7db7 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -234,11 +234,10 @@ GADGETS = { 'format': 'tar', }, 'all': { - 'version': '1.2.0-738' + 'version': '1.2.0-761' }, 'macos': { 'file_name': 'netcoredbg-osx.tar.gz', - 'version': '1.2.0-635', 'checksum': '71c773e34d358950f25119bade7e3081c4c2f9d71847bd49027ca5792e918beb', }, From 7d83419a4f813aee826eee994b8e419b6ff102b0 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 7 Apr 2021 22:45:58 +0100 Subject: [PATCH 33/73] Update docs bundles --- docs/Gemfile.lock | 50 +++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index d2eb55f..6a18520 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -1,7 +1,7 @@ GEM remote: https://rubygems.org/ specs: - activesupport (6.0.3.4) + activesupport (6.0.3.6) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -16,7 +16,7 @@ GEM colorator (1.1.0) commonmarker (0.17.13) ruby-enum (~> 0.5) - concurrent-ruby (1.1.7) + concurrent-ruby (1.1.8) dnsruby (1.61.5) simpleidn (~> 0.1) em-websocket (0.5.2) @@ -30,12 +30,12 @@ GEM faraday-net_http (~> 1.0) multipart-post (>= 1.2, < 3) ruby2_keywords - faraday-net_http (1.0.0) - ffi (1.14.2) + faraday-net_http (1.0.1) + ffi (1.15.0) forwardable-extended (2.6.0) gemoji (3.0.1) - github-pages (209) - github-pages-health-check (= 1.16.1) + github-pages (214) + github-pages-health-check (= 1.17.0) jekyll (= 3.9.0) jekyll-avatar (= 0.7.0) jekyll-coffeescript (= 1.1.1) @@ -50,9 +50,9 @@ GEM jekyll-readme-index (= 0.3.0) jekyll-redirect-from (= 0.16.0) jekyll-relative-links (= 0.6.1) - jekyll-remote-theme (= 0.4.2) + jekyll-remote-theme (= 0.4.3) jekyll-sass-converter (= 1.5.2) - jekyll-seo-tag (= 2.6.1) + jekyll-seo-tag (= 2.7.1) jekyll-sitemap (= 1.4.0) jekyll-swiss (= 1.0.0) jekyll-theme-architect (= 0.1.1) @@ -70,19 +70,19 @@ GEM jekyll-theme-time-machine (= 0.1.1) jekyll-titles-from-headings (= 0.5.3) jemoji (= 0.12.0) - kramdown (= 2.3.0) + kramdown (= 2.3.1) kramdown-parser-gfm (= 1.1.0) liquid (= 4.0.3) mercenary (~> 0.3) minima (= 2.5.1) nokogiri (>= 1.10.4, < 2.0) - rouge (= 3.23.0) + rouge (= 3.26.0) terminal-table (~> 1.4) - github-pages-health-check (1.16.1) + github-pages-health-check (1.17.0) addressable (~> 2.3) dnsruby (~> 1.60) octokit (~> 4.0) - public_suffix (~> 3.0) + public_suffix (>= 2.0.2, < 5.0) typhoeus (~> 1.3) html-pipeline (2.14.0) activesupport (>= 2) @@ -136,15 +136,15 @@ GEM jekyll (>= 3.3, < 5.0) jekyll-relative-links (0.6.1) jekyll (>= 3.3, < 5.0) - jekyll-remote-theme (0.4.2) + jekyll-remote-theme (0.4.3) addressable (~> 2.0) jekyll (>= 3.5, < 5.0) jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0) rubyzip (>= 1.3.0, < 3.0) jekyll-sass-converter (1.5.2) sass (~> 3.4) - jekyll-seo-tag (2.6.1) - jekyll (>= 3.3, < 5.0) + jekyll-seo-tag (2.7.1) + jekyll (>= 3.8, < 5.0) jekyll-sitemap (1.4.0) jekyll (>= 3.7, < 5.0) jekyll-swiss (1.0.0) @@ -196,12 +196,12 @@ GEM gemoji (~> 3.0) html-pipeline (~> 2.2) jekyll (>= 3.0, < 5.0) - kramdown (2.3.0) + kramdown (2.3.1) rexml kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) liquid (4.0.3) - listen (3.4.0) + listen (3.5.1) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) mercenary (0.3.6) @@ -210,9 +210,9 @@ GEM jekyll (>= 3.5, < 5.0) jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) - minitest (5.14.3) + minitest (5.14.4) multipart-post (2.1.1) - nokogiri (1.11.1) + nokogiri (1.11.3) mini_portile2 (~> 2.5.0) racc (~> 1.4) octokit (4.20.0) @@ -220,16 +220,16 @@ GEM sawyer (~> 0.8.0, >= 0.5.3) pathutil (0.16.2) forwardable-extended (~> 2.6) - public_suffix (3.1.1) + public_suffix (4.0.6) racc (1.5.2) rb-fsevent (0.10.4) rb-inotify (0.10.1) ffi (~> 1.0) - rexml (3.2.4) - rouge (3.23.0) - ruby-enum (0.8.0) + rexml (3.2.5) + rouge (3.26.0) + ruby-enum (0.9.0) i18n - ruby2_keywords (0.0.2) + ruby2_keywords (0.0.4) rubyzip (2.3.0) safe_yaml (1.0.5) sass (3.7.4) @@ -240,7 +240,7 @@ GEM sawyer (0.8.2) addressable (>= 2.3.5) faraday (> 0.8, < 2.0) - simpleidn (0.1.1) + simpleidn (0.2.1) unf (~> 0.1.4) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) From 13a5a1b947825f710a0aacc0fd8167bd3d42822c Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 9 Apr 2021 16:54:38 +0100 Subject: [PATCH 34/73] Fix traceback when +python3 is not availble --- autoload/vimspector.vim | 3 +++ docs/configuration.md | 2 +- plugin/vimspector.vim | 7 +++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index a0b6c42..1219661 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -13,6 +13,9 @@ " See the License for the specific language governing permissions and " limitations under the License. +if !has( 'python3' ) + finish +endif " Boilerplate {{{ let s:save_cpo = &cpoptions diff --git a/docs/configuration.md b/docs/configuration.md index e736985..a2864b1 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -271,7 +271,7 @@ JSON value `true`, and the suffix is stripped fom the key, resulting in the following: ```json - "stopOnEntry#json": true + "stopOnEntry": true ``` Which is what we need. diff --git a/plugin/vimspector.vim b/plugin/vimspector.vim index 75e2baa..27ce473 100644 --- a/plugin/vimspector.vim +++ b/plugin/vimspector.vim @@ -13,6 +13,13 @@ " See the License for the specific language governing permissions and " limitations under the License. +if !has( 'python3' ) + echohl WarningMsg + echom 'Vimspector unavailable: Requires Vim compiled with +python3' + echohl None + finish +endif + " Boilerplate {{{ let s:save_cpo = &cpoptions set cpoptions&vim From 278fc3cd8c285e3e2f6abff824592a18186912bd Mon Sep 17 00:00:00 2001 From: Tony Dwire Date: Fri, 9 Apr 2021 11:29:17 -0500 Subject: [PATCH 35/73] Update sha256sum of netcoredbg --- python3/vimspector/gadgets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 8be7db7..7b807b6 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -239,7 +239,7 @@ GADGETS = { 'macos': { 'file_name': 'netcoredbg-osx.tar.gz', 'checksum': - '71c773e34d358950f25119bade7e3081c4c2f9d71847bd49027ca5792e918beb', + '994e0d001f53af058c94468336dfd1f166a3f3540c9e0de4f9f45f59e6c969fe', }, 'linux': { 'file_name': 'netcoredbg-linux-bionic-amd64.tar.gz', From fa92c2a8d525972bcc97cba9579d9adfca3c859a Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sun, 11 Apr 2021 19:23:47 +0100 Subject: [PATCH 36/73] Add a mode for debugging the extremely flaky netcoredbg --- support/test/csharp/.vimspector.json | 65 ++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/support/test/csharp/.vimspector.json b/support/test/csharp/.vimspector.json index 524ae1a..8b2c499 100644 --- a/support/test/csharp/.vimspector.json +++ b/support/test/csharp/.vimspector.json @@ -1,25 +1,52 @@ { - "configurations": { - "launch - netcoredbg": { - "adapter": "netcoredbg", - "configuration": { - "request": "launch", - "program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/csharp.dll", - "args": [], - "stopAtEntry": true - } + "adapters": { + "netcoredbg-debuglog": { + "attach": { + "pidProperty": "processId", + "pidSelect": "ask" }, - "launch - mono": { - "adapter": "vscode-mono-debug", - "configuration": { - "request": "launch", - "program": "${workspaceRoot}/Program.exe", - "console": "integratedTerminal", - "cwd": "${workspaceRoot}", - "args": [], - "env": {} - } + "command": [ + "${gadgetDir}/netcoredbg/netcoredbg", + "--interpreter=vscode", + "--engineLogging=${workspaceRoot}/netcoredbg.engine.log", + "--log=${workspaceRoot}/netcoredbg.log" + ], + "configuration": { + "cwd": "${workspaceRoot}" + }, + "name": "netcoredbg" + } + }, + "configurations": { + "launch - netcoredbg": { + "adapter": "netcoredbg", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/csharp.dll", + "args": [], + "stopAtEntry": true + } + }, + "launch - netcoredbg - with debug log": { + "adapter": "netcoredbg-debuglog", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/csharp.dll", + "args": [], + "stopAtEntry": true + } + }, + "launch - mono": { + "adapter": "vscode-mono-debug", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/Program.exe", + "console": "integratedTerminal", + "cwd": "${workspaceRoot}", + "args": [], + "env": {} } } + } } From dd88e051a408e828af1d54ce8c98e18f41c64b5d Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 13 Apr 2021 17:34:51 +0100 Subject: [PATCH 37/73] Attempt to recover from broken messages --- python3/vimspector/debug_adapter_connection.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/python3/vimspector/debug_adapter_connection.py b/python3/vimspector/debug_adapter_connection.py index df2ef13..206938a 100644 --- a/python3/vimspector/debug_adapter_connection.py +++ b/python3/vimspector/debug_adapter_connection.py @@ -226,7 +226,12 @@ class DebugAdapterConnection( object ): # self._logger.debug( 'Message received (raw): %s', payload ) - message = json.loads( payload ) + try: + message = json.loads( payload, strict = False ) + except Exception: + self._logger.exception( "Invalid message received: %s", payload ) + self._SetState( 'READ_HEADER' ) + raise self._logger.debug( 'Message received: {0}'.format( message ) ) From a41db89523723dbdde6b3f1381e4de321e67b78c Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 13 Apr 2021 18:01:10 +0100 Subject: [PATCH 38/73] Fix get_configurations test --- support/test/csharp/.vimspector.json | 5 +++++ tests/get_configurations.test.vim | 1 + 2 files changed, 6 insertions(+) diff --git a/support/test/csharp/.vimspector.json b/support/test/csharp/.vimspector.json index 8b2c499..ae796e5 100644 --- a/support/test/csharp/.vimspector.json +++ b/support/test/csharp/.vimspector.json @@ -18,6 +18,11 @@ } }, "configurations": { + // + // NOTE: + // If you add to this, you must update tests/get_configurations.test.vim + // + "launch - netcoredbg": { "adapter": "netcoredbg", "configuration": { diff --git a/tests/get_configurations.test.vim b/tests/get_configurations.test.vim index 4a37d01..33e6577 100644 --- a/tests/get_configurations.test.vim +++ b/tests/get_configurations.test.vim @@ -12,6 +12,7 @@ function Test_Get_Configurations() let configs = vimspector#GetConfigurations() call assert_equal([ \ 'launch - netcoredbg', + \ 'launch - netcoredbg - with debug log', \ 'launch - mono', \ ], configs) From 6ad9101cf27f6d07d2f68fe04762e055869ec2d7 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 15 Apr 2021 15:02:46 +0100 Subject: [PATCH 39/73] Add FAQ about json files in each project. --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 6979e44..ae0ef46 100644 --- a/README.md +++ b/README.md @@ -2070,6 +2070,10 @@ hi link jsonComment Comment Debug adapters (for some reason) send telemetry data to clients. Vimspector simply displays this information in the output window. It *does not* and *will not ever* collect, use, forward or otherwise share any data with any third parties. +10. Do I _have_ to put a `.vimspector.json` in the root of every project? No, you + can put all of your adapter and debug configs in a [single directory](https://puremourning.github.io/vimspector/configuration.html#debug-configurations) if you want to, but note + the caveat that `${workspaceRoot}` won't be calculated correctly in that case. + The vimsepctor author uses this [a lot](https://github.com/puremourning/.vim-mac/tree/master/vimspector-conf). [ycmd]: https://github.com/Valloric/ycmd From b4195eee93846da6c73241520751b20a25bdbab7 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 15 Apr 2021 18:02:55 +0100 Subject: [PATCH 40/73] Upgrade to netcoredbg v1.2.0-782 Also upgrade the test project to LTS 3.1 dotnet framework, as MS is making it very difficult to get framework 2.2 anymore. Also remove some object files which apparently were included in the repo. --- python3/vimspector/gadgets.py | 4 +- support/test/csharp/.gitignore | 1 + support/test/csharp/.vimspector.json | 4 +- support/test/csharp/csharp.csproj | 2 +- .../test/csharp/obj/csharp.csproj.nuget.cache | 5 - .../csharp/obj/csharp.csproj.nuget.g.props | 21 - .../csharp/obj/csharp.csproj.nuget.g.targets | 10 - support/test/csharp/obj/project.assets.json | 748 ------------------ 8 files changed, 6 insertions(+), 789 deletions(-) delete mode 100644 support/test/csharp/obj/csharp.csproj.nuget.cache delete mode 100644 support/test/csharp/obj/csharp.csproj.nuget.g.props delete mode 100644 support/test/csharp/obj/csharp.csproj.nuget.g.targets delete mode 100644 support/test/csharp/obj/project.assets.json diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 7b807b6..6b28095 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -234,12 +234,12 @@ GADGETS = { 'format': 'tar', }, 'all': { - 'version': '1.2.0-761' + 'version': '1.2.0-782' }, 'macos': { 'file_name': 'netcoredbg-osx.tar.gz', 'checksum': - '994e0d001f53af058c94468336dfd1f166a3f3540c9e0de4f9f45f59e6c969fe', + '', }, 'linux': { 'file_name': 'netcoredbg-linux-bionic-amd64.tar.gz', diff --git a/support/test/csharp/.gitignore b/support/test/csharp/.gitignore index b7d74e4..03cd7d8 100644 --- a/support/test/csharp/.gitignore +++ b/support/test/csharp/.gitignore @@ -1,2 +1,3 @@ bin/ obj/Debug +obj/ diff --git a/support/test/csharp/.vimspector.json b/support/test/csharp/.vimspector.json index ae796e5..3bfb0f3 100644 --- a/support/test/csharp/.vimspector.json +++ b/support/test/csharp/.vimspector.json @@ -27,7 +27,7 @@ "adapter": "netcoredbg", "configuration": { "request": "launch", - "program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/csharp.dll", + "program": "${workspaceRoot}/bin/Debug/netcoreapp3.1/csharp.dll", "args": [], "stopAtEntry": true } @@ -36,7 +36,7 @@ "adapter": "netcoredbg-debuglog", "configuration": { "request": "launch", - "program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/csharp.dll", + "program": "${workspaceRoot}/bin/Debug/netcoreapp3.1/csharp.dll", "args": [], "stopAtEntry": true } diff --git a/support/test/csharp/csharp.csproj b/support/test/csharp/csharp.csproj index 01d5113..d453e9a 100644 --- a/support/test/csharp/csharp.csproj +++ b/support/test/csharp/csharp.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.2 + netcoreapp3.1 diff --git a/support/test/csharp/obj/csharp.csproj.nuget.cache b/support/test/csharp/obj/csharp.csproj.nuget.cache deleted file mode 100644 index 3ac8d84..0000000 --- a/support/test/csharp/obj/csharp.csproj.nuget.cache +++ /dev/null @@ -1,5 +0,0 @@ -{ - "version": 1, - "dgSpecHash": "6/vdr7YprlSIoQecv/nNuLNflFpO0X7eN7jHUinZTsgian9nYpmHMWirsDWMi5l+29TH+Qy8O/QfaB/48QtjRQ==", - "success": true -} \ No newline at end of file diff --git a/support/test/csharp/obj/csharp.csproj.nuget.g.props b/support/test/csharp/obj/csharp.csproj.nuget.g.props deleted file mode 100644 index c71f0e6..0000000 --- a/support/test/csharp/obj/csharp.csproj.nuget.g.props +++ /dev/null @@ -1,21 +0,0 @@ - - - - True - NuGet - $(MSBuildThisFileDirectory)project.assets.json - /Users/ben/.nuget/packages/ - /Users/ben/.nuget/packages/;/usr/local/share/dotnet/sdk/NuGetFallbackFolder - PackageReference - 5.7.0 - - - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - - - \ No newline at end of file diff --git a/support/test/csharp/obj/csharp.csproj.nuget.g.targets b/support/test/csharp/obj/csharp.csproj.nuget.g.targets deleted file mode 100644 index 099158b..0000000 --- a/support/test/csharp/obj/csharp.csproj.nuget.g.targets +++ /dev/null @@ -1,10 +0,0 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - - - - \ No newline at end of file diff --git a/support/test/csharp/obj/project.assets.json b/support/test/csharp/obj/project.assets.json deleted file mode 100644 index bd6c0fc..0000000 --- a/support/test/csharp/obj/project.assets.json +++ /dev/null @@ -1,748 +0,0 @@ -{ - "version": 3, - "targets": { - ".NETCoreApp,Version=v2.2": { - "Microsoft.NETCore.App/2.2.0": { - "type": "package", - "dependencies": { - "Microsoft.NETCore.DotNetHostPolicy": "2.2.0", - "Microsoft.NETCore.Platforms": "2.2.0", - "Microsoft.NETCore.Targets": "2.0.0", - "NETStandard.Library": "2.0.3" - }, - "compile": { - "ref/netcoreapp2.2/Microsoft.CSharp.dll": {}, - "ref/netcoreapp2.2/Microsoft.VisualBasic.dll": {}, - "ref/netcoreapp2.2/Microsoft.Win32.Primitives.dll": {}, - "ref/netcoreapp2.2/System.AppContext.dll": {}, - "ref/netcoreapp2.2/System.Buffers.dll": {}, - "ref/netcoreapp2.2/System.Collections.Concurrent.dll": {}, - "ref/netcoreapp2.2/System.Collections.Immutable.dll": {}, - "ref/netcoreapp2.2/System.Collections.NonGeneric.dll": {}, - "ref/netcoreapp2.2/System.Collections.Specialized.dll": {}, - "ref/netcoreapp2.2/System.Collections.dll": {}, - "ref/netcoreapp2.2/System.ComponentModel.Annotations.dll": {}, - "ref/netcoreapp2.2/System.ComponentModel.DataAnnotations.dll": {}, - "ref/netcoreapp2.2/System.ComponentModel.EventBasedAsync.dll": {}, - "ref/netcoreapp2.2/System.ComponentModel.Primitives.dll": {}, - "ref/netcoreapp2.2/System.ComponentModel.TypeConverter.dll": {}, - "ref/netcoreapp2.2/System.ComponentModel.dll": {}, - "ref/netcoreapp2.2/System.Configuration.dll": {}, - "ref/netcoreapp2.2/System.Console.dll": {}, - "ref/netcoreapp2.2/System.Core.dll": {}, - "ref/netcoreapp2.2/System.Data.Common.dll": {}, - "ref/netcoreapp2.2/System.Data.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.Contracts.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.Debug.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.DiagnosticSource.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.FileVersionInfo.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.Process.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.StackTrace.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.TextWriterTraceListener.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.Tools.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.TraceSource.dll": {}, - "ref/netcoreapp2.2/System.Diagnostics.Tracing.dll": {}, - "ref/netcoreapp2.2/System.Drawing.Primitives.dll": {}, - "ref/netcoreapp2.2/System.Drawing.dll": {}, - "ref/netcoreapp2.2/System.Dynamic.Runtime.dll": {}, - "ref/netcoreapp2.2/System.Globalization.Calendars.dll": {}, - "ref/netcoreapp2.2/System.Globalization.Extensions.dll": {}, - "ref/netcoreapp2.2/System.Globalization.dll": {}, - "ref/netcoreapp2.2/System.IO.Compression.Brotli.dll": {}, - "ref/netcoreapp2.2/System.IO.Compression.FileSystem.dll": {}, - "ref/netcoreapp2.2/System.IO.Compression.ZipFile.dll": {}, - "ref/netcoreapp2.2/System.IO.Compression.dll": {}, - "ref/netcoreapp2.2/System.IO.FileSystem.DriveInfo.dll": {}, - "ref/netcoreapp2.2/System.IO.FileSystem.Primitives.dll": {}, - "ref/netcoreapp2.2/System.IO.FileSystem.Watcher.dll": {}, - "ref/netcoreapp2.2/System.IO.FileSystem.dll": {}, - "ref/netcoreapp2.2/System.IO.IsolatedStorage.dll": {}, - "ref/netcoreapp2.2/System.IO.MemoryMappedFiles.dll": {}, - "ref/netcoreapp2.2/System.IO.Pipes.dll": {}, - "ref/netcoreapp2.2/System.IO.UnmanagedMemoryStream.dll": {}, - "ref/netcoreapp2.2/System.IO.dll": {}, - "ref/netcoreapp2.2/System.Linq.Expressions.dll": {}, - "ref/netcoreapp2.2/System.Linq.Parallel.dll": {}, - "ref/netcoreapp2.2/System.Linq.Queryable.dll": {}, - "ref/netcoreapp2.2/System.Linq.dll": {}, - "ref/netcoreapp2.2/System.Memory.dll": {}, - "ref/netcoreapp2.2/System.Net.Http.dll": {}, - "ref/netcoreapp2.2/System.Net.HttpListener.dll": {}, - "ref/netcoreapp2.2/System.Net.Mail.dll": {}, - "ref/netcoreapp2.2/System.Net.NameResolution.dll": {}, - "ref/netcoreapp2.2/System.Net.NetworkInformation.dll": {}, - "ref/netcoreapp2.2/System.Net.Ping.dll": {}, - "ref/netcoreapp2.2/System.Net.Primitives.dll": {}, - "ref/netcoreapp2.2/System.Net.Requests.dll": {}, - "ref/netcoreapp2.2/System.Net.Security.dll": {}, - "ref/netcoreapp2.2/System.Net.ServicePoint.dll": {}, - "ref/netcoreapp2.2/System.Net.Sockets.dll": {}, - "ref/netcoreapp2.2/System.Net.WebClient.dll": {}, - "ref/netcoreapp2.2/System.Net.WebHeaderCollection.dll": {}, - "ref/netcoreapp2.2/System.Net.WebProxy.dll": {}, - "ref/netcoreapp2.2/System.Net.WebSockets.Client.dll": {}, - "ref/netcoreapp2.2/System.Net.WebSockets.dll": {}, - "ref/netcoreapp2.2/System.Net.dll": {}, - "ref/netcoreapp2.2/System.Numerics.Vectors.dll": {}, - "ref/netcoreapp2.2/System.Numerics.dll": {}, - "ref/netcoreapp2.2/System.ObjectModel.dll": {}, - "ref/netcoreapp2.2/System.Reflection.DispatchProxy.dll": {}, - "ref/netcoreapp2.2/System.Reflection.Emit.ILGeneration.dll": {}, - "ref/netcoreapp2.2/System.Reflection.Emit.Lightweight.dll": {}, - "ref/netcoreapp2.2/System.Reflection.Emit.dll": {}, - "ref/netcoreapp2.2/System.Reflection.Extensions.dll": {}, - "ref/netcoreapp2.2/System.Reflection.Metadata.dll": {}, - "ref/netcoreapp2.2/System.Reflection.Primitives.dll": {}, - "ref/netcoreapp2.2/System.Reflection.TypeExtensions.dll": {}, - "ref/netcoreapp2.2/System.Reflection.dll": {}, - "ref/netcoreapp2.2/System.Resources.Reader.dll": {}, - "ref/netcoreapp2.2/System.Resources.ResourceManager.dll": {}, - "ref/netcoreapp2.2/System.Resources.Writer.dll": {}, - "ref/netcoreapp2.2/System.Runtime.CompilerServices.VisualC.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Extensions.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Handles.dll": {}, - "ref/netcoreapp2.2/System.Runtime.InteropServices.RuntimeInformation.dll": {}, - "ref/netcoreapp2.2/System.Runtime.InteropServices.WindowsRuntime.dll": {}, - "ref/netcoreapp2.2/System.Runtime.InteropServices.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Loader.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Numerics.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Serialization.Formatters.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Serialization.Json.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Serialization.Primitives.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Serialization.Xml.dll": {}, - "ref/netcoreapp2.2/System.Runtime.Serialization.dll": {}, - "ref/netcoreapp2.2/System.Runtime.dll": {}, - "ref/netcoreapp2.2/System.Security.Claims.dll": {}, - "ref/netcoreapp2.2/System.Security.Cryptography.Algorithms.dll": {}, - "ref/netcoreapp2.2/System.Security.Cryptography.Csp.dll": {}, - "ref/netcoreapp2.2/System.Security.Cryptography.Encoding.dll": {}, - "ref/netcoreapp2.2/System.Security.Cryptography.Primitives.dll": {}, - "ref/netcoreapp2.2/System.Security.Cryptography.X509Certificates.dll": {}, - "ref/netcoreapp2.2/System.Security.Principal.dll": {}, - "ref/netcoreapp2.2/System.Security.SecureString.dll": {}, - "ref/netcoreapp2.2/System.Security.dll": {}, - "ref/netcoreapp2.2/System.ServiceModel.Web.dll": {}, - "ref/netcoreapp2.2/System.ServiceProcess.dll": {}, - "ref/netcoreapp2.2/System.Text.Encoding.Extensions.dll": {}, - "ref/netcoreapp2.2/System.Text.Encoding.dll": {}, - "ref/netcoreapp2.2/System.Text.RegularExpressions.dll": {}, - "ref/netcoreapp2.2/System.Threading.Overlapped.dll": {}, - "ref/netcoreapp2.2/System.Threading.Tasks.Dataflow.dll": {}, - "ref/netcoreapp2.2/System.Threading.Tasks.Extensions.dll": {}, - "ref/netcoreapp2.2/System.Threading.Tasks.Parallel.dll": {}, - "ref/netcoreapp2.2/System.Threading.Tasks.dll": {}, - "ref/netcoreapp2.2/System.Threading.Thread.dll": {}, - "ref/netcoreapp2.2/System.Threading.ThreadPool.dll": {}, - "ref/netcoreapp2.2/System.Threading.Timer.dll": {}, - "ref/netcoreapp2.2/System.Threading.dll": {}, - "ref/netcoreapp2.2/System.Transactions.Local.dll": {}, - "ref/netcoreapp2.2/System.Transactions.dll": {}, - "ref/netcoreapp2.2/System.ValueTuple.dll": {}, - "ref/netcoreapp2.2/System.Web.HttpUtility.dll": {}, - "ref/netcoreapp2.2/System.Web.dll": {}, - "ref/netcoreapp2.2/System.Windows.dll": {}, - "ref/netcoreapp2.2/System.Xml.Linq.dll": {}, - "ref/netcoreapp2.2/System.Xml.ReaderWriter.dll": {}, - "ref/netcoreapp2.2/System.Xml.Serialization.dll": {}, - "ref/netcoreapp2.2/System.Xml.XDocument.dll": {}, - "ref/netcoreapp2.2/System.Xml.XPath.XDocument.dll": {}, - "ref/netcoreapp2.2/System.Xml.XPath.dll": {}, - "ref/netcoreapp2.2/System.Xml.XmlDocument.dll": {}, - "ref/netcoreapp2.2/System.Xml.XmlSerializer.dll": {}, - "ref/netcoreapp2.2/System.Xml.dll": {}, - "ref/netcoreapp2.2/System.dll": {}, - "ref/netcoreapp2.2/WindowsBase.dll": {}, - "ref/netcoreapp2.2/mscorlib.dll": {}, - "ref/netcoreapp2.2/netstandard.dll": {} - }, - "build": { - "build/netcoreapp2.2/Microsoft.NETCore.App.props": {}, - "build/netcoreapp2.2/Microsoft.NETCore.App.targets": {} - } - }, - "Microsoft.NETCore.DotNetAppHost/2.2.0": { - "type": "package" - }, - "Microsoft.NETCore.DotNetHostPolicy/2.2.0": { - "type": "package", - "dependencies": { - "Microsoft.NETCore.DotNetHostResolver": "2.2.0" - } - }, - "Microsoft.NETCore.DotNetHostResolver/2.2.0": { - "type": "package", - "dependencies": { - "Microsoft.NETCore.DotNetAppHost": "2.2.0" - } - }, - "Microsoft.NETCore.Platforms/2.2.0": { - "type": "package", - "compile": { - "lib/netstandard1.0/_._": {} - }, - "runtime": { - "lib/netstandard1.0/_._": {} - } - }, - "Microsoft.NETCore.Targets/2.0.0": { - "type": "package", - "compile": { - "lib/netstandard1.0/_._": {} - }, - "runtime": { - "lib/netstandard1.0/_._": {} - } - }, - "NETStandard.Library/2.0.3": { - "type": "package", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0" - }, - "compile": { - "lib/netstandard1.0/_._": {} - }, - "runtime": { - "lib/netstandard1.0/_._": {} - }, - "build": { - "build/netstandard2.0/NETStandard.Library.targets": {} - } - } - } - }, - "libraries": { - "Microsoft.NETCore.App/2.2.0": { - "sha512": "7z5l8Jp324S8bU8+yyWeYHXUFYvKyiI5lqS1dXgTzOx1H69Qbf6df12kCKlNX45LpMfCMd4U3M6p7Rl5Zk7SLA==", - "type": "package", - "path": "microsoft.netcore.app/2.2.0", - "files": [ - ".nupkg.metadata", - ".signature.p7s", - "LICENSE.TXT", - "Microsoft.NETCore.App.versions.txt", - "THIRD-PARTY-NOTICES.TXT", - "build/netcoreapp2.2/Microsoft.NETCore.App.PlatformManifest.txt", - "build/netcoreapp2.2/Microsoft.NETCore.App.props", - "build/netcoreapp2.2/Microsoft.NETCore.App.targets", - "microsoft.netcore.app.2.2.0.nupkg.sha512", - "microsoft.netcore.app.nuspec", - "ref/netcoreapp2.2/Microsoft.CSharp.dll", - "ref/netcoreapp2.2/Microsoft.CSharp.xml", - "ref/netcoreapp2.2/Microsoft.VisualBasic.dll", - "ref/netcoreapp2.2/Microsoft.VisualBasic.xml", - "ref/netcoreapp2.2/Microsoft.Win32.Primitives.dll", - "ref/netcoreapp2.2/Microsoft.Win32.Primitives.xml", - "ref/netcoreapp2.2/System.AppContext.dll", - "ref/netcoreapp2.2/System.Buffers.dll", - "ref/netcoreapp2.2/System.Buffers.xml", - "ref/netcoreapp2.2/System.Collections.Concurrent.dll", - "ref/netcoreapp2.2/System.Collections.Concurrent.xml", - "ref/netcoreapp2.2/System.Collections.Immutable.dll", - "ref/netcoreapp2.2/System.Collections.Immutable.xml", - "ref/netcoreapp2.2/System.Collections.NonGeneric.dll", - "ref/netcoreapp2.2/System.Collections.NonGeneric.xml", - "ref/netcoreapp2.2/System.Collections.Specialized.dll", - "ref/netcoreapp2.2/System.Collections.Specialized.xml", - "ref/netcoreapp2.2/System.Collections.dll", - "ref/netcoreapp2.2/System.Collections.xml", - "ref/netcoreapp2.2/System.ComponentModel.Annotations.dll", - "ref/netcoreapp2.2/System.ComponentModel.Annotations.xml", - "ref/netcoreapp2.2/System.ComponentModel.DataAnnotations.dll", - "ref/netcoreapp2.2/System.ComponentModel.EventBasedAsync.dll", - "ref/netcoreapp2.2/System.ComponentModel.EventBasedAsync.xml", - "ref/netcoreapp2.2/System.ComponentModel.Primitives.dll", - "ref/netcoreapp2.2/System.ComponentModel.Primitives.xml", - "ref/netcoreapp2.2/System.ComponentModel.TypeConverter.dll", - "ref/netcoreapp2.2/System.ComponentModel.TypeConverter.xml", - "ref/netcoreapp2.2/System.ComponentModel.dll", - "ref/netcoreapp2.2/System.ComponentModel.xml", - "ref/netcoreapp2.2/System.Configuration.dll", - "ref/netcoreapp2.2/System.Console.dll", - "ref/netcoreapp2.2/System.Console.xml", - "ref/netcoreapp2.2/System.Core.dll", - "ref/netcoreapp2.2/System.Data.Common.dll", - "ref/netcoreapp2.2/System.Data.Common.xml", - "ref/netcoreapp2.2/System.Data.dll", - "ref/netcoreapp2.2/System.Diagnostics.Contracts.dll", - "ref/netcoreapp2.2/System.Diagnostics.Contracts.xml", - "ref/netcoreapp2.2/System.Diagnostics.Debug.dll", - "ref/netcoreapp2.2/System.Diagnostics.Debug.xml", - "ref/netcoreapp2.2/System.Diagnostics.DiagnosticSource.dll", - "ref/netcoreapp2.2/System.Diagnostics.DiagnosticSource.xml", - "ref/netcoreapp2.2/System.Diagnostics.FileVersionInfo.dll", - "ref/netcoreapp2.2/System.Diagnostics.FileVersionInfo.xml", - "ref/netcoreapp2.2/System.Diagnostics.Process.dll", - "ref/netcoreapp2.2/System.Diagnostics.Process.xml", - "ref/netcoreapp2.2/System.Diagnostics.StackTrace.dll", - "ref/netcoreapp2.2/System.Diagnostics.StackTrace.xml", - "ref/netcoreapp2.2/System.Diagnostics.TextWriterTraceListener.dll", - "ref/netcoreapp2.2/System.Diagnostics.TextWriterTraceListener.xml", - "ref/netcoreapp2.2/System.Diagnostics.Tools.dll", - "ref/netcoreapp2.2/System.Diagnostics.Tools.xml", - "ref/netcoreapp2.2/System.Diagnostics.TraceSource.dll", - "ref/netcoreapp2.2/System.Diagnostics.TraceSource.xml", - "ref/netcoreapp2.2/System.Diagnostics.Tracing.dll", - "ref/netcoreapp2.2/System.Diagnostics.Tracing.xml", - "ref/netcoreapp2.2/System.Drawing.Primitives.dll", - "ref/netcoreapp2.2/System.Drawing.Primitives.xml", - "ref/netcoreapp2.2/System.Drawing.dll", - "ref/netcoreapp2.2/System.Dynamic.Runtime.dll", - "ref/netcoreapp2.2/System.Globalization.Calendars.dll", - "ref/netcoreapp2.2/System.Globalization.Extensions.dll", - "ref/netcoreapp2.2/System.Globalization.dll", - "ref/netcoreapp2.2/System.IO.Compression.Brotli.dll", - "ref/netcoreapp2.2/System.IO.Compression.FileSystem.dll", - "ref/netcoreapp2.2/System.IO.Compression.ZipFile.dll", - "ref/netcoreapp2.2/System.IO.Compression.ZipFile.xml", - "ref/netcoreapp2.2/System.IO.Compression.dll", - "ref/netcoreapp2.2/System.IO.Compression.xml", - "ref/netcoreapp2.2/System.IO.FileSystem.DriveInfo.dll", - "ref/netcoreapp2.2/System.IO.FileSystem.DriveInfo.xml", - "ref/netcoreapp2.2/System.IO.FileSystem.Primitives.dll", - "ref/netcoreapp2.2/System.IO.FileSystem.Watcher.dll", - "ref/netcoreapp2.2/System.IO.FileSystem.Watcher.xml", - "ref/netcoreapp2.2/System.IO.FileSystem.dll", - "ref/netcoreapp2.2/System.IO.FileSystem.xml", - "ref/netcoreapp2.2/System.IO.IsolatedStorage.dll", - "ref/netcoreapp2.2/System.IO.IsolatedStorage.xml", - "ref/netcoreapp2.2/System.IO.MemoryMappedFiles.dll", - "ref/netcoreapp2.2/System.IO.MemoryMappedFiles.xml", - "ref/netcoreapp2.2/System.IO.Pipes.dll", - "ref/netcoreapp2.2/System.IO.Pipes.xml", - "ref/netcoreapp2.2/System.IO.UnmanagedMemoryStream.dll", - "ref/netcoreapp2.2/System.IO.dll", - "ref/netcoreapp2.2/System.Linq.Expressions.dll", - "ref/netcoreapp2.2/System.Linq.Expressions.xml", - "ref/netcoreapp2.2/System.Linq.Parallel.dll", - "ref/netcoreapp2.2/System.Linq.Parallel.xml", - "ref/netcoreapp2.2/System.Linq.Queryable.dll", - "ref/netcoreapp2.2/System.Linq.Queryable.xml", - "ref/netcoreapp2.2/System.Linq.dll", - "ref/netcoreapp2.2/System.Linq.xml", - "ref/netcoreapp2.2/System.Memory.dll", - "ref/netcoreapp2.2/System.Memory.xml", - "ref/netcoreapp2.2/System.Net.Http.dll", - "ref/netcoreapp2.2/System.Net.Http.xml", - "ref/netcoreapp2.2/System.Net.HttpListener.dll", - "ref/netcoreapp2.2/System.Net.HttpListener.xml", - "ref/netcoreapp2.2/System.Net.Mail.dll", - "ref/netcoreapp2.2/System.Net.Mail.xml", - "ref/netcoreapp2.2/System.Net.NameResolution.dll", - "ref/netcoreapp2.2/System.Net.NameResolution.xml", - "ref/netcoreapp2.2/System.Net.NetworkInformation.dll", - "ref/netcoreapp2.2/System.Net.NetworkInformation.xml", - "ref/netcoreapp2.2/System.Net.Ping.dll", - "ref/netcoreapp2.2/System.Net.Ping.xml", - "ref/netcoreapp2.2/System.Net.Primitives.dll", - "ref/netcoreapp2.2/System.Net.Primitives.xml", - "ref/netcoreapp2.2/System.Net.Requests.dll", - "ref/netcoreapp2.2/System.Net.Requests.xml", - "ref/netcoreapp2.2/System.Net.Security.dll", - "ref/netcoreapp2.2/System.Net.Security.xml", - "ref/netcoreapp2.2/System.Net.ServicePoint.dll", - "ref/netcoreapp2.2/System.Net.ServicePoint.xml", - "ref/netcoreapp2.2/System.Net.Sockets.dll", - "ref/netcoreapp2.2/System.Net.Sockets.xml", - "ref/netcoreapp2.2/System.Net.WebClient.dll", - "ref/netcoreapp2.2/System.Net.WebClient.xml", - "ref/netcoreapp2.2/System.Net.WebHeaderCollection.dll", - "ref/netcoreapp2.2/System.Net.WebHeaderCollection.xml", - "ref/netcoreapp2.2/System.Net.WebProxy.dll", - "ref/netcoreapp2.2/System.Net.WebProxy.xml", - "ref/netcoreapp2.2/System.Net.WebSockets.Client.dll", - "ref/netcoreapp2.2/System.Net.WebSockets.Client.xml", - "ref/netcoreapp2.2/System.Net.WebSockets.dll", - "ref/netcoreapp2.2/System.Net.WebSockets.xml", - "ref/netcoreapp2.2/System.Net.dll", - "ref/netcoreapp2.2/System.Numerics.Vectors.dll", - "ref/netcoreapp2.2/System.Numerics.Vectors.xml", - "ref/netcoreapp2.2/System.Numerics.dll", - "ref/netcoreapp2.2/System.ObjectModel.dll", - "ref/netcoreapp2.2/System.ObjectModel.xml", - "ref/netcoreapp2.2/System.Reflection.DispatchProxy.dll", - "ref/netcoreapp2.2/System.Reflection.DispatchProxy.xml", - "ref/netcoreapp2.2/System.Reflection.Emit.ILGeneration.dll", - "ref/netcoreapp2.2/System.Reflection.Emit.ILGeneration.xml", - "ref/netcoreapp2.2/System.Reflection.Emit.Lightweight.dll", - "ref/netcoreapp2.2/System.Reflection.Emit.Lightweight.xml", - "ref/netcoreapp2.2/System.Reflection.Emit.dll", - "ref/netcoreapp2.2/System.Reflection.Emit.xml", - "ref/netcoreapp2.2/System.Reflection.Extensions.dll", - "ref/netcoreapp2.2/System.Reflection.Metadata.dll", - "ref/netcoreapp2.2/System.Reflection.Metadata.xml", - "ref/netcoreapp2.2/System.Reflection.Primitives.dll", - "ref/netcoreapp2.2/System.Reflection.Primitives.xml", - "ref/netcoreapp2.2/System.Reflection.TypeExtensions.dll", - "ref/netcoreapp2.2/System.Reflection.TypeExtensions.xml", - "ref/netcoreapp2.2/System.Reflection.dll", - "ref/netcoreapp2.2/System.Resources.Reader.dll", - "ref/netcoreapp2.2/System.Resources.ResourceManager.dll", - "ref/netcoreapp2.2/System.Resources.ResourceManager.xml", - "ref/netcoreapp2.2/System.Resources.Writer.dll", - "ref/netcoreapp2.2/System.Resources.Writer.xml", - "ref/netcoreapp2.2/System.Runtime.CompilerServices.VisualC.dll", - "ref/netcoreapp2.2/System.Runtime.CompilerServices.VisualC.xml", - "ref/netcoreapp2.2/System.Runtime.Extensions.dll", - "ref/netcoreapp2.2/System.Runtime.Extensions.xml", - "ref/netcoreapp2.2/System.Runtime.Handles.dll", - "ref/netcoreapp2.2/System.Runtime.InteropServices.RuntimeInformation.dll", - "ref/netcoreapp2.2/System.Runtime.InteropServices.RuntimeInformation.xml", - "ref/netcoreapp2.2/System.Runtime.InteropServices.WindowsRuntime.dll", - "ref/netcoreapp2.2/System.Runtime.InteropServices.WindowsRuntime.xml", - "ref/netcoreapp2.2/System.Runtime.InteropServices.dll", - "ref/netcoreapp2.2/System.Runtime.InteropServices.xml", - "ref/netcoreapp2.2/System.Runtime.Loader.dll", - "ref/netcoreapp2.2/System.Runtime.Loader.xml", - "ref/netcoreapp2.2/System.Runtime.Numerics.dll", - "ref/netcoreapp2.2/System.Runtime.Numerics.xml", - "ref/netcoreapp2.2/System.Runtime.Serialization.Formatters.dll", - "ref/netcoreapp2.2/System.Runtime.Serialization.Formatters.xml", - "ref/netcoreapp2.2/System.Runtime.Serialization.Json.dll", - "ref/netcoreapp2.2/System.Runtime.Serialization.Json.xml", - "ref/netcoreapp2.2/System.Runtime.Serialization.Primitives.dll", - "ref/netcoreapp2.2/System.Runtime.Serialization.Primitives.xml", - "ref/netcoreapp2.2/System.Runtime.Serialization.Xml.dll", - "ref/netcoreapp2.2/System.Runtime.Serialization.Xml.xml", - "ref/netcoreapp2.2/System.Runtime.Serialization.dll", - "ref/netcoreapp2.2/System.Runtime.dll", - "ref/netcoreapp2.2/System.Runtime.xml", - "ref/netcoreapp2.2/System.Security.Claims.dll", - "ref/netcoreapp2.2/System.Security.Claims.xml", - "ref/netcoreapp2.2/System.Security.Cryptography.Algorithms.dll", - "ref/netcoreapp2.2/System.Security.Cryptography.Algorithms.xml", - "ref/netcoreapp2.2/System.Security.Cryptography.Csp.dll", - "ref/netcoreapp2.2/System.Security.Cryptography.Csp.xml", - "ref/netcoreapp2.2/System.Security.Cryptography.Encoding.dll", - "ref/netcoreapp2.2/System.Security.Cryptography.Encoding.xml", - "ref/netcoreapp2.2/System.Security.Cryptography.Primitives.dll", - "ref/netcoreapp2.2/System.Security.Cryptography.Primitives.xml", - "ref/netcoreapp2.2/System.Security.Cryptography.X509Certificates.dll", - "ref/netcoreapp2.2/System.Security.Cryptography.X509Certificates.xml", - "ref/netcoreapp2.2/System.Security.Principal.dll", - "ref/netcoreapp2.2/System.Security.Principal.xml", - "ref/netcoreapp2.2/System.Security.SecureString.dll", - "ref/netcoreapp2.2/System.Security.dll", - "ref/netcoreapp2.2/System.ServiceModel.Web.dll", - "ref/netcoreapp2.2/System.ServiceProcess.dll", - "ref/netcoreapp2.2/System.Text.Encoding.Extensions.dll", - "ref/netcoreapp2.2/System.Text.Encoding.Extensions.xml", - "ref/netcoreapp2.2/System.Text.Encoding.dll", - "ref/netcoreapp2.2/System.Text.RegularExpressions.dll", - "ref/netcoreapp2.2/System.Text.RegularExpressions.xml", - "ref/netcoreapp2.2/System.Threading.Overlapped.dll", - "ref/netcoreapp2.2/System.Threading.Overlapped.xml", - "ref/netcoreapp2.2/System.Threading.Tasks.Dataflow.dll", - "ref/netcoreapp2.2/System.Threading.Tasks.Dataflow.xml", - "ref/netcoreapp2.2/System.Threading.Tasks.Extensions.dll", - "ref/netcoreapp2.2/System.Threading.Tasks.Extensions.xml", - "ref/netcoreapp2.2/System.Threading.Tasks.Parallel.dll", - "ref/netcoreapp2.2/System.Threading.Tasks.Parallel.xml", - "ref/netcoreapp2.2/System.Threading.Tasks.dll", - "ref/netcoreapp2.2/System.Threading.Tasks.xml", - "ref/netcoreapp2.2/System.Threading.Thread.dll", - "ref/netcoreapp2.2/System.Threading.Thread.xml", - "ref/netcoreapp2.2/System.Threading.ThreadPool.dll", - "ref/netcoreapp2.2/System.Threading.ThreadPool.xml", - "ref/netcoreapp2.2/System.Threading.Timer.dll", - "ref/netcoreapp2.2/System.Threading.Timer.xml", - "ref/netcoreapp2.2/System.Threading.dll", - "ref/netcoreapp2.2/System.Threading.xml", - "ref/netcoreapp2.2/System.Transactions.Local.dll", - "ref/netcoreapp2.2/System.Transactions.Local.xml", - "ref/netcoreapp2.2/System.Transactions.dll", - "ref/netcoreapp2.2/System.ValueTuple.dll", - "ref/netcoreapp2.2/System.Web.HttpUtility.dll", - "ref/netcoreapp2.2/System.Web.HttpUtility.xml", - "ref/netcoreapp2.2/System.Web.dll", - "ref/netcoreapp2.2/System.Windows.dll", - "ref/netcoreapp2.2/System.Xml.Linq.dll", - "ref/netcoreapp2.2/System.Xml.ReaderWriter.dll", - "ref/netcoreapp2.2/System.Xml.ReaderWriter.xml", - "ref/netcoreapp2.2/System.Xml.Serialization.dll", - "ref/netcoreapp2.2/System.Xml.XDocument.dll", - "ref/netcoreapp2.2/System.Xml.XDocument.xml", - "ref/netcoreapp2.2/System.Xml.XPath.XDocument.dll", - "ref/netcoreapp2.2/System.Xml.XPath.XDocument.xml", - "ref/netcoreapp2.2/System.Xml.XPath.dll", - "ref/netcoreapp2.2/System.Xml.XPath.xml", - "ref/netcoreapp2.2/System.Xml.XmlDocument.dll", - "ref/netcoreapp2.2/System.Xml.XmlSerializer.dll", - "ref/netcoreapp2.2/System.Xml.XmlSerializer.xml", - "ref/netcoreapp2.2/System.Xml.dll", - "ref/netcoreapp2.2/System.dll", - "ref/netcoreapp2.2/WindowsBase.dll", - "ref/netcoreapp2.2/mscorlib.dll", - "ref/netcoreapp2.2/netstandard.dll", - "runtime.json" - ] - }, - "Microsoft.NETCore.DotNetAppHost/2.2.0": { - "sha512": "DrhaKInRKKvN6Ns2VNIlC7ZffLOp9THf8cO6X4fytPRJovJUbF49/zzx4WfgX9E44FMsw9hT8hrKiIqDSHvGvA==", - "type": "package", - "path": "microsoft.netcore.dotnetapphost/2.2.0", - "files": [ - ".nupkg.metadata", - ".signature.p7s", - "LICENSE.TXT", - "THIRD-PARTY-NOTICES.TXT", - "microsoft.netcore.dotnetapphost.2.2.0.nupkg.sha512", - "microsoft.netcore.dotnetapphost.nuspec", - "runtime.json" - ] - }, - "Microsoft.NETCore.DotNetHostPolicy/2.2.0": { - "sha512": "FJie7IoPZFaPgNDxhZGmDBQP/Bs5vPdfca/G2Wf9gd6LIvMYkZcibtmJwB4tcf4KXkaOYfIOo4Cl9sEPMsSzkw==", - "type": "package", - "path": "microsoft.netcore.dotnethostpolicy/2.2.0", - "files": [ - ".nupkg.metadata", - ".signature.p7s", - "LICENSE.TXT", - "THIRD-PARTY-NOTICES.TXT", - "microsoft.netcore.dotnethostpolicy.2.2.0.nupkg.sha512", - "microsoft.netcore.dotnethostpolicy.nuspec", - "runtime.json" - ] - }, - "Microsoft.NETCore.DotNetHostResolver/2.2.0": { - "sha512": "spDm3AJYmebthDNhzY17YLPtvbc+Y1lCLVeiIH1uLJ/hZaM+40pBiPefFR8J1u66Ndkqi8ipR2tEbqPnYnjRhw==", - "type": "package", - "path": "microsoft.netcore.dotnethostresolver/2.2.0", - "files": [ - ".nupkg.metadata", - ".signature.p7s", - "LICENSE.TXT", - "THIRD-PARTY-NOTICES.TXT", - "microsoft.netcore.dotnethostresolver.2.2.0.nupkg.sha512", - "microsoft.netcore.dotnethostresolver.nuspec", - "runtime.json" - ] - }, - "Microsoft.NETCore.Platforms/2.2.0": { - "sha512": "T/J+XZo+YheFTJh8/4uoeJDdz5qOmOMkjg6/VL8mHJ9AnP8+fmV/kcbxeXsob0irRNiChf+V0ig1MCRLp/+Kog==", - "type": "package", - "path": "microsoft.netcore.platforms/2.2.0", - "files": [ - ".nupkg.metadata", - ".signature.p7s", - "LICENSE.TXT", - "THIRD-PARTY-NOTICES.TXT", - "lib/netstandard1.0/_._", - "microsoft.netcore.platforms.2.2.0.nupkg.sha512", - "microsoft.netcore.platforms.nuspec", - "runtime.json", - "useSharedDesignerContext.txt", - "version.txt" - ] - }, - "Microsoft.NETCore.Targets/2.0.0": { - "sha512": "odP/tJj1z6GylFpNo7pMtbd/xQgTC3Ex2If63dRTL38bBNMwsBnJ+RceUIyHdRBC0oik/3NehYT+oECwBhIM3Q==", - "type": "package", - "path": "microsoft.netcore.targets/2.0.0", - "files": [ - ".nupkg.metadata", - "LICENSE.TXT", - "THIRD-PARTY-NOTICES.TXT", - "lib/netstandard1.0/_._", - "microsoft.netcore.targets.2.0.0.nupkg.sha512", - "microsoft.netcore.targets.nuspec", - "runtime.json", - "useSharedDesignerContext.txt", - "version.txt" - ] - }, - "NETStandard.Library/2.0.3": { - "sha512": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", - "type": "package", - "path": "netstandard.library/2.0.3", - "files": [ - ".nupkg.metadata", - "LICENSE.TXT", - "THIRD-PARTY-NOTICES.TXT", - "build/netstandard2.0/NETStandard.Library.targets", - "build/netstandard2.0/ref/Microsoft.Win32.Primitives.dll", - "build/netstandard2.0/ref/System.AppContext.dll", - "build/netstandard2.0/ref/System.Collections.Concurrent.dll", - "build/netstandard2.0/ref/System.Collections.NonGeneric.dll", - "build/netstandard2.0/ref/System.Collections.Specialized.dll", - "build/netstandard2.0/ref/System.Collections.dll", - "build/netstandard2.0/ref/System.ComponentModel.Composition.dll", - "build/netstandard2.0/ref/System.ComponentModel.EventBasedAsync.dll", - "build/netstandard2.0/ref/System.ComponentModel.Primitives.dll", - "build/netstandard2.0/ref/System.ComponentModel.TypeConverter.dll", - "build/netstandard2.0/ref/System.ComponentModel.dll", - "build/netstandard2.0/ref/System.Console.dll", - "build/netstandard2.0/ref/System.Core.dll", - "build/netstandard2.0/ref/System.Data.Common.dll", - "build/netstandard2.0/ref/System.Data.dll", - "build/netstandard2.0/ref/System.Diagnostics.Contracts.dll", - "build/netstandard2.0/ref/System.Diagnostics.Debug.dll", - "build/netstandard2.0/ref/System.Diagnostics.FileVersionInfo.dll", - "build/netstandard2.0/ref/System.Diagnostics.Process.dll", - "build/netstandard2.0/ref/System.Diagnostics.StackTrace.dll", - "build/netstandard2.0/ref/System.Diagnostics.TextWriterTraceListener.dll", - "build/netstandard2.0/ref/System.Diagnostics.Tools.dll", - "build/netstandard2.0/ref/System.Diagnostics.TraceSource.dll", - "build/netstandard2.0/ref/System.Diagnostics.Tracing.dll", - "build/netstandard2.0/ref/System.Drawing.Primitives.dll", - "build/netstandard2.0/ref/System.Drawing.dll", - "build/netstandard2.0/ref/System.Dynamic.Runtime.dll", - "build/netstandard2.0/ref/System.Globalization.Calendars.dll", - "build/netstandard2.0/ref/System.Globalization.Extensions.dll", - "build/netstandard2.0/ref/System.Globalization.dll", - "build/netstandard2.0/ref/System.IO.Compression.FileSystem.dll", - "build/netstandard2.0/ref/System.IO.Compression.ZipFile.dll", - "build/netstandard2.0/ref/System.IO.Compression.dll", - "build/netstandard2.0/ref/System.IO.FileSystem.DriveInfo.dll", - "build/netstandard2.0/ref/System.IO.FileSystem.Primitives.dll", - "build/netstandard2.0/ref/System.IO.FileSystem.Watcher.dll", - "build/netstandard2.0/ref/System.IO.FileSystem.dll", - "build/netstandard2.0/ref/System.IO.IsolatedStorage.dll", - "build/netstandard2.0/ref/System.IO.MemoryMappedFiles.dll", - "build/netstandard2.0/ref/System.IO.Pipes.dll", - "build/netstandard2.0/ref/System.IO.UnmanagedMemoryStream.dll", - "build/netstandard2.0/ref/System.IO.dll", - "build/netstandard2.0/ref/System.Linq.Expressions.dll", - "build/netstandard2.0/ref/System.Linq.Parallel.dll", - "build/netstandard2.0/ref/System.Linq.Queryable.dll", - "build/netstandard2.0/ref/System.Linq.dll", - "build/netstandard2.0/ref/System.Net.Http.dll", - "build/netstandard2.0/ref/System.Net.NameResolution.dll", - "build/netstandard2.0/ref/System.Net.NetworkInformation.dll", - "build/netstandard2.0/ref/System.Net.Ping.dll", - "build/netstandard2.0/ref/System.Net.Primitives.dll", - "build/netstandard2.0/ref/System.Net.Requests.dll", - "build/netstandard2.0/ref/System.Net.Security.dll", - "build/netstandard2.0/ref/System.Net.Sockets.dll", - "build/netstandard2.0/ref/System.Net.WebHeaderCollection.dll", - "build/netstandard2.0/ref/System.Net.WebSockets.Client.dll", - "build/netstandard2.0/ref/System.Net.WebSockets.dll", - "build/netstandard2.0/ref/System.Net.dll", - "build/netstandard2.0/ref/System.Numerics.dll", - "build/netstandard2.0/ref/System.ObjectModel.dll", - "build/netstandard2.0/ref/System.Reflection.Extensions.dll", - "build/netstandard2.0/ref/System.Reflection.Primitives.dll", - "build/netstandard2.0/ref/System.Reflection.dll", - "build/netstandard2.0/ref/System.Resources.Reader.dll", - "build/netstandard2.0/ref/System.Resources.ResourceManager.dll", - "build/netstandard2.0/ref/System.Resources.Writer.dll", - "build/netstandard2.0/ref/System.Runtime.CompilerServices.VisualC.dll", - "build/netstandard2.0/ref/System.Runtime.Extensions.dll", - "build/netstandard2.0/ref/System.Runtime.Handles.dll", - "build/netstandard2.0/ref/System.Runtime.InteropServices.RuntimeInformation.dll", - "build/netstandard2.0/ref/System.Runtime.InteropServices.dll", - "build/netstandard2.0/ref/System.Runtime.Numerics.dll", - "build/netstandard2.0/ref/System.Runtime.Serialization.Formatters.dll", - "build/netstandard2.0/ref/System.Runtime.Serialization.Json.dll", - "build/netstandard2.0/ref/System.Runtime.Serialization.Primitives.dll", - "build/netstandard2.0/ref/System.Runtime.Serialization.Xml.dll", - "build/netstandard2.0/ref/System.Runtime.Serialization.dll", - "build/netstandard2.0/ref/System.Runtime.dll", - "build/netstandard2.0/ref/System.Security.Claims.dll", - "build/netstandard2.0/ref/System.Security.Cryptography.Algorithms.dll", - "build/netstandard2.0/ref/System.Security.Cryptography.Csp.dll", - "build/netstandard2.0/ref/System.Security.Cryptography.Encoding.dll", - "build/netstandard2.0/ref/System.Security.Cryptography.Primitives.dll", - "build/netstandard2.0/ref/System.Security.Cryptography.X509Certificates.dll", - "build/netstandard2.0/ref/System.Security.Principal.dll", - "build/netstandard2.0/ref/System.Security.SecureString.dll", - "build/netstandard2.0/ref/System.ServiceModel.Web.dll", - "build/netstandard2.0/ref/System.Text.Encoding.Extensions.dll", - "build/netstandard2.0/ref/System.Text.Encoding.dll", - "build/netstandard2.0/ref/System.Text.RegularExpressions.dll", - "build/netstandard2.0/ref/System.Threading.Overlapped.dll", - "build/netstandard2.0/ref/System.Threading.Tasks.Parallel.dll", - "build/netstandard2.0/ref/System.Threading.Tasks.dll", - "build/netstandard2.0/ref/System.Threading.Thread.dll", - "build/netstandard2.0/ref/System.Threading.ThreadPool.dll", - "build/netstandard2.0/ref/System.Threading.Timer.dll", - "build/netstandard2.0/ref/System.Threading.dll", - "build/netstandard2.0/ref/System.Transactions.dll", - "build/netstandard2.0/ref/System.ValueTuple.dll", - "build/netstandard2.0/ref/System.Web.dll", - "build/netstandard2.0/ref/System.Windows.dll", - "build/netstandard2.0/ref/System.Xml.Linq.dll", - "build/netstandard2.0/ref/System.Xml.ReaderWriter.dll", - "build/netstandard2.0/ref/System.Xml.Serialization.dll", - "build/netstandard2.0/ref/System.Xml.XDocument.dll", - "build/netstandard2.0/ref/System.Xml.XPath.XDocument.dll", - "build/netstandard2.0/ref/System.Xml.XPath.dll", - "build/netstandard2.0/ref/System.Xml.XmlDocument.dll", - "build/netstandard2.0/ref/System.Xml.XmlSerializer.dll", - "build/netstandard2.0/ref/System.Xml.dll", - "build/netstandard2.0/ref/System.dll", - "build/netstandard2.0/ref/mscorlib.dll", - "build/netstandard2.0/ref/netstandard.dll", - "build/netstandard2.0/ref/netstandard.xml", - "lib/netstandard1.0/_._", - "netstandard.library.2.0.3.nupkg.sha512", - "netstandard.library.nuspec" - ] - } - }, - "projectFileDependencyGroups": { - ".NETCoreApp,Version=v2.2": [ - "Microsoft.NETCore.App >= 2.2.0" - ] - }, - "packageFolders": { - "/Users/ben/.nuget/packages/": {}, - "/usr/local/share/dotnet/sdk/NuGetFallbackFolder": {} - }, - "project": { - "version": "1.0.0", - "restore": { - "projectUniqueName": "/Users/ben/.vim/bundle/vimspector/support/test/csharp/csharp.csproj", - "projectName": "csharp", - "projectPath": "/Users/ben/.vim/bundle/vimspector/support/test/csharp/csharp.csproj", - "packagesPath": "/Users/ben/.nuget/packages/", - "outputPath": "/Users/ben/.vim/bundle/vimspector/support/test/csharp/obj/", - "projectStyle": "PackageReference", - "fallbackFolders": [ - "/usr/local/share/dotnet/sdk/NuGetFallbackFolder" - ], - "configFilePaths": [ - "/Users/ben/.nuget/NuGet/NuGet.Config" - ], - "originalTargetFrameworks": [ - "netcoreapp2.2" - ], - "sources": { - "https://api.nuget.org/v3/index.json": {} - }, - "frameworks": { - "netcoreapp2.2": { - "projectReferences": {} - } - }, - "warningProperties": { - "warnAsError": [ - "NU1605" - ] - } - }, - "frameworks": { - "netcoreapp2.2": { - "dependencies": { - "Microsoft.NETCore.App": { - "suppressParent": "All", - "target": "Package", - "version": "[2.2.0, )", - "autoReferenced": true - } - }, - "imports": [ - "net461", - "net462", - "net47", - "net471", - "net472", - "net48" - ], - "assetTargetFallback": true, - "warn": true, - "runtimeIdentifierGraphPath": "/usr/local/share/dotnet/sdk/3.1.402/RuntimeIdentifierGraph.json" - } - } - } -} \ No newline at end of file From f389d65a24e02137b62c939264ffeb37952c522a Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 15 Apr 2021 19:12:24 +0100 Subject: [PATCH 41/73] Add a test for csharp, run in CI --- .github/workflows/build.yaml | 5 +++ run_tests | 8 +++- support/test/csharp/.vimspector.json | 4 +- support/test/csharp/csharp.sln | 16 +++++++ tests/ci/image/Dockerfile | 6 +++ tests/language_csharp.test.vim | 65 ++++++++++++++++++++++++++++ 6 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 tests/language_csharp.test.vim diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 17f9601..f4ec9bf 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -111,6 +111,11 @@ jobs: path: gadgets/macos/download name: Cache gadgets + - name: 'Install .NET Core SDK 3.1' + uses: actions/setup-dotnet@v1.7.2 + with: + dotnet-version: 3.1 + - run: vim --version name: 'Print vim version information' diff --git a/run_tests b/run_tests index 39dc7ec..441acb0 100755 --- a/run_tests +++ b/run_tests @@ -91,7 +91,8 @@ if [ "$INSTALL" = "1" ] || [ "$INSTALL" = "script" ]; then if ! python3 $(dirname $0)/install_gadget.py \ --basedir ${BASEDIR} \ ${INSTALLER_ARGS} \ - --all; then + --all \ + --force-enable-csharp; then echo "Script installation reported errors" >&2 exit 1 fi @@ -102,7 +103,7 @@ if [ "$INSTALL" = "1" ] || [ "$INSTALL" = "vim" ]; then --cmd "${BASEDIR_CMD}" \ -c 'autocmd User VimspectorInstallSuccess qa!' \ -c 'autocmd User VimspectorInstallFailed cquit!' \ - -c "VimspectorInstall --all"; then + -c "VimspectorInstall --all netcoredbg"; then echo "Vim installation reported errors" >&2 exit 1 fi @@ -144,6 +145,9 @@ set -e pushd tests/testdata/cpp/simple make clean all popd + pushd support/test/csharp + dotnet build + popd set +e echo "%DONE - built test programs" diff --git a/support/test/csharp/.vimspector.json b/support/test/csharp/.vimspector.json index 3bfb0f3..326739b 100644 --- a/support/test/csharp/.vimspector.json +++ b/support/test/csharp/.vimspector.json @@ -29,7 +29,7 @@ "request": "launch", "program": "${workspaceRoot}/bin/Debug/netcoreapp3.1/csharp.dll", "args": [], - "stopAtEntry": true + "stopAtEntry": false } }, "launch - netcoredbg - with debug log": { @@ -38,7 +38,7 @@ "request": "launch", "program": "${workspaceRoot}/bin/Debug/netcoreapp3.1/csharp.dll", "args": [], - "stopAtEntry": true + "stopAtEntry": false } }, "launch - mono": { diff --git a/support/test/csharp/csharp.sln b/support/test/csharp/csharp.sln index bba50e0..91f59bf 100644 --- a/support/test/csharp/csharp.sln +++ b/support/test/csharp/csharp.sln @@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26124.0 MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "csharp", "csharp.csproj", "{91DB205F-E422-430B-BBB8-955110C7B3B6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,4 +17,18 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x64.ActiveCfg = Debug|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x64.Build.0 = Debug|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x86.ActiveCfg = Debug|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x86.Build.0 = Debug|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|Any CPU.Build.0 = Release|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x64.ActiveCfg = Release|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x64.Build.0 = Release|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x86.ActiveCfg = Release|Any CPU + {91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection EndGlobal diff --git a/tests/ci/image/Dockerfile b/tests/ci/image/Dockerfile index a25febc..164a5a7 100644 --- a/tests/ci/image/Dockerfile +++ b/tests/ci/image/Dockerfile @@ -70,6 +70,12 @@ RUN mkdir -p /home/linuxbrew/.linuxbrew &&\ RUN /home/linuxbrew/.linuxbrew/bin/brew install golang +# dotnet +RUN curl -sSL https://dot.net/v1/dotnet-install.sh \ + | bash /dev/stdin --channel LTS --install-dir /usr/share/dotnet && \ + update-alternatives --install /usr/bin/dotnet dotnet \ + /usr/share/dotnet/dotnet 1 + # clean up RUN /home/linuxbrew/.linuxbrew/bin/brew cleanup && \ rm -rf ~/.cache && \ diff --git a/tests/language_csharp.test.vim b/tests/language_csharp.test.vim new file mode 100644 index 0000000..64cf954 --- /dev/null +++ b/tests/language_csharp.test.vim @@ -0,0 +1,65 @@ +function! SetUp() + call vimspector#test#setup#SetUpWithMappings( v:none ) +endfunction + +function! ClearDown() + call vimspector#test#setup#ClearDown() +endfunction + +function! SetUp_Test_Go_Simple() + let g:vimspector_enable_mappings = 'HUMAN' +endfunction + +function! Test_CSharp_Simple() + let fn='Program.cs' + lcd ../support/test/csharp + exe 'edit ' . fn + + call vimspector#SetLineBreakpoint( fn, 31 ) + call vimspector#LaunchWithSettings( { + \ 'configuration': 'launch - netcoredbg' + \ } ) + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 31, 7 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 31 ) + \ } ) + + call vimspector#StepOver() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 32, 12 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 32 ) + \ } ) + + call vimspector#test#setup#Reset() + + lcd - + %bwipeout! +endfunction + + +function! Test_Run_To_Cursor() + let fn='Program.cs' + lcd ../support/test/csharp + exe 'edit ' . fn + + call vimspector#SetLineBreakpoint( fn, 31 ) + call vimspector#LaunchWithSettings( { + \ 'configuration': 'launch - netcoredbg' + \ } ) + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 31, 7 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 31 ) + \ } ) + + call cursor( 33, 1 ) + call vimspector#RunToCursor() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 33, 1 ) + call WaitForAssert( {-> + \ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 33 ) + \ } ) + + call vimspector#test#setup#Reset() + lcd - + %bwipeout! +endfunction + From bc15c9451375909c6a52cf98c9d2ce8d2a834f41 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 15 Apr 2021 21:39:38 +0100 Subject: [PATCH 42/73] Retire mono debug - never worked and seems abandoned, and vscode-python as it is serious legacy now --- README.md | 102 ++++++---------------------------- python3/vimspector/gadgets.py | 58 ------------------- 2 files changed, 18 insertions(+), 142 deletions(-) diff --git a/README.md b/README.md index ae0ef46..5e05500 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,6 @@ For detailed explanatin of the `.vimspector.json` format, see the * [Python](#python) * [Python Remote Debugging](#python-remote-debugging) * [Python Remote launch and attach](#python-remote-launch-and-attach) - * [Legacy: vscode-python](#legacy-vscode-python) * [TCL](#tcl) * [C♯](#c) * [Go](#go) @@ -145,23 +144,24 @@ runtime dependencies). They are categorised by their level of support: * `Supported` : Fully supported, frequently used and manually tested * `Experimental`: Working, but not frequently used and rarely tested * `Legacy`: No longer supported, please migrate your config +* `Retired`: No longer included or supported. -| Language | Status | Switch (for `install_gadget.py`) | Adapter (for `:VimspectorInstall`) | Dependencies | -|--------------------|--------------|------------------------------------|------------------------------------|--------------------------------------------| -| C, C++, Rust etc. | Tested | `--all` or `--enable-c` (or cpp) | vscode-cpptools | mono-core | -| Rust, C, C++, etc. | Supported | `--force-enable-rust` | CodeLLDB | Python 3 | -| Python | Tested | `--all` or `--enable-python` | debugpy | Python 2.7 or Python 3 | -| Go | Tested | `--enable-go` | vscode-go | Node, Go, [Delve][] | -| TCL | Supported | `--all` or `--enable-tcl` | tclpro | TCL 8.5 | -| Bourne Shell | Supported | `--all` or `--enable-bash` | vscode-bash-debug | Bash v?? | -| Lua | Supported | `--all` or `--enable-lua` | local-lua-debugger-vscode | Node >=12.13.0, Npm, Lua interpreter | -| Node.js | Supported | `--force-enable-node` | vscode-node-debug2 | 6 < Node < 12, Npm | -| Javascript | Supported | `--force-enable-chrome` | debugger-for-chrome | Chrome | -| Java | Supported | `--force-enable-java ` | vscode-java-debug | Compatible LSP plugin (see [later](#java)) | -| C# (dotnet core) | Experimental | `--force-enable-csharp` | netcoredbg | DotNet core | -| C# (mono) | Experimental | `--force-enable-csharp` | vscode-mono-debug | Mono | -| F#, VB, etc. | Experimental | `--force-enable-fsharp` (or vbnet) | netcoredbg | DotNet core | -| Python.legacy | Legacy | `--force-enable-python.legacy` | vscode-python | Node 10, Python 2.7 or Python 3 | +| Language | Status | Switch (for `install_gadget.py`) | Adapter (for `:VimspectorInstall`) | Dependencies | +|--------------------|-----------|----------------------------------|------------------------------------|--------------------------------------------| +| C, C++, Rust etc. | Tested | `--all` or `--enable-c` (or cpp) | vscode-cpptools | mono-core | +| Rust, C, C++, etc. | Supported | `--force-enable-rust` | CodeLLDB | Python 3 | +| Python | Tested | `--all` or `--enable-python` | debugpy | Python 2.7 or Python 3 | +| Go | Tested | `--enable-go` | vscode-go | Node, Go, [Delve][] | +| TCL | Supported | `--all` or `--enable-tcl` | tclpro | TCL 8.5 | +| Bourne Shell | Supported | `--all` or `--enable-bash` | vscode-bash-debug | Bash v?? | +| Lua | Supported | `--all` or `--enable-lua` | local-lua-debugger-vscode | Node >=12.13.0, Npm, Lua interpreter | +| Node.js | Supported | `--force-enable-node` | vscode-node-debug2 | 6 < Node < 12, Npm | +| Javascript | Supported | `--force-enable-chrome` | debugger-for-chrome | Chrome | +| Java | Supported | `--force-enable-java ` | vscode-java-debug | Compatible LSP plugin (see [later](#java)) | +| C# (dotnet core) | Tested | `--force-enable-csharp` | netcoredbg | DotNet core | +| F#, VB, etc. | Supported | `--force-enable-[fsharp,vbnet]` | `, `--force-enable-vbnet` | netcoredbg | DotNet core | +| C# (mono) | _Retired_ | N/A | N/A | N/A | +| Python.legacy | _Retired_ | N/A | N/A | N/A | ## Other languages @@ -526,13 +526,6 @@ Example: "${gadgetDir}/vscode-cpptools/debugAdapters/OpenDebugAD7" ], "name": "cppdbg" - }, - "vscode-python": { - "command": [ - "node", - "${gadgetDir}/vscode-python/out/client/debugger/debugAdapter/main.js" - ], - "name": "vscode-python" } } } @@ -1264,10 +1257,6 @@ Rust is supported with any gdb/lldb-based debugger. So it works fine with headers/libs to build a C python extension for performance. * Full options: https://github.com/microsoft/debugpy/wiki/Debug-configuration-settings - -**Migrating from `vscode-python`**: change `"adapter": "vscode-python"` to -`"adapter": "debugpy"`. - ```json { "configurations": { @@ -1334,34 +1323,6 @@ debugpy](https://github.com/microsoft/debugpy/wiki/Debugging-over-SSH). If you're feeling fancy, checkout the [reference guide][remote-debugging] for an example of getting Vimspector to remotely launch and attach. -### Legacy: vscode-python - -* No longer installed by default - please pass `--force-enable-python.legacy` if - you just want to continue using your working setup. -* [vscode-python](https://github.com/Microsoft/vscode-python) -* NOTE: You must be running `node` 10. See [this issue](https://github.com/puremourning/vimspector/issues/105) - -```json -{ - "configurations": { - ": Launch": { - "adapter": "vscode-python", - "configuration": { - "name": ": Launch", - "type": "python", - "request": "launch", - "cwd": "", - "stopOnEntry": true, - "console": "externalTerminal", - "debugOptions": [], - "program": "" - } - } - ... - } -} -``` - ## TCL * TCL (TclProDebug) @@ -1385,35 +1346,8 @@ netcoredbg` "program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/csharp.dll", "args": [], "stopAtEntry": true, - "cwd": "${workspaceRoot}" - } - } - } -} -``` - -* C# - mono - -Install with `install_gadget.py --force-enable-csharp` or `:VimspectorInstall -vscode-mono-debug`. - -***Known not to work.*** - -```json -{ - "configurations": { - "launch - mono": { - "adapter": "vscode-mono-debug", - "configuration": { - "request": "launch", - "program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/csharp.dll", - "args": [], "cwd": "${workspaceRoot}", - "runtimeExecutable": "mono", - "runtimeArgs": [], - "env": [], - "externalConsole": false, - "console": "integratedTerminal" + "env": {} } } } diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 6b28095..2c60a1a 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -86,29 +86,6 @@ GADGETS = { }, }, }, - 'vscode-python': { - 'language': 'python.legacy', - 'enabled': False, - 'download': { - 'url': 'https://github.com/Microsoft/vscode-python/releases/download/' - '${version}/${file_name}', - }, - 'all': { - 'version': '2019.11.50794', - 'file_name': 'ms-python-release.vsix', - 'checksum': - '6a9edf9ecabed14aac424e6007858068204a3638bf3bb4f235bd6035d823acc6', - }, - 'adapters': { - "vscode-python": { - "name": "vscode-python", - "command": [ - "node", - "${gadgetDir}/vscode-python/out/client/debugger/debugAdapter/main.js", - ], - } - }, - }, 'debugpy': { 'language': 'python', 'download': { @@ -269,41 +246,6 @@ GADGETS = { }, } }, - 'vscode-mono-debug': { - 'language': 'csharp', - 'enabled': False, - 'download': { - 'url': 'https://marketplace.visualstudio.com/_apis/public/gallery/' - 'publishers/ms-vscode/vsextensions/mono-debug/${version}/' - 'vspackage', - 'target': 'vscode-mono-debug.vsix.gz', - 'format': 'zip.gz', - }, - 'all': { - 'file_name': 'vscode-mono-debug.vsix', - 'version': '0.16.2', - 'checksum': - '121eca297d83daeeb1e6e1d791305d1827998dbd595c330086b3b94d33dba3b9', - }, - 'adapters': { - 'vscode-mono-debug': { - "name": "mono-debug", - "command": [ - "mono", - "${gadgetDir}/vscode-mono-debug/bin/Release/mono-debug.exe" - ], - "attach": { - "pidSelect": "none" - }, - "configuration": { - "cwd": "${workspaceRoot}", - "console": "integratedTerminal", - "args": [], - "env": {} - } - }, - } - }, 'vscode-bash-debug': { 'language': 'bash', 'download': { From 1e25313cb5efc014b66a79d84d5c92c9bded6ebf Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 15 Apr 2021 22:52:58 +0100 Subject: [PATCH 43/73] Switch to xcode 11 which apparently works with coreclr debugging https://github.com/dotnet/runtime/issues/42311#issuecomment-700718025 --- .github/workflows/build.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index f4ec9bf..14f5979 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -116,6 +116,11 @@ jobs: with: dotnet-version: 3.1 + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: ^11 + name: "Switch to xcode 11 because of .NET debugging bug" + - run: vim --version name: 'Print vim version information' @@ -148,7 +153,7 @@ jobs: # if: failure() # with: # NGROK_AUTH_TOKEN: ${{ secrets.NGROK_AUTH_TOKEN }} - # SSH_PASS: ${{ secrets.SSH_PASS }} + # SSH_PASS: ${{ secrets.SSH_PASS }} # [V]imspector PublishRelease: runs-on: 'ubuntu-16.04' From 297c0bea56fd3afce5209f47f330880d759c8698 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 20 Apr 2021 20:52:47 +0100 Subject: [PATCH 44/73] Ensure linux tests pass on PR --- .mergify.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.mergify.yml b/.mergify.yml index 09d3d83..0f02002 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -9,9 +9,8 @@ pull_request_rules: # CI https://doc.mergify.io/conditions.html#github-actions - status-success=PythonLint - status-success=VimscriptLint + - status-success=Linux - status-success=MacOS - - actions: &merge-actions merge: method: merge From 026ac22280cc19b7dd7bb3f976968264b6b15aab Mon Sep 17 00:00:00 2001 From: Jade Date: Thu, 22 Apr 2021 03:33:02 -0700 Subject: [PATCH 45/73] Fix some typos in the readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5e05500..e3a5ad5 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ For a tutorial and usage overview, take a look at the [Vimspector website][website]. -For detailed explanatin of the `.vimspector.json` format, see the +For detailed explanation of the `.vimspector.json` format, see the [reference guide][vimspector-ref]. ![Build](https://github.com/puremourning/vimspector/workflows/Build/badge.svg?branch=master) [![Gitter](https://badges.gitter.im/vimspector/Lobby.svg)](https://gitter.im/vimspector/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) @@ -99,7 +99,7 @@ For detailed explanatin of the `.vimspector.json` format, see the # Features and Usage The plugin is a capable Vim graphical debugger for multiple languages. -It's mostly tested for c++, python and TCL, but in theory supports any +It's mostly tested for C++, Python and TCL, but in theory supports any language that Visual Studio Code supports (but see caveats). The [Vimspector website][website] has an overview of the UI, along with basic From 0c88cc8badeeee74f9cafbf461b72769b06a15d5 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 29 Apr 2021 10:02:23 +0100 Subject: [PATCH 46/73] Fix traceback when opening popup in neovim with log visible * We enter the popup window * some log data is received, so we update the log buffer and jump to the log window to scroll it * meanwhile, the WinLeave auto command on the popup window fires and closes the popup window * Having scrolled the log window, we try to jump back to the popup window, which by now has been closed. Fixes #390 --- autoload/vimspector/internal/neojob.vim | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/autoload/vimspector/internal/neojob.vim b/autoload/vimspector/internal/neojob.vim index 0cefc63..a398afe 100644 --- a/autoload/vimspector/internal/neojob.vim +++ b/autoload/vimspector/internal/neojob.vim @@ -159,15 +159,16 @@ function! s:_OnCommandEvent( category, id, data, event ) abort call setbufvar( buffer, '&modified', 0 ) endtry - " if the buffer is visible, scroll it + " if the buffer is visible, scroll it, but don't allow autocommands to fire, + " as this may close the current window! let w = bufwinnr( buffer ) if w > 0 let cw = winnr() try - execute w . 'wincmd w' - normal! Gz- + noautocmd execute w . 'wincmd w' + noautocmd normal! Gz- finally - execute cw . 'wincmd w' + noautocmd execute cw . 'wincmd w' endtry endif elseif a:event ==# 'exit' From 2b844394133343a8868e7b4044ed286d5202fc99 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Mon, 3 May 2021 14:09:14 +0100 Subject: [PATCH 47/73] Lock closed issues after 60 days --- .github/workflows/lock_old_issues.yaml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/lock_old_issues.yaml diff --git a/.github/workflows/lock_old_issues.yaml b/.github/workflows/lock_old_issues.yaml new file mode 100644 index 0000000..d9c3bca --- /dev/null +++ b/.github/workflows/lock_old_issues.yaml @@ -0,0 +1,26 @@ +name: "Lock Old Issues" + +on: + schedule: + - cron: '0 0 * * *' + +jobs: + lock: + runs-on: ubuntu-latest + steps: + - uses: dessant/lock-threads@v2 + with: + github-token: ${{ github.token }} + issue-lock-inactive-days: '60' + # issue-exclude-created-before: '' + # issue-exclude-labels: '' + # issue-lock-labels: '' + # issue-lock-comment: '' + # issue-lock-reason: 'resolved' + # pr-lock-inactive-days: '365' + # pr-exclude-created-before: '' + # pr-exclude-labels: '' + # pr-lock-labels: '' + # pr-lock-comment: '' + # pr-lock-reason: 'resolved' + process-only: 'issues' From a7e8e93920cbdf41eb9334b4998c0688a00b8ef8 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Mon, 3 May 2021 14:09:56 +0100 Subject: [PATCH 48/73] Allow manual running of locker --- .github/workflows/lock_old_issues.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/lock_old_issues.yaml b/.github/workflows/lock_old_issues.yaml index d9c3bca..25d65e0 100644 --- a/.github/workflows/lock_old_issues.yaml +++ b/.github/workflows/lock_old_issues.yaml @@ -3,6 +3,7 @@ name: "Lock Old Issues" on: schedule: - cron: '0 0 * * *' + workflow_dispatch: jobs: lock: From 4e04a862cb37105acebac8b6ac5b275dc7865815 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Mon, 3 May 2021 15:02:50 +0100 Subject: [PATCH 49/73] Add note about existing github issues --- CONTRIBUTING.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1866974..adec034 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -46,6 +46,23 @@ The GitHub issue tracker is for *bug reports* and *features requests* for the Vimspector project, and on-topic comments and follow-ups to them. It is not for general discussion, general support or for any other purpose. +Please **search the issue tracker for similar issues** before creating a new +one. There's no point in duplication; if an existing open issue addresses your +problem, please comment there instead of creating a duplicate. However, if the +issue you found is **closed as resolved** (e.g. with a PR or the original user's +problem was resolved), raise a **new issue**, because you've found a new +problem. Reference the original issue if you think that's useful information. + +Closed issues which have been inactive for 60 days will be locked, this helps to +keep discussions focussed. If you believe you are still experiencing an issue +which has been closed, please raise a new issue, completing the issue template. + +If you do find a similar _open_ issue, **don't just post 'me too' or similar** +responses. This almost never helps resolve the issue, and just causes noise for +the maintainers. Only post if it will aid the maintainers in solving the issue; +if there are existing diagnostics requested in the thread, perform +them and post the results. + Please do not be offended if your Issue or comment is closed or hidden, for any of the following reasons: @@ -53,6 +70,7 @@ of the following reasons: * The issue or comment is off-topic * The issue does not represent a Vimspector bug or feature request * The issue cannot be reasonably reproduced using the minimal vimrc +* The issue is a duplicate of an existing issue * etc. Issue titles are important. It's not usually helpful to write a title like From 08679d1c3ec46edb693e934a3a0f8326280e5893 Mon Sep 17 00:00:00 2001 From: przepompownia Date: Tue, 11 May 2021 00:55:35 +0200 Subject: [PATCH 50/73] Upgrade php-debug to v1.15.1 --- python3/vimspector/gadgets.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 2c60a1a..62321ae 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -323,10 +323,10 @@ GADGETS = { '${version}/${file_name}', }, 'all': { - 'version': 'v1.14.9', - 'file_name': 'php-debug.vsix', + 'version': 'v1.15.1', + 'file_name': 'php-debug-1.15.1.vsix', 'checksum': - '0c5709cbbffe26b12aa63a88142195a9a045a5d8fca7fe63d62c789fe601630d', + '10222655d4179c7d109b1f951d88034eba772b45bf6141dcdb4e9b4477d2e2ab', }, 'adapters': { 'vscode-php-debug': { From 9113dbb6989ff9e289a2d1b8d740774cc33ee024 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 4 May 2021 21:59:44 +0100 Subject: [PATCH 51/73] stack_trace: Add cursorline highlight and sign for current frame --- README.md | 42 +++++---- python3/vimspector/settings.py | 3 +- python3/vimspector/stack_trace.py | 41 +++++++-- .../cpp/simple_c_program/.ycm_extra_conf.py | 2 +- tests/stack_trace.test.vim | 89 +++++++++++++++++++ 5 files changed, 150 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index e3a5ad5..bf84d2f 100644 --- a/README.md +++ b/README.md @@ -1007,6 +1007,8 @@ be changed manually to "switch to" that thread. to set the "focussed" thread to the currently selected one. If the selected line is a stack frame, set the focussed thread to the thread of that frame and jump to that frame in the code window. +* The current frame when a breakpoint is hit or if manuall jumping is also + highlighted. ![stack trace](https://puremourning.github.io/vimspector-web/img/vimspector-callstack-window.png) @@ -1700,22 +1702,26 @@ Vimsector uses them, they will not be replaced. So to customise the signs, define them in your `vimrc`. -| Sign | Description | Priority | -|------------------------|-------------------------------------|----------| -| `vimspectorBP` | Line breakpoint | 9 | -| `vimspectorBPCond` | Conditional line breakpoint | 9 | -| `vimspectorBPDisabled` | Disabled breakpoint | 9 | -| `vimspectorPC` | Program counter (i.e. current line) | 200 | -| `vimspectorPCBP` | Program counter and breakpoint | 200 | +| Sign | Description | Priority | +|---------------------------|-----------------------------------------|----------| +| `vimspectorBP` | Line breakpoint | 9 | +| `vimspectorBPCond` | Conditional line breakpoint | 9 | +| `vimspectorBPDisabled` | Disabled breakpoint | 9 | +| `vimspectorPC` | Program counter (i.e. current line) | 200 | +| `vimspectorPCBP` | Program counter and breakpoint | 200 | +| `vimspectorCurrentThread` | Focussed thread in stack trace view | 200 | +| `vimspectorCurrentFrame` | Current stack frame in stack trace view | 200 | The default symbols are the equivalent of something like the following: ```viml -sign define vimspectorBP text=\ ● texthl=WarningMsg -sign define vimspectorBPCond text=\ ◆ texthl=WarningMsg -sign define vimspectorBPDisabled text=\ ● texthl=LineNr -sign define vimspectorPC text=\ ▶ texthl=MatchParen linehl=CursorLine -sign define vimspectorPCBP text=●▶ texthl=MatchParen linehl=CursorLine +sign define vimspectorBP text=\ ● texthl=WarningMsg +sign define vimspectorBPCond text=\ ◆ texthl=WarningMsg +sign define vimspectorBPDisabled text=\ ● texthl=LineNr +sign define vimspectorPC text=\ ▶ texthl=MatchParen linehl=CursorLine +sign define vimspectorPCBP text=●▶ texthl=MatchParen linehl=CursorLine +sign define vimspectorCurrentThread text=▶ texthl=MatchParen linehl=CursorLine +sign define vimspectorCurrentFrame text=▶ texthl=Special linehl=CursorLine ``` If the signs don't display properly, your font probably doesn't contain these @@ -1723,11 +1729,13 @@ glyphs. You can easily change them by defining the sign in your vimrc. For example, you could put this in your `vimrc` to use some simple ASCII symbols: ```viml -sign define vimspectorBP text=o texthl=WarningMsg -sign define vimspectorBPCond text=o? texthl=WarningMsg -sign define vimspectorBPDisabled text=o! texthl=LineNr -sign define vimspectorPC text=\ > texthl=MatchParen -sign define vimspectorPCBP text=o> texthl=MatchParen +sign define vimspectorBP text=o texthl=WarningMsg +sign define vimspectorBPCond text=o? texthl=WarningMsg +sign define vimspectorBPDisabled text=o! texthl=LineNr +sign define vimspectorPC text=\ > texthl=MatchParen +sign define vimspectorPCBP text=o> texthl=MatchParen +sign define vimspectorCurrentThread text=> texthl=MatchParen +sign define vimspectorCurrentFrame text=> texthl=Special ``` ## Sign priority diff --git a/python3/vimspector/settings.py b/python3/vimspector/settings.py index a060543..89378af 100644 --- a/python3/vimspector/settings.py +++ b/python3/vimspector/settings.py @@ -42,7 +42,8 @@ DEFAULTS = { 'vimspectorBP': 9, 'vimspectorBPCond': 9, 'vimspectorBPDisabled': 9, - 'vimspectorCurrentThread': 200 + 'vimspectorCurrentThread': 200, + 'vimspectorCurrentFrame': 200, }, # Installer diff --git a/python3/vimspector/stack_trace.py b/python3/vimspector/stack_trace.py index ae14e68..f9540ba 100644 --- a/python3/vimspector/stack_trace.py +++ b/python3/vimspector/stack_trace.py @@ -102,7 +102,8 @@ class StackTraceView( object ): self._scratch_buffers = [] # FIXME: This ID is by group, so should be module scope - self._next_sign_id = 1 + self._current_thread_sign_id = 0 # 1 when used + self._current_frame_sign_id = 0 # 2 when used utils.SetUpHiddenBuffer( self._buf, 'vimspector.StackTrace' ) utils.SetUpUIWindow( win ) @@ -127,6 +128,7 @@ class StackTraceView( object ): ':call vimspector#SetCurrentThread()' ) win.options[ 'cursorline' ] = False + win.options[ 'signcolumn' ] = 'auto' if not signs.SignDefined( 'vimspectorCurrentThread' ): @@ -136,6 +138,13 @@ class StackTraceView( object ): texthl = 'MatchParen', linehl = 'CursorLine' ) + if not signs.SignDefined( 'vimspectorCurrentFrame' ): + signs.DefineSign( 'vimspectorCurrentFrame', + text = '▶ ', + double_text = '▶', + texthl = 'Special', + linehl = 'CursorLine' ) + self._line_to_frame = {} self._line_to_thread = {} @@ -157,9 +166,12 @@ class StackTraceView( object ): self._sources = {} self._requesting_threads = StackTraceView.ThreadRequestState.NO self._pending_thread_request = None - if self._next_sign_id: - signs.UnplaceSign( self._next_sign_id, 'VimspectorStackTrace' ) - self._next_sign_id = 0 + if self._current_thread_sign_id: + signs.UnplaceSign( self._current_thread_sign_id, 'VimspectorStackTrace' ) + self._current_thread_sign_id = 0 + if self._current_frame_sign_id: + signs.UnplaceSign( self._current_frame_sign_id, 'VimspectorStackTrace' ) + self._current_frame_sign_id = 0 with utils.ModifiableScratchBuffer( self._buf ): utils.ClearBuffer( self._buf ) @@ -273,10 +285,10 @@ class StackTraceView( object ): self._line_to_frame.clear() self._line_to_thread.clear() - if self._next_sign_id: - signs.UnplaceSign( self._next_sign_id, 'VimspectorStackTrace' ) + if self._current_thread_sign_id: + signs.UnplaceSign( self._current_thread_sign_id, 'VimspectorStackTrace' ) else: - self._next_sign_id = 1 + self._current_thread_sign_id = 1 with utils.ModifiableScratchBuffer( self._buf ): with utils.RestoreCursorPosition(): @@ -290,7 +302,7 @@ class StackTraceView( object ): f'({thread.State()})' ) if self._current_thread == thread.id: - signs.PlaceSign( self._next_sign_id, + signs.PlaceSign( self._current_thread_sign_id, 'VimspectorStackTrace', 'vimspectorCurrentThread', self._buf.name, @@ -421,6 +433,7 @@ class StackTraceView( object ): # Should this set the current _Thread_ too ? If i jump to a frame in # Thread 2, should that become the focussed thread ? self._current_frame = frame + self._DrawThreads() return self._session.SetCurrentFrame( self._current_frame, reason ) return False @@ -518,6 +531,11 @@ class StackTraceView( object ): if not thread.IsExpanded(): return + if self._current_frame_sign_id: + signs.UnplaceSign( self._current_frame_sign_id, 'VimspectorStackTrace' ) + else: + self._current_frame_sign_id = 2 + for frame in thread.stacktrace: if frame.get( 'source' ): source = frame[ 'source' ] @@ -542,6 +560,13 @@ class StackTraceView( object ): source[ 'name' ], frame[ 'line' ] ) ) + if self._current_frame[ 'id' ] == frame[ 'id' ]: + signs.PlaceSign( self._current_frame_sign_id, + 'VimspectorStackTrace', + 'vimspectorCurrentFrame', + self._buf.name, + line ) + self._line_to_frame[ line ] = ( thread, frame ) def _ResolveSource( self, source, and_then ): diff --git a/support/test/cpp/simple_c_program/.ycm_extra_conf.py b/support/test/cpp/simple_c_program/.ycm_extra_conf.py index 0d17586..4203b36 100644 --- a/support/test/cpp/simple_c_program/.ycm_extra_conf.py +++ b/support/test/cpp/simple_c_program/.ycm_extra_conf.py @@ -1,4 +1,4 @@ def Settings( **kwargs ): return { - 'flags': [ '-x', 'c++', '-Wall', '-Wextra' ] + 'flags': [ '-x', 'c++', '-Wall', '-Wextra', '-std=c++17' ] } diff --git a/tests/stack_trace.test.vim b/tests/stack_trace.test.vim index a65ea5e..f191201 100644 --- a/tests/stack_trace.test.vim +++ b/tests/stack_trace.test.vim @@ -379,6 +379,20 @@ function! Test_UpDownStack() \ '$' ) \ ) \ } ) + call win_gotoid( g:vimspector_session_windows.stack_trace ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 1, + \ 'vimspectorCurrentThread', + \ 200 ) } ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 2, + \ 'vimspectorCurrentFrame', + \ 200 ) } ) + wincmd w call vimspector#DownFrame() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 ) @@ -396,6 +410,21 @@ function! Test_UpDownStack() \ '$' ) \ ) \ } ) + call win_gotoid( g:vimspector_session_windows.stack_trace ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 1, + \ 'vimspectorCurrentThread', + \ 200 ) } ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 2, + \ 'vimspectorCurrentFrame', + \ 200 ) } ) + wincmd w + call vimspector#UpFrame() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 ) @@ -413,6 +442,21 @@ function! Test_UpDownStack() \ '$' ) \ ) \ } ) + call win_gotoid( g:vimspector_session_windows.stack_trace ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 1, + \ 'vimspectorCurrentThread', + \ 200 ) } ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 3, + \ 'vimspectorCurrentFrame', + \ 200 ) } ) + wincmd w + call feedkeys( "\VimspectorUpFrame", 'x' ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 23, 1 ) @@ -430,6 +474,21 @@ function! Test_UpDownStack() \ '$' ) \ ) \ } ) + call win_gotoid( g:vimspector_session_windows.stack_trace ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 1, + \ 'vimspectorCurrentThread', + \ 200 ) } ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 4, + \ 'vimspectorCurrentFrame', + \ 200 ) } ) + wincmd w + call feedkeys( "\VimspectorDownFrame", 'x' ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 ) @@ -447,6 +506,21 @@ function! Test_UpDownStack() \ '$' ) \ ) \ } ) + call win_gotoid( g:vimspector_session_windows.stack_trace ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 1, + \ 'vimspectorCurrentThread', + \ 200 ) } ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 3, + \ 'vimspectorCurrentFrame', + \ 200 ) } ) + wincmd w + call vimspector#DownFrame() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 ) @@ -464,6 +538,21 @@ function! Test_UpDownStack() \ '$' ) \ ) \ } ) + call win_gotoid( g:vimspector_session_windows.stack_trace ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 1, + \ 'vimspectorCurrentThread', + \ 200 ) } ) + call WaitForAssert( { -> + \ vimspector#test#signs#AssertSignGroupSingletonAtLine( + \ 'VimspectorStackTrace', + \ 2, + \ 'vimspectorCurrentFrame', + \ 200 ) } ) + wincmd w + call vimspector#ClearBreakpoints() From 0e9497ce8f12d481974397e7c1c7f8378b9bce69 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sat, 15 May 2021 15:50:59 +0100 Subject: [PATCH 52/73] Add cpptools to cpp test proj --- support/test/cpp/simple_c_program/.vimspector.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/support/test/cpp/simple_c_program/.vimspector.json b/support/test/cpp/simple_c_program/.vimspector.json index 7b8c53a..fb4c958 100644 --- a/support/test/cpp/simple_c_program/.vimspector.json +++ b/support/test/cpp/simple_c_program/.vimspector.json @@ -15,6 +15,15 @@ "program": "${workspaceRoot}/test", "stopAtEntry": true } + }, + "cpptools": { + "adapter": "vscode-cpptools", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/test", + "stopOnEntry": true, + "MIMode": "lldb" + } } } } From aacd62f09feed377c35930790514b2739fa08e51 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sat, 15 May 2021 16:03:02 +0100 Subject: [PATCH 53/73] Rename AssertMatchist -> AssertMatchList --- tests/lib/plugin/shared.vim | 2 +- tests/stack_trace.test.vim | 56 ++++++++++++++++++------------------- tests/variables.test.vim | 44 ++++++++++++++--------------- 3 files changed, 51 insertions(+), 51 deletions(-) diff --git a/tests/lib/plugin/shared.vim b/tests/lib/plugin/shared.vim index 70e297e..f98b8e9 100644 --- a/tests/lib/plugin/shared.vim +++ b/tests/lib/plugin/shared.vim @@ -99,7 +99,7 @@ function! ThisTestIsFlaky() let g:test_is_flaky = v:true endfunction -function! AssertMatchist( expected, actual ) abort +function! AssertMatchList( expected, actual ) abort let ret = assert_equal( len( a:expected ), len( a:actual ) ) let len = min( [ len( a:expected ), len( a:actual ) ] ) let idx = 0 diff --git a/tests/stack_trace.test.vim b/tests/stack_trace.test.vim index f191201..b5ed795 100644 --- a/tests/stack_trace.test.vim +++ b/tests/stack_trace.test.vim @@ -30,7 +30,7 @@ function! Test_Multiple_Threads_Continue() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call cursor( 1, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( thread_l ) @@ -45,7 +45,7 @@ function! Test_Multiple_Threads_Continue() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call cursor( 1, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( thread_l ) @@ -56,7 +56,7 @@ function! Test_Multiple_Threads_Continue() \ ) \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ ], @@ -70,7 +70,7 @@ function! Test_Multiple_Threads_Continue() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call cursor( 1, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( thread_l ) @@ -81,7 +81,7 @@ function! Test_Multiple_Threads_Continue() \ ) \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ ], @@ -95,7 +95,7 @@ function! Test_Multiple_Threads_Continue() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call cursor( 1, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( thread_l ) @@ -106,7 +106,7 @@ function! Test_Multiple_Threads_Continue() \ ) \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ ], @@ -121,7 +121,7 @@ function! Test_Multiple_Threads_Continue() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call cursor( 1, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( thread_l ) @@ -132,7 +132,7 @@ function! Test_Multiple_Threads_Continue() \ ) \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ ], @@ -146,7 +146,7 @@ function! Test_Multiple_Threads_Continue() " So we break out of the loop call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, notify_l, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( notify_l ) @@ -157,7 +157,7 @@ function! Test_Multiple_Threads_Continue() \ ) \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ ], @@ -192,7 +192,7 @@ function! Test_Multiple_Threads_Step() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread [0-9]\+: .* (paused)', \ ' .*: .*@threads.cpp:' . string( thread_l ) @@ -205,7 +205,7 @@ function! Test_Multiple_Threads_Step() call vimspector#StepOver() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ ], @@ -218,7 +218,7 @@ function! Test_Multiple_Threads_Step() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ ], @@ -230,7 +230,7 @@ function! Test_Multiple_Threads_Step() call vimspector#StepOver() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)', @@ -244,7 +244,7 @@ function! Test_Multiple_Threads_Step() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)', @@ -257,7 +257,7 @@ function! Test_Multiple_Threads_Step() call vimspector#StepOver() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)', @@ -273,7 +273,7 @@ function! Test_Multiple_Threads_Step() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)', @@ -287,7 +287,7 @@ function! Test_Multiple_Threads_Step() call vimspector#StepOver() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)', @@ -304,7 +304,7 @@ function! Test_Multiple_Threads_Step() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_l, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)', @@ -319,7 +319,7 @@ function! Test_Multiple_Threads_Step() call vimspector#StepOver() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, thread_n, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)', @@ -338,7 +338,7 @@ function! Test_Multiple_Threads_Step() " So we break out of the loop call vimspector#test#signs#AssertCursorIsAtLineInBuffer( s:fn, notify_l, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '+ Thread [0-9]\+: .* (paused)', \ '+ Thread [0-9]\+: .* (paused)', @@ -366,7 +366,7 @@ function! Test_UpDownStack() call vimspector#LaunchWithSettings( { 'configuration': 'run' } ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread 1: MainThread (paused)', \ ' 2: DoSomething@main.py:15', @@ -397,7 +397,7 @@ function! Test_UpDownStack() call vimspector#DownFrame() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread 1: MainThread (paused)', \ ' 2: DoSomething@main.py:15', @@ -429,7 +429,7 @@ function! Test_UpDownStack() call vimspector#UpFrame() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread 1: MainThread (paused)', \ ' 2: DoSomething@main.py:15', @@ -461,7 +461,7 @@ function! Test_UpDownStack() call feedkeys( "\VimspectorUpFrame", 'x' ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 23, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread 1: MainThread (paused)', \ ' 2: DoSomething@main.py:15', @@ -493,7 +493,7 @@ function! Test_UpDownStack() call feedkeys( "\VimspectorDownFrame", 'x' ) call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread 1: MainThread (paused)', \ ' 2: DoSomething@main.py:15', @@ -525,7 +525,7 @@ function! Test_UpDownStack() call vimspector#DownFrame() call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 15, 1 ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Thread 1: MainThread (paused)', \ ' 2: DoSomething@main.py:15', diff --git a/tests/variables.test.vim b/tests/variables.test.vim index c7d373b..59ca2c0 100644 --- a/tests/variables.test.vim +++ b/tests/variables.test.vim @@ -211,7 +211,7 @@ function! Test_ExpandVariables() call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Scope: Locals', \ ' \*- t (Test): {...}', @@ -229,7 +229,7 @@ function! Test_ExpandVariables() " Step - stays expanded call vimspector#StepOver() call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Scope: Locals', \ ' - t (Test): {...}', @@ -278,7 +278,7 @@ function! Test_ExpandVariables() call setpos( '.', [ 0, 2, 1 ] ) call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Scope: Locals', \ ' - t (Test): {...}', @@ -378,7 +378,7 @@ function! Test_ExpandWatch() call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ 'Watches: ----', \ 'Expression: t', @@ -397,7 +397,7 @@ function! Test_ExpandWatch() " Step - stays expanded call vimspector#StepOver() call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ 'Watches: ----', \ 'Expression: t', @@ -449,7 +449,7 @@ function! Test_ExpandWatch() call setpos( '.', [ 0, 3, 1 ] ) call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ 'Watches: ----', \ 'Expression: t', @@ -607,7 +607,7 @@ function! Test_EvaluateFailure() " Add a wtch call vimspector#AddWatch( 'test' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ 'Watches: ----', \ 'Expression: test', @@ -658,7 +658,7 @@ function! Test_VariableEval() \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '{...}', \ ' - i: 0', @@ -690,7 +690,7 @@ function! Test_VariableEval() \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '{...}', \ ' - i: 0', @@ -724,7 +724,7 @@ function! Test_VariableEval() \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ 'Evaluation error', \ ], @@ -768,7 +768,7 @@ function! Test_VariableEvalExpand() \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '{...}', \ ' - i: 0', @@ -786,7 +786,7 @@ function! Test_VariableEvalExpand() call feedkeys( "jjjj\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '{...}', \ ' - i: 0', @@ -806,7 +806,7 @@ function! Test_VariableEvalExpand() call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '{...}', \ ' - i: 0', @@ -863,7 +863,7 @@ function! Test_SetVariableValue_Local() call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Scope: Locals', \ ' \*- t (Test): {...}', @@ -889,7 +889,7 @@ with mock.patch( 'vimspector.utils.InputSave' ): EOF call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Scope: Locals', \ ' \*- t (Test): {...}', @@ -908,7 +908,7 @@ EOF call vimspector#SetVariableValue( '1234' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Scope: Locals', \ ' \*- t (Test): {...}', @@ -927,7 +927,7 @@ EOF call vimspector#SetVariableValue( 'this is invalid' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '- Scope: Locals', \ ' \*- t (Test): {...}', @@ -983,7 +983,7 @@ function! Test_SetVariableValue_Watch() call feedkeys( "\", 'xt' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ 'Watches: ----', \ 'Expression: t', @@ -1012,7 +1012,7 @@ EOF call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ 'Watches: ----', \ 'Expression: t', @@ -1032,7 +1032,7 @@ EOF call vimspector#SetVariableValue( '1234' ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ 'Watches: ----', \ 'Expression: t', @@ -1075,7 +1075,7 @@ function! Test_SetVariableValue_Balloon() \ } ) call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '{...}', \ ' - i: 0', @@ -1102,7 +1102,7 @@ with mock.patch( 'vimspector.utils.InputSave' ): EOF call WaitForAssert( {-> - \ AssertMatchist( + \ AssertMatchList( \ [ \ '{...}', \ ' - i: 0', From d43904eb57c2771c6ba05b48c47da5ff2bbb9735 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sat, 15 May 2021 17:55:01 +0100 Subject: [PATCH 54/73] Add basic VimspectorDebugInfo command --- .github/ISSUE_TEMPLATE/bug_report.md | 6 ++++++ README.md | 2 ++ autoload/vimspector.vim | 8 +++++++ plugin/vimspector.vim | 3 +++ python3/vimspector/debug_session.py | 31 ++++++++++++++++++++++++++++ python3/vimspector/output.py | 26 ++++++++++++++++++----- 6 files changed, 71 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index f01a833..828ec18 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -57,6 +57,12 @@ discussing on Gitter rather than raising an issue. * Version of Vimspector: (e.g. output of `git rev-parse HEAD` if cloned or the name of the tarball used to install otherwise) +* Output of `:VimspectorDebugInfo` + +``` +paste here +``` + * Output of `vim --version` or `nvim --version` ``` diff --git a/README.md b/README.md index bf84d2f..f8db3aa 100644 --- a/README.md +++ b/README.md @@ -1070,6 +1070,8 @@ information when something goes wrong that's not a Vim traceback. If you just want to see the Vimspector log file, use `:VimspectorToggleLog`, which will tail it in a little window (doesn't work on Windows). +You can see some debugging info with `:VimspectorDebugInfo` + ## Closing debugger To close the debugger, use: diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index 1219661..78c7c1b 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -557,6 +557,14 @@ function! vimspector#ShowEvalBalloon( is_visual ) abort \ . '", 0 )' ) endfunction +function! vimspector#PrintDebugInfo() abort + if !s:Enabled() + return + endif + + py3 _vimspector_session.PrintDebugInfo() +endfunction + " Boilerplate {{{ let &cpoptions=s:save_cpo diff --git a/plugin/vimspector.vim b/plugin/vimspector.vim index 27ce473..2668bf1 100644 --- a/plugin/vimspector.vim +++ b/plugin/vimspector.vim @@ -115,6 +115,9 @@ command! -bar -nargs=? -complete=custom,vimspector#CompleteOutput command! -bar \ VimspectorToggleLog \ call vimspector#ToggleLog() +command! -bar + \ VimspectorDebugInfo + \ call vimspector#PrintDebugInfo() command! -nargs=1 -complete=custom,vimspector#CompleteExpr \ VimspectorEval \ call vimspector#Evaluate( ) diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 2f132f9..36ad62b 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -1270,6 +1270,37 @@ class DebugSession( object ): self._stackTraceView.LoadThreads( True ) + @IfConnected() + @RequiresUI() + def PrintDebugInfo( self ): + def Line(): + return ( "--------------------------------------------------------------" + "------------------" ) + + def Pretty( obj ): + if obj is None: + return [ "None" ] + return [ Line() ] + json.dumps( obj, indent=2 ).splitlines() + [ Line() ] + + + debugInfo = [ + "Vimspector Debug Info", + Line(), + f"ConnectionType: { self._connection_type }", + "Adapter: " ] + Pretty( self._adapter ) + [ + "Configuration: " ] + Pretty( self._configuration ) + [ + f"API Prefix: { self._api_prefix }", + f"Launch/Init: { self._launch_complete } / { self._init_complete }", + f"Workspace Root: { self._workspace_root }", + "Launch Config: " ] + Pretty( self._launch_config ) + [ + "Server Capabilities: " ] + Pretty( self._server_capabilities ) + [ + ] + + self._outputView.ClearCategory( 'DebugInfo' ) + self._outputView.Print( "DebugInfo", debugInfo ) + self.ShowOutput( "DebugInfo" ) + + def OnEvent_loadedSource( self, msg ): pass diff --git a/python3/vimspector/output.py b/python3/vimspector/output.py index c453417..8c94b44 100644 --- a/python3/vimspector/output.py +++ b/python3/vimspector/output.py @@ -64,8 +64,11 @@ class OutputView( object ): self._api_prefix = api_prefix VIEWS.add( self ) - def Print( self, categroy, text ): - self._Print( 'server', text.splitlines() ) + def Print( self, category, text: typing.Union[ str, list ] ): + if not isinstance( text, list ): + text = text.splitlines() + + self._Print( category, text ) def OnOutput( self, event ): category = CategoryToBuffer( event.get( 'category' ) or 'output' ) @@ -104,13 +107,26 @@ class OutputView( object ): def Clear( self ): for category, tab_buffer in self._buffers.items(): - if tab_buffer.is_job: - utils.CleanUpCommand( category, self._api_prefix ) - utils.CleanUpHiddenBuffer( tab_buffer.buf ) + self._CleanUpBuffer( category, tab_buffer ) # FIXME: nunmenu the WinBar ? self._buffers = {} + + def ClearCategory( self, category: str ): + if category not in self._buffers: + return + + self._CleanUpBuffer( category, self._buffers[ category ] ) + + + def _CleanUpBuffer( self, category: str, tab_buffer: TabBuffer ): + if tab_buffer.is_job: + utils.CleanUpCommand( category, self._api_prefix ) + + utils.CleanUpHiddenBuffer( tab_buffer.buf ) + + def WindowIsValid( self ): return self._window.valid From daa8865feab2ec32a60ab2fb11b6f33a0cdeadb6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 May 2021 10:56:04 +0000 Subject: [PATCH 55/73] Bump nokogiri from 1.11.3 to 1.11.5 in /docs Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.3 to 1.11.5. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.3...v1.11.5) Signed-off-by: dependabot[bot] --- docs/Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index 6a18520..0fa7776 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -205,14 +205,14 @@ GEM rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) mercenary (0.3.6) - mini_portile2 (2.5.0) + mini_portile2 (2.5.1) minima (2.5.1) jekyll (>= 3.5, < 5.0) jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) minitest (5.14.4) multipart-post (2.1.1) - nokogiri (1.11.3) + nokogiri (1.11.5) mini_portile2 (~> 2.5.0) racc (~> 1.4) octokit (4.20.0) From a51b8b23c9b7e12c2899e423037458d46dbe196e Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 25 May 2021 14:53:29 +0100 Subject: [PATCH 56/73] Fix traceback if the current frame isn't set --- python3/vimspector/stack_trace.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python3/vimspector/stack_trace.py b/python3/vimspector/stack_trace.py index f9540ba..8b1d848 100644 --- a/python3/vimspector/stack_trace.py +++ b/python3/vimspector/stack_trace.py @@ -560,7 +560,8 @@ class StackTraceView( object ): source[ 'name' ], frame[ 'line' ] ) ) - if self._current_frame[ 'id' ] == frame[ 'id' ]: + if ( self._current_frame is not None and + self._current_frame[ 'id' ] == frame[ 'id' ] ): signs.PlaceSign( self._current_frame_sign_id, 'VimspectorStackTrace', 'vimspectorCurrentFrame', From 5ea1f0d9d49011259ecedb70df94c6ff799ead62 Mon Sep 17 00:00:00 2001 From: przepompownia Date: Mon, 7 Jun 2021 14:10:44 +0200 Subject: [PATCH 57/73] Upgrade vscode-php-debug to 1.16.0 --- python3/vimspector/gadgets.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 62321ae..23a298c 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -323,10 +323,10 @@ GADGETS = { '${version}/${file_name}', }, 'all': { - 'version': 'v1.15.1', - 'file_name': 'php-debug-1.15.1.vsix', + 'version': 'v1.16.0', + 'file_name': 'php-debug-1.16.0.vsix', 'checksum': - '10222655d4179c7d109b1f951d88034eba772b45bf6141dcdb4e9b4477d2e2ab', + '62d210f7b87b21315c37ea10a1a5dbae376ff9f963b8f8cf33361e01413731be', }, 'adapters': { 'vscode-php-debug': { From 0500e41429bde17105e931d9920b3c6dbe5eabdb Mon Sep 17 00:00:00 2001 From: Paulo Date: Wed, 9 Jun 2021 19:24:37 +0200 Subject: [PATCH 58/73] FIx typo in configuration.md A small typo that wastes time for people that copy and modify the config file --- docs/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration.md b/docs/configuration.md index a2864b1..3d524bf 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -722,7 +722,7 @@ Vimspector then orchestrates the various tools to set you up. "variables": { // Just an example of how to specify a variable manually rather than // vimspector asking for input from the user - "ServiceName": "${fileBasenameNoExtention}" + "ServiceName": "${fileBasenameNoExtension}" }, "adapter": "python-remote", From 5075f3a11aba4e31cb7994746862a4342c8546ae Mon Sep 17 00:00:00 2001 From: Simon Drake Date: Thu, 24 Jun 2021 14:40:40 +0100 Subject: [PATCH 59/73] Add a runnable Go example --- README.md | 2 +- .../name-starts-with-vowel/.vimspector.json | 29 ++++++++++++++++ .../test/go/name-starts-with-vowel/README.md | 33 +++++++++++++++++++ .../cmd/namestartswithvowel/main.go | 20 +++++++++++ support/test/go/name-starts-with-vowel/go.mod | 3 ++ .../internal/vowels/vowels.go | 9 +++++ .../internal/vowels/vowels_test.go | 30 +++++++++++++++++ 7 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 support/test/go/name-starts-with-vowel/.vimspector.json create mode 100644 support/test/go/name-starts-with-vowel/README.md create mode 100644 support/test/go/name-starts-with-vowel/cmd/namestartswithvowel/main.go create mode 100644 support/test/go/name-starts-with-vowel/go.mod create mode 100644 support/test/go/name-starts-with-vowel/internal/vowels/vowels.go create mode 100644 support/test/go/name-starts-with-vowel/internal/vowels/vowels_test.go diff --git a/README.md b/README.md index f8db3aa..66f2720 100644 --- a/README.md +++ b/README.md @@ -290,7 +290,7 @@ If you just want to try out vimspector without changing your vim config, there are example projects for a number of languages in `support/test`, including: * Python (`support/test/python/simple_python`) -* Go (`support/test/go/hello_world`) +* Go (`support/test/go/hello_world` and `support/test/go/name-starts-with-vowel`) * Nodejs (`support/test/node/simple`) * Chrome (`support/test/chrome/`) * etc. diff --git a/support/test/go/name-starts-with-vowel/.vimspector.json b/support/test/go/name-starts-with-vowel/.vimspector.json new file mode 100644 index 0000000..ffcfc93 --- /dev/null +++ b/support/test/go/name-starts-with-vowel/.vimspector.json @@ -0,0 +1,29 @@ +{ + "configurations": { + "run-cmd": { + "adapter": "vscode-go", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/cmd/namestartswithvowel/main.go", + "mode": "debug", + "dlvToolPath": "$HOME/go/bin/dlv", + "dlvLoadConfig": { + "maxArrayValues": 1000, + "maxStringLen": 1000 + } + } + }, + "test-current-file": { + "adapter": "vscode-go", + "configuration": { + "request": "launch", + "mode": "test", + "program": "${fileDirname}", + "cwd": "${fileDirname}", + "dlvToolPath": "$GOPATH/bin/dlv", + "env": {}, + "args": [] + } + } + } +} diff --git a/support/test/go/name-starts-with-vowel/README.md b/support/test/go/name-starts-with-vowel/README.md new file mode 100644 index 0000000..fec967e --- /dev/null +++ b/support/test/go/name-starts-with-vowel/README.md @@ -0,0 +1,33 @@ +# Purpose + +This example comes with two example vimspector configs for the Go programming language. + +1) `run-cmd` will launch the main programme under `cmd/namestartswithvowel`. +1) `test-current-file` will run the tests in the current file in debug mode. + +## Example use-cases + +### run-cmd + +* Open `cmd/namestartswithvowel/main.go` +* Add a breakpoint somewhere within the programme +* Start the debugger (`:call vimspector#Continue()` or your relevant keymapping) +* Select the first launch configuration (`1: run-cmd`) + +### test-current-file + +* Open `internal/vowels/vowels_test.go` +* Add a breakpoint somewhere within the test +* Start the debugger (`:call vimspector#Continue()` or your relevant keymapping) +* Select the second launch configuration (`2: test-current-file`) + +## Additional Configuration + +There are two additional configuration options specified under `run-cmd`; these parameters configure the maximum string/array size to be shown while debugging. + +``` +"dlvLoadConfig": { + "maxArrayValues": 1000, + "maxStringLen": 1000 +} +``` diff --git a/support/test/go/name-starts-with-vowel/cmd/namestartswithvowel/main.go b/support/test/go/name-starts-with-vowel/cmd/namestartswithvowel/main.go new file mode 100644 index 0000000..c160aea --- /dev/null +++ b/support/test/go/name-starts-with-vowel/cmd/namestartswithvowel/main.go @@ -0,0 +1,20 @@ +package main + +import ( + "fmt" + + "example.com/internal/vowels" +) + +func main() { + names := []string{"Simon", "Bob", "Jennifer", "Amy", "Duke", "Elizabeth"} + + for _, n := range names { + if vowels.NameStartsWithVowel(n) { + fmt.Printf("%s starts with a vowel!\n", n) + continue + } + + fmt.Printf("%s does not start with a vowel!\n", n) + } +} diff --git a/support/test/go/name-starts-with-vowel/go.mod b/support/test/go/name-starts-with-vowel/go.mod new file mode 100644 index 0000000..3070734 --- /dev/null +++ b/support/test/go/name-starts-with-vowel/go.mod @@ -0,0 +1,3 @@ +module example.com + +go 1.16 diff --git a/support/test/go/name-starts-with-vowel/internal/vowels/vowels.go b/support/test/go/name-starts-with-vowel/internal/vowels/vowels.go new file mode 100644 index 0000000..4e76480 --- /dev/null +++ b/support/test/go/name-starts-with-vowel/internal/vowels/vowels.go @@ -0,0 +1,9 @@ +package vowels + +import "strings" + +func NameStartsWithVowel(name string) bool { + s := strings.Split(strings.ToLower(name), "") + + return s[0] == "a" || s[0] == "e" || s[0] == "i" || s[0] == "o" || s[0] == "u" +} diff --git a/support/test/go/name-starts-with-vowel/internal/vowels/vowels_test.go b/support/test/go/name-starts-with-vowel/internal/vowels/vowels_test.go new file mode 100644 index 0000000..e0d5773 --- /dev/null +++ b/support/test/go/name-starts-with-vowel/internal/vowels/vowels_test.go @@ -0,0 +1,30 @@ +package vowels + +import ( + "fmt" + "testing" +) + +func TestNameStartsWithVowel(t *testing.T) { + testCases := []struct { + input string + expectedOutput bool + }{ + { + input: "Simon", + expectedOutput: false, + }, + { + input: "Andy", + expectedOutput: true, + }, + } + for _, tt := range testCases { + t.Run(fmt.Sprintf("%s should product %t", tt.input, tt.expectedOutput), func(t *testing.T) { + out := NameStartsWithVowel(tt.input) + if out != tt.expectedOutput { + t.Errorf("%s produced %t, when %t was expected", tt.input, out, tt.expectedOutput) + } + }) + } +} From 21ebb22fd44c586f6b22ef393012863b6502a010 Mon Sep 17 00:00:00 2001 From: przepompownia Date: Sun, 4 Jul 2021 23:00:32 +0200 Subject: [PATCH 60/73] Upgrade vscode-php-debug to 1.16.1 --- python3/vimspector/gadgets.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 23a298c..240fc68 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -323,10 +323,10 @@ GADGETS = { '${version}/${file_name}', }, 'all': { - 'version': 'v1.16.0', - 'file_name': 'php-debug-1.16.0.vsix', + 'version': 'v1.16.1', + 'file_name': 'php-debug-1.16.1.vsix', 'checksum': - '62d210f7b87b21315c37ea10a1a5dbae376ff9f963b8f8cf33361e01413731be', + '2eb6ff1100b6b3d2d160f243858f3524e269078b8154e108d015882e2c0d52c4', }, 'adapters': { 'vscode-php-debug': { From 3af97f192841247a2891c021d935a2e4f15db7c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Jul 2021 05:43:17 +0000 Subject: [PATCH 61/73] Bump addressable from 2.7.0 to 2.8.0 in /docs Bumps [addressable](https://github.com/sporkmonger/addressable) from 2.7.0 to 2.8.0. - [Release notes](https://github.com/sporkmonger/addressable/releases) - [Changelog](https://github.com/sporkmonger/addressable/blob/main/CHANGELOG.md) - [Commits](https://github.com/sporkmonger/addressable/compare/addressable-2.7.0...addressable-2.8.0) --- updated-dependencies: - dependency-name: addressable dependency-type: indirect ... Signed-off-by: dependabot[bot] --- docs/Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index 0fa7776..acf20f2 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -7,7 +7,7 @@ GEM minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) - addressable (2.7.0) + addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) coffee-script (2.4.1) coffee-script-source From 59c9cd10ab9073b91a11ccd9b21c34d8331fa9cb Mon Sep 17 00:00:00 2001 From: przepompownia Date: Mon, 2 Aug 2021 16:11:04 +0200 Subject: [PATCH 62/73] Upgrade vscode-php-debug to 1.17.0 --- python3/vimspector/gadgets.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 240fc68..170956a 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -323,10 +323,10 @@ GADGETS = { '${version}/${file_name}', }, 'all': { - 'version': 'v1.16.1', - 'file_name': 'php-debug-1.16.1.vsix', + 'version': 'v1.17.0', + 'file_name': 'php-debug-1.17.0.vsix', 'checksum': - '2eb6ff1100b6b3d2d160f243858f3524e269078b8154e108d015882e2c0d52c4', + 'd0fff272503414b6696cc737bc2e18e060fdd5e5dc4bcaf38ae7373afd8d8bc9', }, 'adapters': { 'vscode-php-debug': { From f1e2c12e5bfbb0b9abd1dec75ad8d2810ecc4fc9 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Mon, 2 Aug 2021 16:01:47 +0100 Subject: [PATCH 63/73] Update codelldb Add a way to checksum downloads and a little guide to updating gadgets --- python3/vimspector/gadgets.py | 8 ++++---- run_tests | 4 ++-- support/gadget_upgrade/README.md | 8 ++++++++ support/gadget_upgrade/checksum.py | 13 +++++++++++++ 4 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 support/gadget_upgrade/README.md create mode 100755 support/gadget_upgrade/checksum.py diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 170956a..72f13c8 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -394,12 +394,12 @@ GADGETS = { '${version}/${file_name}', }, 'all': { - 'version': 'v1.6.1', + 'version': 'v1.6.5', }, 'macos': { 'file_name': 'codelldb-x86_64-darwin.vsix', 'checksum': - 'b1c998e7421beea9f3ba21aa5706210bb2249eba93c99b809247ee831075262f', + 'e7d9f4f8ec3c3774af6d1dbf11f0568db1417c4d51038927228cd07028725594', 'make_executable': [ 'adapter/codelldb', 'lldb/bin/debugserver', @@ -410,7 +410,7 @@ GADGETS = { 'linux': { 'file_name': 'codelldb-x86_64-linux.vsix', 'checksum': - 'f2a36cb6971fd95a467cf1a7620e160914e8f11bf82929932ee0aa5afbf6ae6a', + 'eda2cd9b3089dcc0524c273e91ffb5875fe08c930bf643739a2cd1846e1f98d6', 'make_executable': [ 'adapter/codelldb', 'lldb/bin/lldb', @@ -421,7 +421,7 @@ GADGETS = { 'windows': { 'file_name': 'codelldb-x86_64-windows.vsix', 'checksum': - 'ca6a6525bf7719dc95265dc630b3cc817a8c0393b756fd242b710805ffdfb940', + '8ddebe8381a3d22dc3d95139c3797fda06b5cc34aadf300e13b1c516b9da95fe', 'make_executable': [] }, 'adapters': { diff --git a/run_tests b/run_tests index 441acb0..201ec1b 100755 --- a/run_tests +++ b/run_tests @@ -21,7 +21,7 @@ out_fd=1 while [ -n "$1" ]; do case "$1" in - "--basedir") + "--basedir"|"--base-dir"|"--test-base") shift SetBaseDir $1 shift @@ -36,7 +36,7 @@ while [ -n "$1" ]; do INSTALL=$1 shift ;; - "--update") + "--update"|"--upgrade") UPDATE=1 shift ;; diff --git a/support/gadget_upgrade/README.md b/support/gadget_upgrade/README.md new file mode 100644 index 0000000..9ae3d7f --- /dev/null +++ b/support/gadget_upgrade/README.md @@ -0,0 +1,8 @@ +# Manually updating shipped gadgets + +Download the gadget files manuall from their official source into this dir. +Run `./checksum.py ` to get the checksums. + +Update ../../python3/vimspector/gadgets.py with the new version and the +checksums. + diff --git a/support/gadget_upgrade/checksum.py b/support/gadget_upgrade/checksum.py new file mode 100755 index 0000000..d0c1404 --- /dev/null +++ b/support/gadget_upgrade/checksum.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import hashlib +import sys + + +def GetChecksumSHA254( file_path ): + with open( file_path, 'rb' ) as existing_file: + return hashlib.sha256( existing_file.read() ).hexdigest() + + +for arg in sys.argv[ 1: ]: + print( f"{ arg } = { GetChecksumSHA254( arg ) }" ) From 57ce0992803fcf22c0557550fff45e3fe869f707 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 3 Aug 2021 17:29:55 +0100 Subject: [PATCH 64/73] SHow the output in the console, as this is where codelldb puts it --- python3/vimspector/output.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python3/vimspector/output.py b/python3/vimspector/output.py index 8c94b44..3f0da1e 100644 --- a/python3/vimspector/output.py +++ b/python3/vimspector/output.py @@ -32,6 +32,7 @@ class TabBuffer( object ): BUFFER_MAP = { 'console': 'Console', 'stdout': 'Console', + 'output': 'Console', 'stderr': 'stderr', 'telemetry': None, } From 7c7e3f9c3f63de7ef91e5d579662a4e16be95315 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 20 Aug 2021 11:17:05 +0100 Subject: [PATCH 65/73] Add config for bash to tests --- support/test/bash/.vimspector.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 support/test/bash/.vimspector.json diff --git a/support/test/bash/.vimspector.json b/support/test/bash/.vimspector.json new file mode 100644 index 0000000..a1be1b9 --- /dev/null +++ b/support/test/bash/.vimspector.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json", + "configurations": { + "Run Current Script": { + "adapter": "vscode-bash", + "autoselect": false, + "configuration": { + "request": "launch", + "program": "${file}", + "cwd": "${fileDirname}", + "args": [ "*${args}" ] + } + } + } +} From a720d0e1d56743bb1f335b2a4bcb963491e9b421 Mon Sep 17 00:00:00 2001 From: roachsinai Date: Sat, 21 Aug 2021 00:57:27 +0800 Subject: [PATCH 66/73] Fix error: E806: using Float as a String. --- support/custom_ui_vimrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/custom_ui_vimrc b/support/custom_ui_vimrc index a8812cb..e76c6ee 100644 --- a/support/custom_ui_vimrc +++ b/support/custom_ui_vimrc @@ -54,7 +54,7 @@ function s:SetUpTerminal() let padding = 4 let cols = max( [ min( [ &columns - left_bar - code - padding, 80 ] ), 10 ] ) call win_gotoid( terminal_win ) - execute cols . 'wincmd |' + execute string(cols) . 'wincmd |' endfunction function! s:CustomiseWinBar() From 51d78fce5f95fb10ba84b8ab66e97d44d75df010 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 7 Sep 2021 17:00:04 +0100 Subject: [PATCH 67/73] Note on using legacy vscode-dap --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 66f2720..3420d56 100644 --- a/README.md +++ b/README.md @@ -1368,6 +1368,8 @@ Requires: * [Delve][delve-install] installed, e.g. `go get -u github.com/go-delve/delve/cmd/dlv` * Delve to be in your PATH, or specify the `dlvToolPath` launch option +NOTE: Vimspector uses the ["legacy" vscode-go debug adapter](https://github.com/golang/vscode-go/blob/master/docs/debugging-legacy.md) rather than the "built-in" DAP support in Delve. You can track https://github.com/puremourning/vimspector/issues/186 for that. + ```json { "configurations": { @@ -1385,7 +1387,7 @@ Requires: ``` See the vscode-go docs for -[troubleshooting information](https://github.com/golang/vscode-go/blob/master/docs/debugging.md#troubleshooting) +[troubleshooting information](https://github.com/golang/vscode-go/blob/master/docs/debugging-legacy.md#troubleshooting) ## PHP From 46cfdc678dbdbb162f8cb8ab4384897e1a3d3bd0 Mon Sep 17 00:00:00 2001 From: Sebastian Goth Date: Wed, 8 Sep 2021 12:19:51 +0200 Subject: [PATCH 68/73] Update vscode-cpptools from 0.27.0 to 1.6.0 --- python3/vimspector/gadgets.py | 10 +++++----- python3/vimspector/installer.py | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 72f13c8..dda962d 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -30,12 +30,12 @@ GADGETS = { root, gadget ), 'all': { - 'version': '0.27.0', + 'version': '1.6.0', "adapters": { "vscode-cpptools": { "name": "cppdbg", "command": [ - "${gadgetDir}/vscode-cpptools/debugAdapters/OpenDebugAD7" + "${gadgetDir}/vscode-cpptools/debugAdapters/bin/OpenDebugAD7" ], "attach": { "pidProperty": "processId", @@ -53,17 +53,17 @@ GADGETS = { 'linux': { 'file_name': 'cpptools-linux.vsix', 'checksum': - '3695202e1e75a03de18049323b66d868165123f26151f8c974a480eaf0205435', + 'c25299bcfb46b22d41aa3f125df7184e6282a35ff9fb69c47def744cb4778f55', }, 'macos': { 'file_name': 'cpptools-osx.vsix', 'checksum': - 'cb061e3acd7559a539e5586f8d3f535101c4ec4e8a48195856d1d39380b5cf3c', + 'ae21cde361335b350402904991cf9f746fec685449ca9bd5d50227c3dec3719b', }, 'windows': { 'file_name': 'cpptools-win32.vsix', 'checksum': - 'aa294368ed16d48c59e49c8000e146eae5a19ad07b654efed5db8ec93b24229e', + 'ef7ac5831874a3c7dbf0feb826bfda2be579aff9b6d990622fff1d0d4ede00d1', "adapters": { "vscode-cpptools": { "name": "cppdbg", diff --git a/python3/vimspector/installer.py b/python3/vimspector/installer.py index f0f85a4..a81db8f 100644 --- a/python3/vimspector/installer.py +++ b/python3/vimspector/installer.py @@ -358,7 +358,8 @@ def InstallCppTools( name, root, gadget ): # It's hilarious, but the execute bits aren't set in the vsix. So they # actually have javascript code which does this. It's just a horrible horrible # hack that really is not funny. - MakeExecutable( os.path.join( extension, 'debugAdapters', 'OpenDebugAD7' ) ) + MakeExecutable( + os.path.join( extension, 'debugAdapters', 'bin', 'OpenDebugAD7' ) ) with open( os.path.join( extension, 'package.json' ) ) as f: package = json.load( f ) runtime_dependencies = package[ 'runtimeDependencies' ] From 561a5b9aa2c0c0a9f801b12af3cd7ef861fad962 Mon Sep 17 00:00:00 2001 From: Sebastian Goth Date: Wed, 8 Sep 2021 21:36:37 +0200 Subject: [PATCH 69/73] Update variables tests to expect register scope vscode-cpptools 1.6.0 now reports an additional scope 'Registers' after 'Locals'. --- tests/variables.test.vim | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/variables.test.vim b/tests/variables.test.vim index 59ca2c0..c00fb7f 100644 --- a/tests/variables.test.vim +++ b/tests/variables.test.vim @@ -194,6 +194,7 @@ function! Test_ExpandVariables() \ [ \ '- Scope: Locals', \ ' *+ t (Test): {...}', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -219,6 +220,7 @@ function! Test_ExpandVariables() \ ' \*- c (char): 0 ''\\0\{1,3}''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -237,6 +239,7 @@ function! Test_ExpandVariables() \ ' - c (char): 0 ''\\0\{1,3}''', \ ' - fffff (float): 0', \ ' + another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -253,6 +256,7 @@ function! Test_ExpandVariables() \ [ \ '- Scope: Locals', \ ' + t (Test): {...}', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -267,6 +271,7 @@ function! Test_ExpandVariables() \ [ \ '- Scope: Locals', \ ' + t (Test): {...}', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -286,6 +291,7 @@ function! Test_ExpandVariables() \ ' \*- c (char): 99 ''c''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -302,6 +308,7 @@ function! Test_ExpandVariables() \ assert_equal( \ [ \ '+ Scope: Locals', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -316,6 +323,7 @@ function! Test_ExpandVariables() \ assert_equal( \ [ \ '+ Scope: Locals', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -331,6 +339,7 @@ function! Test_ExpandVariables() \ assert_equal( \ [ \ '+ Scope: Locals', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -846,6 +855,7 @@ function! Test_SetVariableValue_Local() \ [ \ '- Scope: Locals', \ ' *+ t (Test): {...}', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -871,6 +881,7 @@ function! Test_SetVariableValue_Local() \ ' \*- c (char): 0 ''\\0\{1,3}''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -897,6 +908,7 @@ EOF \ ' \*- c (char): 0 ''\\0\{1,3}''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -916,6 +928,7 @@ EOF \ ' \*- c (char): 0 ''\\0\{1,3}''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -935,6 +948,7 @@ EOF \ ' \*- c (char): 0 ''\\0\{1,3}''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, From 17ca1522f8a0cca53c8ab75a680f27ea58b50de3 Mon Sep 17 00:00:00 2001 From: Sebastian Goth Date: Wed, 8 Sep 2021 23:16:47 +0200 Subject: [PATCH 70/73] Use correct spelling of MIMode in tests --- tests/testdata/cpp/simple/.vimspector.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/testdata/cpp/simple/.vimspector.json b/tests/testdata/cpp/simple/.vimspector.json index 0dca061..48ce801 100644 --- a/tests/testdata/cpp/simple/.vimspector.json +++ b/tests/testdata/cpp/simple/.vimspector.json @@ -12,7 +12,7 @@ "externalConsole": false, "stopAtEntry": true, "stopOnEntry": true, - "MImode": "${VIMSPECTOR_MIMODE}" + "MIMode": "${VIMSPECTOR_MIMODE}" }, "breakpoints": { "exception": { @@ -33,7 +33,7 @@ "externalConsole": false, "stopAtEntry": false, "stopOnEntry": false, - "MImode": "${VIMSPECTOR_MIMODE}" + "MIMode": "${VIMSPECTOR_MIMODE}" }, "breakpoints": { "exception": { @@ -55,7 +55,7 @@ "externalConsole": false, "stopAtEntry": false, "stopOnEntry": false, - "MImode": "${VIMSPECTOR_MIMODE}" + "MIMode": "${VIMSPECTOR_MIMODE}" }, "breakpoints": { "exception": { @@ -82,7 +82,7 @@ "configuration": { "request": "launch", "program": "${workspaceRoot}/${fileBasenameNoExtension}", - "MImode": "${VIMSPECTOR_MIMODE}", + "MIMode": "${VIMSPECTOR_MIMODE}", "externalConsole": false, "args": [ "CALCULATED_LIST", "${CALCULATED_LIST}", From db5ed8e80228fbb5366e6fc7629e430f886d2b34 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 8 Sep 2021 22:20:33 +0100 Subject: [PATCH 71/73] Update to ubuntu 18.04 as 16.04 is deprecated --- .github/workflows/build.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 14f5979..f186f5d 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -13,7 +13,7 @@ defaults: jobs: PythonLint: - runs-on: ubuntu-16.04 + runs-on: ubuntu-18.04 container: 'puremourning/vimspector:test' steps: - uses: actions/checkout@v2 @@ -22,7 +22,7 @@ jobs: - name: 'Run flake8' run: '$HOME/.local/bin/flake8 python3/ *.py' VimscriptLint: - runs-on: 'ubuntu-16.04' + runs-on: 'ubuntu-18.04' container: 'puremourning/vimspector:test' steps: - uses: actions/checkout@v2 @@ -32,7 +32,7 @@ jobs: run: $HOME/.local/bin/vint autoload/ compiler/ plugin/ tests/ syntax/ Linux: - runs-on: 'ubuntu-16.04' + runs-on: 'ubuntu-18.04' container: image: 'puremourning/vimspector:test' options: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined @@ -156,7 +156,7 @@ jobs: # SSH_PASS: ${{ secrets.SSH_PASS }} # [V]imspector PublishRelease: - runs-on: 'ubuntu-16.04' + runs-on: 'ubuntu-18.04' needs: - Linux - MacOS From dc862fe565a74a9810f37edaa8d0e1bb7bbdd79d Mon Sep 17 00:00:00 2001 From: Sebastian Goth Date: Thu, 9 Sep 2021 16:42:49 +0200 Subject: [PATCH 72/73] Readme: pretty printing with vscode-cpptools / gdb --- README.md | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3420d56..d198292 100644 --- a/README.md +++ b/README.md @@ -61,9 +61,10 @@ For detailed explanation of the `.vimspector.json` format, see the * [Closing debugger](#closing-debugger) * [Terminate debuggee](#terminate-debuggee) * [Debug profile configuration](#debug-profile-configuration) - * [C, C , Rust, etc.](#c-c-rust-etc) - * [C Remote debugging](#c-remote-debugging) - * [C Remote launch and attach](#c-remote-launch-and-attach) + * [C, C++, Rust, etc.](#c-c-rust-etc) + * [Data visualization / pretty printing](#data-visualization--pretty-printing) + * [C++ Remote debugging](#c-remote-debugging) + * [C++ Remote launch and attach](#c-remote-launch-and-attach) * [Rust](#rust) * [Python](#python) * [Python Remote Debugging](#python-remote-debugging) @@ -1176,6 +1177,38 @@ licensing. } ``` +### Data visualization / pretty printing + +Depending on the backend you need to enable pretty printing of complex types manually. + +* LLDB: Pretty printing is enabled by default + +* GDB: To enable gdb pretty printers, consider the snippet below. + It is not enough to have `set print pretty on` in your .gdbinit! + +``` +{ + "configurations": { + "Launch": { + "adapter": "vscode-cpptools", + "configuration": { + "request": "launch", + "program": "", + ... + "MIMode": "gdb" + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + } + } + } +} +``` + ### C++ Remote debugging The cpptools documentation describes how to attach cpptools to gdbserver using From 7c12519b9d87f261abfff62f4f197c693a0ffb4f Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Fri, 10 Sep 2021 10:30:44 -0600 Subject: [PATCH 73/73] Modify for mac m1 --- python3/vimspector/gadgets.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index dda962d..02eb0e7 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -56,9 +56,9 @@ GADGETS = { 'c25299bcfb46b22d41aa3f125df7184e6282a35ff9fb69c47def744cb4778f55', }, 'macos': { - 'file_name': 'cpptools-osx.vsix', + 'file_name': 'cpptools-osx-arm64.vsix', 'checksum': - 'ae21cde361335b350402904991cf9f746fec685449ca9bd5d50227c3dec3719b', + 'ceb3e8cdaa2b5bb45af50913ddd8402089969748af8d70f5d46480408287ba6f', }, 'windows': { 'file_name': 'cpptools-win32.vsix', @@ -394,12 +394,12 @@ GADGETS = { '${version}/${file_name}', }, 'all': { - 'version': 'v1.6.5', + 'version': 'v1.6.6', }, 'macos': { - 'file_name': 'codelldb-x86_64-darwin.vsix', + 'file_name': 'codelldb-aarch64-darwin.vsix', 'checksum': - 'e7d9f4f8ec3c3774af6d1dbf11f0568db1417c4d51038927228cd07028725594', + '5adc3b9139eabdafd825bd5efc55df4424a203fb2b6087b425cd434956e7ec58', 'make_executable': [ 'adapter/codelldb', 'lldb/bin/debugserver',