From d81bdf30efaefc017eb4e6fc707d69e5dd94d02a Mon Sep 17 00:00:00 2001 From: __ <__@__> Date: Sat, 6 Feb 2021 00:52:11 +0100 Subject: [PATCH 01/11] Emit User VimspectorFrameWasSet event --- python3/vimspector/debug_session.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 36e6feb..275fa72 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -710,6 +710,7 @@ class DebugSession( object ): self._stackTraceView.SetSyntax( self._codeView.current_syntax ) self._variablesView.LoadScopes( frame ) self._variablesView.EvaluateWatches() + vim.command( 'doautocmd User VimspectorFrameWasSet' ) if reason == 'stopped': self._breakpoints.ClearTemporaryBreakpoint( frame[ 'source' ][ 'path' ], From 0bb8416e116254047e7822c0271006daeb71dce3 Mon Sep 17 00:00:00 2001 From: __ <__@__> Date: Sat, 6 Feb 2021 13:10:38 +0100 Subject: [PATCH 02/11] Add test --- tests/ui.test.vim | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/ui.test.vim b/tests/ui.test.vim index b6c8feb..ea90f82 100644 --- a/tests/ui.test.vim +++ b/tests/ui.test.vim @@ -409,3 +409,18 @@ function! Test_CustomWinBar() call vimspector#test#setup#Reset() %bwipe! endfunction + +function! Test_VimspectorFrameWasSet() + augroup TestVimspectorFrameWasSet + au! + au User VimspectorFrameWasSet let b:vimspectorStepIsThere = 'foo' + augroup END + + call s:StartDebugging() + call assert_equal( 'foo', getbufvar(bufnr(), 'vimspectorStepIsThere', 0) ) + + au! TestVimspectorFrameWasSet + unlet b:vimspectorStepIsThere + call vimspector#test#setup#Reset() + %bwipe! +endfunction From 840ee09242b107e815aad7306f3bfe7e34e3ac18 Mon Sep 17 00:00:00 2001 From: __ <__@__> Date: Sat, 6 Feb 2021 14:48:39 +0100 Subject: [PATCH 03/11] Send an event before leave buffer in window --- python3/vimspector/debug_session.py | 1 - python3/vimspector/utils.py | 7 +++++++ tests/ui.test.vim | 8 ++++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 275fa72..36e6feb 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -710,7 +710,6 @@ class DebugSession( object ): self._stackTraceView.SetSyntax( self._codeView.current_syntax ) self._variablesView.LoadScopes( frame ) self._variablesView.EvaluateWatches() - vim.command( 'doautocmd User VimspectorFrameWasSet' ) if reason == 'stopped': self._breakpoints.ClearTemporaryBreakpoint( frame[ 'source' ][ 'path' ], diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 4022315..eda958b 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -76,7 +76,14 @@ def WindowForBuffer( buf ): def OpenFileInCurrentWindow( file_name ): buffer_number = BufferNumberForFile( file_name ) try: + if "vimspectorStep" in vim.current.buffer.vars: + del vim.current.buffer.vars["vimspectorStep"] + # @todo: what if the same buffer is still visited by another thread + vim.command( 'doautocmd User VimspectorFrameLeavePre' ) + vim.current.buffer = vim.buffers[ buffer_number ] + vim.current.buffer.vars["vimspectorStep"] = 1 + vim.command( 'doautocmd User VimspectorFrameWasSet' ) except vim.error as e: if 'E325' not in str( e ): raise diff --git a/tests/ui.test.vim b/tests/ui.test.vim index ea90f82..91cd214 100644 --- a/tests/ui.test.vim +++ b/tests/ui.test.vim @@ -410,16 +410,16 @@ function! Test_CustomWinBar() %bwipe! endfunction -function! Test_VimspectorFrameWasSet() - augroup TestVimspectorFrameWasSet +function! Test_VimspectorFrameEnter() + augroup TestVimspectorFrameEnter au! - au User VimspectorFrameWasSet let b:vimspectorStepIsThere = 'foo' + au User VimspectorFrameEnter let b:vimspectorStepIsThere = 'foo' augroup END call s:StartDebugging() call assert_equal( 'foo', getbufvar(bufnr(), 'vimspectorStepIsThere', 0) ) - au! TestVimspectorFrameWasSet + au! TestVimspectorFrameEnter unlet b:vimspectorStepIsThere call vimspector#test#setup#Reset() %bwipe! From 716181e056eda0778179ff767cb9b5446a4f8aaf Mon Sep 17 00:00:00 2001 From: __ <__@__> Date: Sat, 6 Feb 2021 14:50:01 +0100 Subject: [PATCH 04/11] fixup! Send an event before leave buffer in window --- python3/vimspector/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index eda958b..3ab31bc 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -83,7 +83,7 @@ def OpenFileInCurrentWindow( file_name ): vim.current.buffer = vim.buffers[ buffer_number ] vim.current.buffer.vars["vimspectorStep"] = 1 - vim.command( 'doautocmd User VimspectorFrameWasSet' ) + vim.command( 'doautocmd User VimspectorFrameEnter' ) except vim.error as e: if 'E325' not in str( e ): raise From 50dc55e0e827d82babeab8c534cebdff3113ad90 Mon Sep 17 00:00:00 2001 From: __ <__@__> Date: Sat, 6 Feb 2021 15:01:54 +0100 Subject: [PATCH 05/11] Fix errors reported by flake8 --- python3/vimspector/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 3ab31bc..5281ec8 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -77,12 +77,12 @@ def OpenFileInCurrentWindow( file_name ): buffer_number = BufferNumberForFile( file_name ) try: if "vimspectorStep" in vim.current.buffer.vars: - del vim.current.buffer.vars["vimspectorStep"] + del vim.current.buffer.vars[ "vimspectorStep" ] # @todo: what if the same buffer is still visited by another thread vim.command( 'doautocmd User VimspectorFrameLeavePre' ) vim.current.buffer = vim.buffers[ buffer_number ] - vim.current.buffer.vars["vimspectorStep"] = 1 + vim.current.buffer.vars[ "vimspectorStep" ] = 1 vim.command( 'doautocmd User VimspectorFrameEnter' ) except vim.error as e: if 'E325' not in str( e ): From bcf4120ba48afea716f6fa1149265da79f0c2610 Mon Sep 17 00:00:00 2001 From: przepompownia Date: Wed, 17 Feb 2021 01:04:49 +0100 Subject: [PATCH 06/11] Do not send event after leave buffer. --- python3/vimspector/code.py | 1 + python3/vimspector/utils.py | 7 ------- tests/ui.test.vim | 8 ++++---- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/python3/vimspector/code.py b/python3/vimspector/code.py index d3c6324..98aeca5 100644 --- a/python3/vimspector/code.py +++ b/python3/vimspector/code.py @@ -134,6 +134,7 @@ class CodeView( object ): utils.JumpToWindow( self._window ) try: utils.OpenFileInCurrentWindow( frame[ 'source' ][ 'path' ] ) + vim.command( 'doautocmd User VimspectorJumpedToFrame' ) except vim.error: self._logger.exception( 'Unexpected vim error opening file {}'.format( frame[ 'source' ][ 'path' ] ) ) diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 5281ec8..4022315 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -76,14 +76,7 @@ def WindowForBuffer( buf ): def OpenFileInCurrentWindow( file_name ): buffer_number = BufferNumberForFile( file_name ) try: - if "vimspectorStep" in vim.current.buffer.vars: - del vim.current.buffer.vars[ "vimspectorStep" ] - # @todo: what if the same buffer is still visited by another thread - vim.command( 'doautocmd User VimspectorFrameLeavePre' ) - vim.current.buffer = vim.buffers[ buffer_number ] - vim.current.buffer.vars[ "vimspectorStep" ] = 1 - vim.command( 'doautocmd User VimspectorFrameEnter' ) except vim.error as e: if 'E325' not in str( e ): raise diff --git a/tests/ui.test.vim b/tests/ui.test.vim index 91cd214..390f870 100644 --- a/tests/ui.test.vim +++ b/tests/ui.test.vim @@ -410,16 +410,16 @@ function! Test_CustomWinBar() %bwipe! endfunction -function! Test_VimspectorFrameEnter() - augroup TestVimspectorFrameEnter +function! Test_VimspectorJumpedToFrame() + augroup TestVimspectorJumpedToFrame au! - au User VimspectorFrameEnter let b:vimspectorStepIsThere = 'foo' + au User VimspectorJumpedToFrame let b:vimspectorStepIsThere = 'foo' augroup END call s:StartDebugging() call assert_equal( 'foo', getbufvar(bufnr(), 'vimspectorStepIsThere', 0) ) - au! TestVimspectorFrameEnter + au! TestVimspectorJumpedToFrame unlet b:vimspectorStepIsThere call vimspector#test#setup#Reset() %bwipe! From 3c54cd268f210b9eefa802b7ac8a5eb09e23683c Mon Sep 17 00:00:00 2001 From: przepompownia Date: Wed, 17 Feb 2021 01:05:09 +0100 Subject: [PATCH 07/11] Send VimspectorDebugEnded event --- python3/vimspector/debug_session.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 36e6feb..954d2c6 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -412,6 +412,7 @@ class DebugSession( object ): self._outputView.Reset() self._codeView.Reset() vim.command( 'tabclose!' ) + vim.command( 'doautocmd User VimspectorDebugEnded' ) self._stackTraceView = None self._variablesView = None self._outputView = None From d561c4aea5fdedee2b44a2951310cd85baf43d45 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sat, 20 Feb 2021 22:37:02 +0000 Subject: [PATCH 08/11] Add demo of new commands for local mappings --- support/custom_ui_vimrc | 43 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/support/custom_ui_vimrc b/support/custom_ui_vimrc index 95c3360..4e9f635 100644 --- a/support/custom_ui_vimrc +++ b/support/custom_ui_vimrc @@ -1,5 +1,7 @@ execute 'source' expand( ':p:h' ) . '/minimal_vimrc' set noequalalways +let mapleader = ',' +let maplocalleader = "\" function! s:CustomiseUI() let wins = g:vimspector_session_windows @@ -59,11 +61,52 @@ function! s:CustomiseWinBar() nnoremenu WinBar.✕\ ᶠ⁸ :call vimspector#Reset() endfunction +let s:mapped = {} + +function! s:OnJumpToFrame() abort + if has_key( s:mapped, string( bufnr() ) ) + return + endif + + nmap dn VimspectorStepOver + nmap ds VimspectorStepInto + nmap df VimspectorStepOut + nmap dc VimspectorContinue + + let s:mapped[ string( bufnr() ) ] = 1 +endfunction + +function! s:OnDebugEnd() abort + + let original_buf = bufnr() + let hidden = &hidden + + try + set hidden + for bufnr in keys( s:mapped ) + try + execute 'noautocmd buffer' bufnr + silent! nunmap dn + silent! nunmap ds + silent! nunmap df + silent! nunmap dc + endtry + endfor + finally + execute 'noautocmd buffer' original_buf + let &hidden = hidden + endtry + + let s:mapped = {} +endfunction + augroup TestUICustomistaion autocmd! autocmd User VimspectorUICreated call s:CustomiseUI() autocmd User VimspectorTerminalOpened call s:SetUpTerminal() autocmd User VimspectorUICreated call s:CustomiseWinBar() + autocmd User VimspectorJumpedToFrame call s:OnJumpToFrame() + autocmd User VimspectorDebugEnded call s:OnDebugEnd() augroup END let g:vimspector_sign_priority = { From 3c7311e33a9a77d7d315cc473ccffc600119e2b3 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sun, 21 Feb 2021 20:49:56 +0000 Subject: [PATCH 09/11] Test that the commands are fired when stepping through and continuing --- tests/ui.test.vim | 46 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/tests/ui.test.vim b/tests/ui.test.vim index 390f870..f251539 100644 --- a/tests/ui.test.vim +++ b/tests/ui.test.vim @@ -411,16 +411,54 @@ function! Test_CustomWinBar() endfunction function! Test_VimspectorJumpedToFrame() + let s:ended = 0 + let s:au_visited_buffers = {} + augroup TestVimspectorJumpedToFrame au! - au User VimspectorJumpedToFrame let b:vimspectorStepIsThere = 'foo' + au User VimspectorJumpedToFrame + \ let s:au_visited_buffers[ bufname() ] = get( s:au_visited_buffers, + \ bufname(), + \ 0 ) + 1 + au User VimspectorDebugEnded + \ let s:ended = 1 augroup END - call s:StartDebugging() - call assert_equal( 'foo', getbufvar(bufnr(), 'vimspectorStepIsThere', 0) ) + lcd ../support/test/python/multiple_files + edit moo.py + + let moo = 'moo.py' + let cow = getcwd() . '/cow.py' + + call vimspector#SetLineBreakpoint( 'moo.py', 13 ) + call vimspector#Launch() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 1, 1 ) + call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 1 ) + let expected = {} + let expected[ moo ] = 1 + call assert_equal( expected, s:au_visited_buffers ) + + call vimspector#Continue() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'moo.py', 13, 1 ) + call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'moo.py', 13 ) + let expected[ moo ] += 1 + call assert_equal( expected, s:au_visited_buffers ) + + call vimspector#SetLineBreakpoint( 'cow.py', 2 ) + call vimspector#Continue() + call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'cow.py', 2, 1 ) + call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'cow.py', 2 ) + let expected[ cow ] = 1 + call assert_equal( expected, s:au_visited_buffers ) + + VimspectorReset + call WaitForAssert( { -> assert_equal( s:ended, 1 ) } ) au! TestVimspectorJumpedToFrame - unlet b:vimspectorStepIsThere + unlet! s:au_visited_buffers + unlet! s:ended + call vimspector#test#setup#Reset() + lcd - %bwipe! endfunction From ae289a88c76fe69531293eb6ce311028d3e78dfd Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sun, 21 Feb 2021 21:16:54 +0000 Subject: [PATCH 10/11] Update readme with example --- README.md | 30 ++++++++++++++++++++++++++- support/custom_ui_vimrc | 46 +++++++++++++++++++++++++++++++---------- 2 files changed, 64 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index b3088b7..e13aae0 100644 --- a/README.md +++ b/README.md @@ -85,12 +85,13 @@ For detailed explanatin of the `.vimspector.json` format, see the * [Sign priority](#sign-priority) * [Changing the default window sizes](#changing-the-default-window-sizes) * [Changing the terminal size](#changing-the-terminal-size) + * [Custom mappings while debugging](#custom-mappings-while-debugging) * [Advanced UI customisation](#advanced-ui-customisation) * [Customising the WinBar](#customising-the-winbar) * [Example](#example) * [FAQ](#faq) - + @@ -675,6 +676,10 @@ 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](#custom-mappings-while-debugging). + 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. @@ -1821,6 +1826,29 @@ let g:vimspector_terminal_maxwidth = 75 let g:vimspector_terminal_minwidth = 20 ``` +## 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` autocommds: + +* `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 commadns 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. + ## Advanced UI customisation > ***Please Note***: This cusomiation API is ***unstable***, meaning that it may diff --git a/support/custom_ui_vimrc b/support/custom_ui_vimrc index 4e9f635..51a7304 100644 --- a/support/custom_ui_vimrc +++ b/support/custom_ui_vimrc @@ -1,7 +1,12 @@ +" setup boilerplate to make this file usable with vim -Nu {{{ +scriptencoding utf-8 execute 'source' expand( ':p:h' ) . '/minimal_vimrc' set noequalalways let mapleader = ',' let maplocalleader = "\" +" }}} + +" Custom Layout {{{ function! s:CustomiseUI() let wins = g:vimspector_session_windows @@ -61,6 +66,27 @@ function! s:CustomiseWinBar() nnoremenu WinBar.✕\ ᶠ⁸ :call vimspector#Reset() endfunction +augroup TestUICustomistaion + autocmd! + autocmd User VimspectorUICreated call s:CustomiseUI() + autocmd User VimspectorTerminalOpened call s:SetUpTerminal() + autocmd User VimspectorUICreated call s:CustomiseWinBar() +augroup END + +" }}} + +" Custom sign priority {{{ + +let g:vimspector_sign_priority = { + \ 'vimspectorBP': 3, + \ 'vimspectorBPCond': 2, + \ 'vimspectorBPDisabled': 1, + \ 'vimspectorPC': 999, + \ } + +" }}} + +" Custom mappings while debuggins {{{ let s:mapped = {} function! s:OnJumpToFrame() abort @@ -72,6 +98,8 @@ function! s:OnJumpToFrame() abort nmap ds VimspectorStepInto nmap df VimspectorStepOut nmap dc VimspectorContinue + nmap di VimspectorBalloonEval + xmap di VimspectorBalloonEval let s:mapped[ string( bufnr() ) ] = 1 endfunction @@ -90,6 +118,8 @@ function! s:OnDebugEnd() abort silent! nunmap ds silent! nunmap df silent! nunmap dc + silent! nunmap di + silent! xunmap di endtry endfor finally @@ -100,18 +130,12 @@ function! s:OnDebugEnd() abort let s:mapped = {} endfunction -augroup TestUICustomistaion - autocmd! - autocmd User VimspectorUICreated call s:CustomiseUI() - autocmd User VimspectorTerminalOpened call s:SetUpTerminal() - autocmd User VimspectorUICreated call s:CustomiseWinBar() +augroup TestCustomMappings + au! autocmd User VimspectorJumpedToFrame call s:OnJumpToFrame() autocmd User VimspectorDebugEnded call s:OnDebugEnd() augroup END -let g:vimspector_sign_priority = { - \ 'vimspectorBP': 3, - \ 'vimspectorBPCond': 2, - \ 'vimspectorBPDisabled': 1, - \ 'vimspectorPC': 999, - \ } +" }}} + +" vim: foldmethod=marker From 448ee33a6af11a32e4efb18814d1eb778089e58c Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sun, 21 Feb 2021 21:24:02 +0000 Subject: [PATCH 11/11] prevent annoying 'no matching autocmds' message --- plugin/vimspector.vim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugin/vimspector.vim b/plugin/vimspector.vim index 6691a2a..8482dfd 100644 --- a/plugin/vimspector.vim +++ b/plugin/vimspector.vim @@ -125,6 +125,8 @@ augroup VimspectorUserAutoCmds autocmd! autocmd User VimspectorUICreated silent autocmd User VimspectorTerminalOpened silent + autocmd user VimspectorJumpedToFrame silent + autocmd user VimspectorDebugEnded silent augroup END augroup Vimspector