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/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 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/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 diff --git a/support/custom_ui_vimrc b/support/custom_ui_vimrc index 95c3360..51a7304 100644 --- a/support/custom_ui_vimrc +++ b/support/custom_ui_vimrc @@ -1,5 +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 @@ -66,9 +73,69 @@ augroup TestUICustomistaion 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 + if has_key( s:mapped, string( bufnr() ) ) + return + endif + + nmap dn VimspectorStepOver + nmap ds VimspectorStepInto + nmap df VimspectorStepOut + nmap dc VimspectorContinue + nmap di VimspectorBalloonEval + xmap di VimspectorBalloonEval + + 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 + silent! nunmap di + silent! xunmap di + endtry + endfor + finally + execute 'noautocmd buffer' original_buf + let &hidden = hidden + endtry + + let s:mapped = {} +endfunction + +augroup TestCustomMappings + au! + autocmd User VimspectorJumpedToFrame call s:OnJumpToFrame() + autocmd User VimspectorDebugEnded call s:OnDebugEnd() +augroup END + +" }}} + +" vim: foldmethod=marker diff --git a/tests/ui.test.vim b/tests/ui.test.vim index b6c8feb..f251539 100644 --- a/tests/ui.test.vim +++ b/tests/ui.test.vim @@ -409,3 +409,56 @@ function! Test_CustomWinBar() call vimspector#test#setup#Reset() %bwipe! endfunction + +function! Test_VimspectorJumpedToFrame() + let s:ended = 0 + let s:au_visited_buffers = {} + + augroup TestVimspectorJumpedToFrame + au! + 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 + + 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! s:au_visited_buffers + unlet! s:ended + + call vimspector#test#setup#Reset() + lcd - + %bwipe! +endfunction