From 26452289a81eaa5ada15274a8ed216215ac3e213 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 24 Feb 2021 22:10:23 +0000 Subject: [PATCH] Allow overriding the variables/stack trace mappings in config --- autoload/vimspector/internal/balloon.vim | 30 +++++++++-- python3/vimspector/settings.py | 63 +++++++++++++++++++++--- python3/vimspector/stack_trace.py | 17 ++++--- python3/vimspector/variables.py | 22 +++++---- 4 files changed, 106 insertions(+), 26 deletions(-) diff --git a/autoload/vimspector/internal/balloon.vim b/autoload/vimspector/internal/balloon.vim index 1622d10..4770d81 100644 --- a/autoload/vimspector/internal/balloon.vim +++ b/autoload/vimspector/internal/balloon.vim @@ -134,21 +134,43 @@ function! vimspector#internal#balloon#MouseFilter( winid, key ) abort return handled endfunction +function! s:MatchKey( key, candidates ) abort + let mapped = '' + for candidate in a:candidates + try + " Try and expand the key code + execute 'let mapped = "\' . candidate . '"' + if mapped ==# a:key + return v:true + endif + endtry + endfor + + return v:false +endfunction + function! vimspector#internal#balloon#CursorFilter( winid, key ) abort - if a:key ==? "\" + let mappings = py3eval( + \ "__import__( 'vimspector'," + \." fromlist = [ 'settings' ] ).settings.Dict(" + \." 'mappings' )[ 'variables' ]" ) + + if index( [ "\", "\<2-LeftMouse>" ], a:key ) >= 0 + return vimspector#internal#balloon#MouseFilter( a:winid, a:key ) + endif + + if s:MatchKey( a:key, mappings.expand_collapse ) call py3eval( '_vimspector_session.ExpandVariable(' \ . 'buf = vim.buffers[ ' . winbufnr( a:winid ) . ' ],' \ . 'line_num = ' . line( '.', a:winid ) \ . ')' ) return 1 - elseif a:key ==? "\" + elseif s:MatchKey( a:key, mappings.set_value ) call py3eval( '_vimspector_session.SetVariableValue(' \ . 'buf = vim.buffers[ ' . winbufnr( a:winid ) . ' ],' \ . 'line_num = ' . line( '.', a:winid ) \ . ')' ) return 1 - elseif index( [ "\", "\<2-LeftMouse>" ], a:key ) >= 0 - return vimspector#internal#balloon#MouseFilter( a:winid, a:key ) endif return popup_filter_menu( a:winid, a:key ) diff --git a/python3/vimspector/settings.py b/python3/vimspector/settings.py index 5ff729b..53aafd2 100644 --- a/python3/vimspector/settings.py +++ b/python3/vimspector/settings.py @@ -17,6 +17,7 @@ import vim import builtins from vimspector import utils +from collections.abc import Mapping DEFAULTS = { # UI @@ -38,6 +39,19 @@ DEFAULTS = { # Installer 'install_gadgets': [], + + # Mappings + 'mappings': { + 'variables': { + 'expand_collapse': [ '', '<2-LeftMouse>' ], + 'delete': [ '' ], + 'set_value': [ '' ] + }, + 'stack_trace': { + 'expand_or_jump': [ '', '<2-LeftMouse>' ], + 'focus_thread': [ '' ], + } + } } @@ -69,9 +83,46 @@ if hasattr( vim, 'Dictionary' ): DICT_TYPE = vim.Dictionary -def Dict( option: str ): - d = DICT_TYPE( DEFAULTS.get( option, {} ) ) - d.update( utils.GetVimValue( vim.vars, - f'vimspector_{ option }', - {} ) ) - return d +def Dict( option ): + return _UpdateDict( DICT_TYPE( DEFAULTS.get( option, {} ) ), + utils.GetVimValue( vim.vars, + f'vimspector_{ option }', + {} ) ) + + +def _UpdateDict( target, override ): + """Apply the updates in |override| to the dict |target|. This is like + dict.update, but recursive. i.e. if the existing element is a dict, then + override elements of the sub-dict rather than wholesale replacing. + e.g. + UpdateDict( + { + 'outer': { 'inner': { 'key': 'oldValue', 'existingKey': True } } + }, + { + 'outer': { 'inner': { 'key': 'newValue' } }, + 'newKey': { 'newDict': True }, + } + ) + yields: + { + 'outer': { + 'inner': { + 'key': 'newValue', + 'existingKey': True + } + }, + 'newKey': { newDict: True } + } + """ + + for key, value in override.items(): + current_value = target.get( key ) + if not isinstance( current_value, Mapping ): + target[ key ] = value + elif isinstance( value, Mapping ): + target[ key ] = _UpdateDict( current_value, value ) + else: + target[ key ] = value + + return target diff --git a/python3/vimspector/stack_trace.py b/python3/vimspector/stack_trace.py index df32462..c32cead 100644 --- a/python3/vimspector/stack_trace.py +++ b/python3/vimspector/stack_trace.py @@ -18,7 +18,7 @@ import os import logging import typing -from vimspector import utils, signs +from vimspector import utils, signs, settings class Thread: @@ -107,13 +107,16 @@ class StackTraceView( object ): utils.SetUpHiddenBuffer( self._buf, 'vimspector.StackTrace' ) utils.SetUpUIWindow( win ) + mappings = settings.Dict( 'mappings' )[ 'stack_trace' ] + with utils.LetCurrentWindow( win ): - vim.command( 'nnoremap ' - ':call vimspector#GoToFrame()' ) - vim.command( 'nnoremap ' - ':call vimspector#SetCurrentThread()' ) - vim.command( 'nnoremap <2-LeftMouse> ' - ':call vimspector#GoToFrame()' ) + for mapping in utils.GetVimList( mappings, 'expand_or_jump' ): + vim.command( f'nnoremap { mapping } ' + ':call vimspector#GoToFrame()' ) + + for mapping in utils.GetVimList( mappings, 'focus_thread' ): + vim.command( f'nnoremap { mapping } ' + ':call vimspector#SetCurrentThread()' ) if utils.UseWinBar(): vim.command( 'nnoremenu 1.1 WinBar.Pause/Continue ' diff --git a/python3/vimspector/variables.py b/python3/vimspector/variables.py index 9e74345..e418a5e 100644 --- a/python3/vimspector/variables.py +++ b/python3/vimspector/variables.py @@ -19,7 +19,7 @@ import logging from functools import partial import typing -from vimspector import utils +from vimspector import utils, settings class Expandable: @@ -165,13 +165,16 @@ class VariablesView( object ): self._variable_eval: Scope = None self._variable_eval_view: View = None + mappings = settings.Dict( 'mappings' )[ 'variables' ] + def AddExpandMappings(): - vim.command( 'nnoremap ' - ':call vimspector#ExpandVariable()' ) - vim.command( 'nnoremap <2-LeftMouse> ' - ':call vimspector#ExpandVariable()' ) - vim.command( 'nnoremap ' - ':call vimspector#SetVariableValue()' ) + for mapping in utils.GetVimList( mappings, 'expand_collapse' ): + vim.command( f'nnoremap { mapping } ' + ':call vimspector#ExpandVariable()' ) + + for mapping in utils.GetVimList( mappings, 'set_value' ): + vim.command( f'nnoremap { mapping } ' + ':call vimspector#SetVariableValue()' ) # Set up the "Variables" buffer in the variables_win self._scopes: typing.List[ Scope ] = [] @@ -194,8 +197,9 @@ class VariablesView( object ): 'vimspector#OmniFuncWatch' ) with utils.LetCurrentWindow( watches_win ): AddExpandMappings() - vim.command( - 'nnoremap :call vimspector#DeleteWatch()' ) + for mapping in utils.GetVimList( mappings, 'delete' ): + vim.command( + f'nnoremap { mapping } :call vimspector#DeleteWatch()' ) if utils.UseWinBar(): vim.command( 'nnoremenu 1.1 WinBar.New '