From 0d112d70a0f6adccbfd9e7e60bb6e327ebab5fbc Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 13 Oct 2020 22:16:11 +0100 Subject: [PATCH] Add SetLineBreakpoint and ClaerLineBreakpoint APIs These are useful for running tests (i.e. ensure there's a breakpiont at the start of the test) and/or other programmatic usages. They will also be needed for setting temporary breakpionts. --- autoload/vimspector.vim | 25 +++++++ python3/vimspector/breakpoints.py | 108 +++++++++++++++++----------- python3/vimspector/debug_session.py | 6 ++ python3/vimspector/signs.py | 4 +- python3/vimspector/utils.py | 6 +- 5 files changed, 105 insertions(+), 44 deletions(-) diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index 68c49b4..f4d2f58 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -76,6 +76,31 @@ function! vimspector#ToggleBreakpoint( ... ) abort py3 _vimspector_session.ToggleBreakpoint( vim.eval( 'options' ) ) endfunction +function! vimspector#SetLineBreakpoint( file_name, line_num, ... ) abort + if !s:enabled + return + endif + if a:0 == 0 + let options = {} + else + let options = a:1 + endif + py3 _vimspector_session.SetLineBreakpoint( + \ vim.eval( 'a:file_name' ), + \ int( vim.eval( 'a:line_num' ) ), + \ vim.eval( 'options' ) ) +endfunction + +function! vimspector#ClearLineBreakpoint( file_name, line_num ) abort + if !s:enabled + return + endif + py3 _vimspector_session.ClearLineBreakpoint( + \ vim.eval( 'a:file_name' ), + \ int( vim.eval( 'a:line_num' ) ) ) +endfunction + + function! vimspector#AddFunctionBreakpoint( function, ... ) abort if !s:enabled return diff --git a/python3/vimspector/breakpoints.py b/python3/vimspector/breakpoints.py index 6ab14f5..f5999c3 100644 --- a/python3/vimspector/breakpoints.py +++ b/python3/vimspector/breakpoints.py @@ -141,50 +141,74 @@ class ProjectBreakpoints( object ): self.UpdateUI() + def _FindLineBreakpoint( self, file_name, line ): + file_name = os.path.abspath( file_name ) + for index, bp in enumerate( self._line_breakpoints[ file_name ] ): + self._SignToLine( file_name, bp ) + if bp[ 'line' ] == line: + return bp, index + + return None, None + + + def _PutLineBreakpoint( self, file_name, line, options ): + self._line_breakpoints[ os.path.abspath( file_name ) ].append( { + 'state': 'ENABLED', + 'line': line, + 'options': options, + # 'sign_id': , + # + # Used by other breakpoint types (specified in options): + # 'condition': ..., + # 'hitCondition': ..., + # 'logMessage': ... + } ) + + + def _DeleteLineBreakpoint( self, bp, file_name, index ): + if 'sign_id' in bp: + signs.UnplaceSign( bp[ 'sign_id' ], 'VimspectorBP' ) + del self._line_breakpoints[ os.path.abspath( file_name ) ][ index ] + + def ToggleBreakpoint( self, options ): - line, column = vim.current.window.cursor + line, _ = vim.current.window.cursor file_name = vim.current.buffer.name if not file_name: return - found_bp = False - action = 'New' - for index, bp in enumerate( self._line_breakpoints[ file_name ] ): - self._SignToLine( file_name, bp ) - if bp[ 'line' ] == line: - found_bp = True - if bp[ 'state' ] == 'ENABLED' and not self._connection: - bp[ 'state' ] = 'DISABLED' - action = 'Disable' - else: - if 'sign_id' in bp: - signs.UnplaceSign( bp[ 'sign_id' ], 'VimspectorBP' ) - del self._line_breakpoints[ file_name ][ index ] - action = 'Delete' - break - - self._logger.debug( "Toggle found bp at {}:{} ? {} ({})".format( - file_name, - line, - found_bp, - action ) ) - - if not found_bp: - self._line_breakpoints[ file_name ].append( { - 'state': 'ENABLED', - 'line': line, - 'options': options, - # 'sign_id': , - # - # Used by other breakpoint types (specified in options): - # 'condition': ..., - # 'hitCondition': ..., - # 'logMessage': ... - } ) + bp, index = self._FindLineBreakpoint( file_name, line ) + if bp is None: + # ADD + self._PutLineBreakpoint( file_name, line, options ) + elif bp[ 'state' ] == 'ENABLED' and not self._connection: + # DISABLE + bp[ 'state' ] = 'DISABLED' + else: + # DELETE + self._DeleteLineBreakpoint( bp, file_name, index ) self.UpdateUI() + + def SetLineBreakpoint( self, file_name, line_num, options ): + bp, _ = self._FindLineBreakpoint( file_name, line_num ) + if bp is not None: + bp[ 'options' ] = options + return + self._PutLineBreakpoint( file_name, line_num, options ) + self.UpdateUI() + + + def ClearLineBreakpoint( self, file_name, line_num ): + bp, index = self._FindLineBreakpoint( file_name, line_num ) + if bp is None: + return + self._DeleteLineBreakpoint( bp, file_name, index ) + self.UpdateUI() + + def AddFunctionBreakpoint( self, function, options ): self._func_breakpoints.append( { 'state': 'ENABLED', @@ -386,17 +410,21 @@ class ProjectBreakpoints( object ): else 'vimspectorBPCond' if 'condition' in bp[ 'options' ] else 'vimspectorBP' ) - signs.PlaceSign( bp[ 'sign_id' ], - 'VimspectorBP', - sign, - file_name, - bp[ 'line' ] ) + if utils.BufferNumberForFile( file_name, False ) > 0: + signs.PlaceSign( bp[ 'sign_id' ], + 'VimspectorBP', + sign, + file_name, + bp[ 'line' ] ) def _SignToLine( self, file_name, bp ): if 'sign_id' not in bp: return bp[ 'line' ] + if utils.BufferNumberForFile( file_name, False ) <= 0: + return bp[ 'line' ] + signs = vim.eval( "sign_getplaced( '{}', {} )".format( utils.Escape( file_name ), json.dumps( { 'id': bp[ 'sign_id' ], 'group': 'VimspectorBP', } ) ) ) diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index ccec07b..85f32da 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -1165,6 +1165,12 @@ class DebugSession( object ): def ToggleBreakpoint( self, options ): return self._breakpoints.ToggleBreakpoint( options ) + def SetLineBreakpoint( self, file_name, line_num, options ): + return self._breakpoints.SetLineBreakpoint( file_name, line_num, options ) + + def ClearLineBreakpoint( self, file_name, line_num ): + return self._breakpoints.ClearLineBreakpoint( file_name, line_num ) + def ClearBreakpoints( self ): if self._connection: self._codeView.ClearBreakpoints() diff --git a/python3/vimspector/signs.py b/python3/vimspector/signs.py index c51bd76..39d1f03 100644 --- a/python3/vimspector/signs.py +++ b/python3/vimspector/signs.py @@ -29,7 +29,7 @@ def DefineSign( name, text, double_text, texthl, col = 'right', **kwargs ): vim.command( cmd ) -def PlaceSign( sign_id, group, name, file, line ): +def PlaceSign( sign_id, group, name, file_name, line ): priority = settings.Dict( 'sign_priority' )[ name ] cmd = ( f'sign place { sign_id } ' @@ -37,7 +37,7 @@ def PlaceSign( sign_id, group, name, file, line ): f'name={ name } ' f'priority={ priority } ' f'line={ line } ' - f'file={ file }' ) + f'file={ file_name }' ) vim.command( cmd ) diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 879e910..4ce387d 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -45,8 +45,10 @@ _logger = logging.getLogger( __name__ ) SetUpLogging( _logger ) -def BufferNumberForFile( file_name ): - return int( vim.eval( "bufnr( '{0}', 1 )".format( Escape( file_name ) ) ) ) +def BufferNumberForFile( file_name, create = True ): + return int( vim.eval( "bufnr( '{0}', {1} )".format( + Escape( file_name ), + int( create ) ) ) ) def BufferForFile( file_name ):