diff --git a/autoload/vimspector/internal/balloon.vim b/autoload/vimspector/internal/balloon.vim new file mode 100644 index 0000000..783c516 --- /dev/null +++ b/autoload/vimspector/internal/balloon.vim @@ -0,0 +1,34 @@ +" vimspector - A multi-language debugging system for Vim +" Copyright 2018 Ben Jackson +" +" Licensed under the Apache License, Version 2.0 (the "License"); +" you may not use this file except in compliance with the License. +" You may obtain a copy of the License at +" +" http://www.apache.org/licenses/LICENSE-2.0 +" +" Unless required by applicable law or agreed to in writing, software +" distributed under the License is distributed on an "AS IS" BASIS, +" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +" See the License for the specific language governing permissions and +" limitations under the License. + + +" Boilerplate {{{ +let s:save_cpo = &cpo +set cpo&vim +" }}} + +function vimspector#internal#balloon#BalloonExpr() + " winnr + 1 because for *no good reason* winnr is 0 based here unlike + " everywhere else + " int() because for *no good reason* winnr is a string. + py3 _vimspector_session.ShowBalloon( int( vim.eval( 'v:beval_winnr' ) ) + 1, + \ vim.eval( 'v:beval_text' ) ) + return '' +endfunction + +" Boilerplate {{{ +let &cpo=s:save_cpo +unlet s:save_cpo +" }}} diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 76267a2..9260b4b 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -186,6 +186,14 @@ class DebugSession( object ): def DeleteWatch( self ): self._variablesView.DeleteWatch() + def ShowBalloon( self, winnr, expression ): + if winnr == int( self._codeView._window.number ): + self._variablesView.ShowBalloon( self._currentFrame, expression ) + else: + self._logger.debug( 'Winnr {0} is not the code window {1}'.format( + winnr, + self._codeView._window.number ) ) + def GoToFrame( self ): self._stackTraceView.GoToFrame() @@ -244,11 +252,11 @@ class DebugSession( object ): self._logger.info( 'Debug Adapter Started' ) def _StopDebugAdapter( self, callback = None ): - self._codeView.Clear() - def handler( message ): vim.eval( 'vimspector#internal#job#StopDebugSession()' ) self._connection = None + self._stackTraceView.ConnectionClosed() + self._variablesView.ConnectionClosed() if callback: callback() @@ -261,7 +269,6 @@ class DebugSession( object ): def _Initialise( self ): - # TODO: name is mandatory. forcefully add it self._connection.DoRequest( None, { 'command': 'initialize', 'arguments': { @@ -271,6 +278,8 @@ class DebugSession( object ): 'pathFormat': 'path', }, } ) + # FIXME: name is mandatory. Forcefully add it (we should really use the + # _actual_ name, but that isn't actually remembered at this point) if 'name' not in self._configuration[ 'configuration' ]: self._configuration[ 'configuration' ][ 'name' ] = 'test' @@ -294,27 +303,17 @@ class DebugSession( object ): pass def OnEvent_breakpoint( self, message ): - # Useful: - # - # /** The reason for the event. - # Values: 'changed', 'new', 'removed', etc. - # */ - reason = message[ 'body' ][ 'reason' ] bp = message[ 'body' ][ 'breakpoint' ] if reason == 'changed': self._codeView.UpdateBreakpoint( bp ) elif reason == 'new': self._codeView.AddBreakpoints( None, bp ) - elif reason == 'removed': - # TODO - pass else: utils.UserMessage( 'Unrecognised breakpoint event (undocumented): {0}'.format( reason ), persist = True ) - def OnEvent_terminated( self, message ): utils.UserMessage( "The program was terminated because: {0}".format( message.get( 'body', {} ).get( 'reason', "No specific reason" ) ) ) @@ -326,7 +325,6 @@ class DebugSession( object ): with utils.ModifiableScratchBuffer( self._threadsBuffer ): self._threadsBuffer[:] = None - def _SendBreakpoints( self ): for file_name, line_breakpoints in self._breakpoints.items(): breakpoints = [] @@ -360,19 +358,6 @@ class DebugSession( object ): } ) - # TODO: Remove this! - # self._connection.DoRequest( - # functools.partial( self._UpdateBreakpoints, None ), - # { - # 'command': 'setFunctionBreakpoints', - # 'arguments': { - # 'breakpoints': [ - # { 'name': 'main' }, - # ], - # }, - # } - # ) - self._connection.DoRequest( None, { 'command': 'configurationDone', } ) diff --git a/python3/vimspector/stack_trace.py b/python3/vimspector/stack_trace.py index 84f271f..4cd790b 100644 --- a/python3/vimspector/stack_trace.py +++ b/python3/vimspector/stack_trace.py @@ -34,6 +34,10 @@ class StackTraceView( object ): with utils.ModifiableScratchBuffer( self._buf ): self._buf[:] = None + def ConnectionClosed( self ): + self.Clear() + self._connection = None + def LoadStackTrace( self, thread_id ): self._connection.DoRequest( self._PrintStackTrace, { 'command': 'stackTrace', diff --git a/python3/vimspector/variables.py b/python3/vimspector/variables.py index c3dd5f4..517d670 100644 --- a/python3/vimspector/variables.py +++ b/python3/vimspector/variables.py @@ -51,10 +51,19 @@ class VariablesView( object ): utils.SetUpScratchBuffer( self._buf, 'vimspector.Variables' ) + vim.options[ 'balloonexpr' ] = 'vimspector#internal#balloon#BalloonExpr()' + vim.options[ 'ballooneval' ] = True + vim.options[ 'balloonevalterm' ] = True + vim.options[ 'balloondelay' ] = 250 + def Clear( self ): with utils.ModifiableScratchBuffer( self._buf ): self._buf[:] = None + def ConnectionClosed( self ): + self.Clear() + self._connection = None + def LoadScopes( self, frame ): def scopes_consumer( message ): self._scopes = [] @@ -198,3 +207,20 @@ class VariablesView( object ): parent[ '_variables' ].append( variable ) self._DrawScopesAndWatches() + + def ShowBalloon( self, frame, expression ): + if not self._connection: + return + + def handler( message ): + vim.eval( "balloon_show( '{0}' )".format( + message[ 'body' ][ 'result' ] ) ) + + self._connection.DoRequest( handler, { + 'command': 'evaluate', + 'arguments': { + 'expression': expression, + 'frameId': frame[ 'id' ], + 'context': 'hover', + } + } )