diff --git a/.gitignore b/.gitignore index b09d196..64341cf 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,5 @@ README.md.toc.* support/test/csharp/*.exe* .neomake.log configurations/ +venv/ +test-base/ diff --git a/autoload/vimspector/internal/neojob.vim b/autoload/vimspector/internal/neojob.vim index f005a62..8bcae90 100644 --- a/autoload/vimspector/internal/neojob.vim +++ b/autoload/vimspector/internal/neojob.vim @@ -176,6 +176,7 @@ function! s:SetUpHiddenBuffer( buffer ) abort call setbufvar( a:buffer, '&bufhidden', 'hide' ) call setbufvar( a:buffer, '&wrap', 0 ) call setbufvar( a:buffer, '&swapfile', 0 ) + call setbufvar( a:buffer, '&textwidth', 0 ) call s:MakeBufferReadOnly( a:buffer ) endfunction diff --git a/python3/vimspector/code.py b/python3/vimspector/code.py index b7e88d7..b826d21 100644 --- a/python3/vimspector/code.py +++ b/python3/vimspector/code.py @@ -220,7 +220,6 @@ class CodeView( object ): options = { 'vertical': 1, - 'term_cols': 80, 'norestore': 1, 'cwd': cwd, 'env': env, diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 32f9be7..1302ab6 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -62,11 +62,13 @@ class DebugSession( object ): self._run_on_server_exit = None + self._configuration = None + self._adapter = None + self._ResetServerState() def _ResetServerState( self ): self._connection = None - self._configuration = None self._init_complete = False self._launch_complete = False self._on_init_complete_handlers = [] @@ -278,11 +280,7 @@ class DebugSession( object ): start() def Restart( self ): - # TODO: There is a restart message but isn't always supported. - # FIXME: For some reason this doesn't work when run from the WinBar. It just - # beeps and doesn't display the config selector. One option is to just not - # display the selector and restart with the same opitons. - if not self._configuration or not self._adapter: + if self._configuration is None or self._adapter is None: return self.Start() self._StartWithConfiguration( self._configuration, self._adapter ) @@ -294,7 +292,8 @@ class DebugSession( object ): if not self._connection: utils.UserMessage( 'Vimspector not connected, start a debug session first', - persist=True, error=True ) + persist=True, + error=True ) return return fct( self, *args, **kwargs ) return wrapper @@ -595,6 +594,9 @@ class DebugSession( object ): "Shutting down debug adapter..." ) 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 diff --git a/python3/vimspector/stack_trace.py b/python3/vimspector/stack_trace.py index 4504d10..0afeb81 100644 --- a/python3/vimspector/stack_trace.py +++ b/python3/vimspector/stack_trace.py @@ -35,6 +35,7 @@ class StackTraceView( object ): self._threads = [] self._sources = {} + self._scratch_buffers = [] utils.SetUpHiddenBuffer( self._buf, 'vimspector.StackTrace' ) @@ -82,6 +83,11 @@ class StackTraceView( object ): def Reset( self ): self.Clear() utils.CleanUpHiddenBuffer( self._buf ) + for b in self._scratch_buffers: + utils.CleanUpHiddenBuffer( b ) + + self._scratch_buffers = [] + self._buf = None def LoadThreads( self, infer_current_frame ): pending_request = False @@ -290,7 +296,8 @@ class StackTraceView( object ): self._logger.debug( "Received source %s: %s", buf_name, msg ) buf = utils.BufferForFile( buf_name ) - utils.SetUpScratchBuffer( buf, buf_name ) + self._scratch_buffers.append( buf ) + utils.SetUpHiddenBuffer( buf, buf_name ) source[ 'path' ] = buf_name with utils.ModifiableScratchBuffer( buf ): utils.SetBufferContents( buf, msg[ 'body' ][ 'content' ] ) diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 03dbb4d..48991f7 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -52,6 +52,14 @@ def BufferForFile( file_name ): return vim.buffers[ BufferNumberForFile( file_name ) ] +def WindowForBuffer( buf ): + for w in vim.current.tabpage.windows: + if w.buffer == buf: + return w + + return None + + def OpenFileInCurrentWindow( file_name ): buffer_number = BufferNumberForFile( file_name ) try: @@ -136,6 +144,7 @@ def SetUpPromptBuffer( buf, name, prompt, callback ): def SetUpUIWindow( win ): win.options[ 'wrap' ] = False win.options[ 'number' ] = False + win.options[ 'relativenumber' ] = False win.options[ 'signcolumn' ] = 'no' win.options[ 'spell' ] = False win.options[ 'list' ] = False @@ -190,6 +199,18 @@ def RestoreCurrentBuffer( window ): vim.current.buffer = old_buffer +@contextlib.contextmanager +def AnyWindowForBuffer( buf ): + # Only checks the current tab page, which is what we want + current_win = WindowForBuffer( buf ) + if current_win is not None: + with LetCurrentWindow( current_win ): + yield + else: + with LetCurrentBuffer( buf ): + yield + + @contextlib.contextmanager def LetCurrentWindow( window ): with RestoreCurrentWindow(): @@ -566,11 +587,11 @@ def SetSyntax( current_syntax, syntax, *args ): if current_syntax == syntax: return + # We use set syn= because just setting vim.Buffer.options[ 'syntax' ] + # doesn't actually trigger the Syntax autocommand, and i'm not sure that + # 'doautocmd Syntax' is the right solution or not for buf in args: - with LetCurrentBuffer( buf ): - # We use set syn= because just setting vim.Buffer.options[ 'syntax' ] - # doesn't actually trigger the Syntax autocommand, and i'm not sure that - # 'doautocmd Syntax' is the right solution or not + with AnyWindowForBuffer( buf ): vim.command( 'set syntax={}'.format( Escape( syntax ) ) ) return syntax diff --git a/python3/vimspector/variables.py b/python3/vimspector/variables.py index 1cbf599..f6df06c 100644 --- a/python3/vimspector/variables.py +++ b/python3/vimspector/variables.py @@ -23,6 +23,11 @@ from vimspector import utils class Expandable: + EXPANDED_BY_USER = 2 + EXPANDED_BY_US = 1 + COLLAPSED_BY_USER = 0 + COLLAPSED_BY_DEFAULT = None + """Base for anything which might contain a hierarchy of values represented by a 'variablesReference' to be resolved by the 'variables' request. Records the current state expanded/collapsed. Implementations just implement @@ -32,16 +37,13 @@ class Expandable: # None is Falsy and represents collapsed _by default_. WHen set to False, # this means the user explicitly collapsed it. When True, the user expanded # it (or we expanded it by default). - self.expanded: bool = None + self.expanded: int = Expandable.COLLAPSED_BY_DEFAULT - def IsCollapsedByUser( self ): - return self.expanded is False - - def IsExpandedByUser( self ): - return self.expanded is True + def IsExpanded( self ): + return bool( self.expanded ) def ShouldDrawDrillDown( self ): - return self.IsExpandedByUser() and self.variables is not None + return self.IsExpanded() and self.variables is not None def IsExpandable( self ): return self.VariablesReference() > 0 @@ -205,6 +207,7 @@ class VariablesView( object ): def LoadScopes( self, frame ): def scopes_consumer( message ): new_scopes = [] + expanded_some_scope = False for scope_body in message[ 'body' ][ 'scopes' ]: # Find it in the scopes list found = False @@ -221,11 +224,17 @@ class VariablesView( object ): new_scopes.append( scope ) - if not scope.scope.get( 'expensive' ) and not scope.IsCollapsedByUser(): - # Expand any non-expensive scope which is not manually collapsed - scope.expanded = True + # Expand the first non-expensive scope which is not manually collapsed + if ( not expanded_some_scope + and not scope.scope.get( 'expensive' ) + and scope.expanded is not Expandable.COLLAPSED_BY_USER ): + scope.expanded = Expandable.EXPANDED_BY_US + expanded_some_scope = True + elif ( expanded_some_scope and scope.expanded is + Expandable.EXPANDED_BY_US ): + scope.expanded = Expandable.COLLAPSED_BY_DEFAULT - if scope.IsExpandedByUser(): + if scope.IsExpanded(): self._connection.DoRequest( partial( self._ConsumeVariables, self._DrawScopes, scope ), { @@ -293,7 +302,7 @@ class VariablesView( object ): watch.result = WatchResult( message[ 'body' ] ) if ( watch.result.IsExpandable() and - watch.result.IsExpandedByUser() ): + watch.result.IsExpanded() ): self._connection.DoRequest( partial( self._ConsumeVariables, self._watch.draw, watch.result ), { @@ -319,16 +328,16 @@ class VariablesView( object ): variable = view.lines[ current_line ] - if variable.expanded: + if variable.IsExpanded(): # Collapse - variable.expanded = False + variable.expanded = Expandable.COLLAPSED_BY_USER view.draw() return if not variable.IsExpandable(): return - variable.expanded = True + variable.expanded = Expandable.EXPANDED_BY_USER self._connection.DoRequest( partial( self._ConsumeVariables, view.draw, variable ), { @@ -348,11 +357,11 @@ class VariablesView( object ): indent = ' ' * ( indent - 1 ), marker = '*' if variable.changed else ' ', icon = '+' if ( variable.IsExpandable() - and not variable.IsExpandedByUser() ) else '-', + and not variable.IsExpanded() ) else '-', name = variable.variable[ 'name' ], - type_ = variable.variable.get( 'type', '' ), + type_ = variable.variable.get( 'type', '' ), value = variable.variable.get( 'value', - '' ) ).split( '\n' ) ) + '' ) ).split( '\n' ) ) view.lines[ line ] = variable if variable.ShouldDrawDrillDown(): @@ -386,7 +395,7 @@ class VariablesView( object ): self._DrawWatchResult( 2, watch ) def _DrawScope( self, indent, scope ): - icon = '+' if scope.IsExpandable() and not scope.IsExpandedByUser() else '-' + icon = '+' if scope.IsExpandable() and not scope.IsExpanded() else '-' line = utils.AppendToBuffer( self._vars.buf, '{0}{1} Scope: {2}'.format( @@ -405,7 +414,7 @@ class VariablesView( object ): assert indent > 0 icon = '+' if ( watch.result.IsExpandable() and - not watch.result.IsExpandedByUser() ) else '-' + not watch.result.IsExpanded() ) else '-' line = '{indent}{marker}{icon} Result: {result}'.format( # We borrow 1 space of indent to draw the change marker @@ -442,7 +451,7 @@ class VariablesView( object ): new_variables.append( variable ) - if variable.IsExpandable() and variable.IsExpandedByUser(): + if variable.IsExpandable() and variable.IsExpanded(): self._connection.DoRequest( partial( self._ConsumeVariables, draw, variable ), { diff --git a/support/test/java/test_project/src/main/java/com/vimspector/test/Base.java b/support/test/java/test_project/src/main/java/com/vimspector/test/Base.java index 25840d0..1cd89e5 100644 --- a/support/test/java/test_project/src/main/java/com/vimspector/test/Base.java +++ b/support/test/java/test_project/src/main/java/com/vimspector/test/Base.java @@ -1,8 +1,11 @@ package com.vimspector.test; -class Base { +public class Base +{ public String DoSomething() { - return ""; + String s = new String(); + s.replace( "A", "B" ); + return s; } } diff --git a/support/test/java/test_project/src/main/java/com/vimspector/test/TestApplication.java b/support/test/java/test_project/src/main/java/com/vimspector/test/TestApplication.java index 680dbb6..264c0e6 100644 --- a/support/test/java/test_project/src/main/java/com/vimspector/test/TestApplication.java +++ b/support/test/java/test_project/src/main/java/com/vimspector/test/TestApplication.java @@ -24,16 +24,6 @@ public class TestApplication { } } - private static class TestGeneric { - T t; - public TestGeneric( T t ) { - this.t = t; - } - public void DoSomethingUseful() { - System.out.println( t.DoSomething() ); - } - } - private static void DoGeneric( T b ) { TestGeneric foo = new TestGeneric<>( b ); foo.DoSomethingUseful(); diff --git a/support/test/java/test_project/src/main/java/com/vimspector/test/TestGeneric.java b/support/test/java/test_project/src/main/java/com/vimspector/test/TestGeneric.java new file mode 100644 index 0000000..6cd5e01 --- /dev/null +++ b/support/test/java/test_project/src/main/java/com/vimspector/test/TestGeneric.java @@ -0,0 +1,16 @@ +package com.vimspector.test; + +class TestGeneric { + T base; + + public TestGeneric( T b ) + { + this.base = b; + } + + public String DoSomethingUseful() { + String s = "A B C" + base.DoSomething(); + + return s.replace( "B", "C" ); + } +}