From ff454c7d600b4e60ec995b58cb5f6aba20312b77 Mon Sep 17 00:00:00 2001 From: David Barnett Date: Sat, 7 Nov 2020 20:53:17 -0800 Subject: [PATCH] Test and doc fixes for keymapping helpers from code review --- autoload/maktaba/keymapping.vim | 42 ++++++++++++++--------------- autoload/maktaba/keymappingspec.vim | 15 ++++++----- doc/maktaba.txt | 34 +++++++++++------------ vroom/keymapping.vroom | 35 +++++++++++++++++------- 4 files changed, 70 insertions(+), 56 deletions(-) diff --git a/autoload/maktaba/keymapping.vim b/autoload/maktaba/keymapping.vim index 0651dda..9a2ba32 100644 --- a/autoload/maktaba/keymapping.vim +++ b/autoload/maktaba/keymapping.vim @@ -1,7 +1,7 @@ "" " @dict KeyMapping -" A maktaba representation of a vim key mapping, which is used to configure and -" unmap it from vim. +" A maktaba representation of a Vim key mapping, which is used to configure and +" unmap it from Vim. if !exists('s:next_keymap_id') @@ -35,6 +35,7 @@ function! s:GetFuncCallKeystrokes(funcstr, mode) abort elseif a:mode ==# 'i' return printf(':call %s', a:funcstr) elseif a:mode ==# 'v' + " Needs C-u to remove "'<,'>" range inserted for commands from visual mode. " Uses "gv" at the end to re-enter visual mode. return printf(':call %sgv', a:funcstr) elseif a:mode ==# 's' @@ -48,7 +49,16 @@ endfunction "" " @dict KeyMapping -" Unmaps the mapping in vim. +" Returns 1 if the mapping is still defined, 0 otherwise +function! maktaba#keymapping#IsMapped() dict abort + let l:foundmap = maparg(self._lhs, self._mode, 0, 1) + return !empty(l:foundmap) && l:foundmap == self._maparg +endfunction + + +"" +" @dict KeyMapping +" Unmaps the mapping in Vim. " Returns 1 if mapping was found and unmapped, 0 if mapping was gone already. function! maktaba#keymapping#Unmap() dict abort if self.IsMapped() @@ -68,18 +78,6 @@ function! maktaba#keymapping#Unmap() dict abort endfunction -"" -" @dict KeyMapping -" Returns 1 if the mapping is still defined, 0 otherwise -" -" Caveat: This detection can currently false positive if the original mapping -" was unmapped but then another similar one mapped afterwards. -function! maktaba#keymapping#IsMapped() dict abort - let l:foundmap = maparg(self._lhs, self._mode, 0, 1) - return !empty(l:foundmap) && l:foundmap == self._maparg -endfunction - - "" " @dict KeyMapping " Return a copy of the spec used to issue this mapping. @@ -94,16 +92,16 @@ let s:GetSpec = function('maktaba#keymapping#GetSpec') "" -" Set up a key mapping in vim, mapping key sequence {lhs} to replacement +" Set up a key mapping in Vim, mapping key sequence {lhs} to replacement " sequence {rhs} in the given [mode]. This is a convenience wrapper for -" @function(#Spec) and its |KeyMappingSpec.Map| that supports the basic mapping -" options. It is equivalent to calling: > +" @function(#Spec) and its |KeyMappingSpec.Map()| that supports the basic +" mapping options. It is equivalent to calling: > " :call maktaba#keymapping#Spec({lhs}, {rhs}, [mode]).Map() " < " " See those functions for usage and behavior details. " -" @default mode=all of 'n', 'v', and 'o' (vim's default) +" @default mode=all of 'n', 'v', and 'o' (Vim's default) function! maktaba#keymapping#Map(lhs, rhs, ...) abort if a:0 >= 1 let l:spec = maktaba#keymappingspec#Spec(a:lhs, a:rhs, a:1) @@ -179,7 +177,7 @@ endfunction "" " @private " @dict KeyMapping -" Defines the key mapping in vim via the |:map| commands for the keymap in self. +" Defines the key mapping in Vim via the |:map| commands for the keymap in self. " Core internal implementation of @function(KeyMappingSpec.Map). function! maktaba#keymapping#MapSelf() dict abort " TODO(dbarnett): Perform a sweep for expired mapping timeouts before trying @@ -199,7 +197,7 @@ endfunction "" " @private " @dict KeyMapping -" Define a buffer-local one-shot vim mapping from spec that will only trigger +" Define a buffer-local one-shot Vim mapping from spec that will only trigger " once and then unmap itself. " " @throws NotImplemented if used with `WithRemap(1)` @@ -226,7 +224,7 @@ endfunction "" " @private " @dict KeyMapping -" Define a short-lived vim mapping from spec that will only trigger once and +" Define a short-lived Vim mapping from spec that will only trigger once and " will also expire if 'timeoutlen' duration expires with 'timeout' setting " active. See |KeyMappingSpec.MapOnceWithTimeout()| for details. " diff --git a/autoload/maktaba/keymappingspec.vim b/autoload/maktaba/keymappingspec.vim index 60e9e9a..e0fb152 100644 --- a/autoload/maktaba/keymappingspec.vim +++ b/autoload/maktaba/keymappingspec.vim @@ -3,13 +3,13 @@ let s:plugin = maktaba#Maktaba() "" " @dict KeyMappingSpec -" A spec for a key mapping that can be mapped in vim with +" A spec for a key mapping that can be mapped in Vim with " @function(KeyMappingSpec.Map). "" " Create a @dict(KeyMappingSpec) that can be configured with options and then -" mapped in vim with @function(KeyMappingSpec.Map). The eventual mapping will +" mapped in Vim with @function(KeyMappingSpec.Map). The eventual mapping will " map {lhs} to {rhs} in the given [mode]. " " Initialized with recursive mappings disallowed by default (see |:noremap|). @@ -18,7 +18,7 @@ let s:plugin = maktaba#Maktaba() " Arguments will be configured with |map-| by default. Use the " "overwrite" option of `.WithArgs(…, 1)` if you want to map without . " -" @default mode=all of 'n', 'v', and 'o' (vim's default) +" @default mode=all of 'n', 'v', and 'o' (Vim's default) function! maktaba#keymappingspec#Spec(lhs, rhs, ...) abort let l:mode = get(a:, 1, '') @@ -76,6 +76,7 @@ endfunction "" " @dict KeyMappingSpec.Map +" Define a Vim mapping from spec via the |:map| commands. function! maktaba#keymappingspec#MapSelf() dict abort let l:keymap = maktaba#keymapping#PopulateFromSpec(self) call l:keymap._DoMap() @@ -85,7 +86,7 @@ endfunction "" " @dict KeyMappingSpec.MapOnce -" Define a buffer-local one-shot vim mapping from spec that will only trigger +" Define a buffer-local one-shot Vim mapping from spec that will only trigger " once and then unmap itself. " " Not supported for recursive mappings. @@ -99,14 +100,14 @@ endfunction "" " @dict KeyMappingSpec.MapOnceWithTimeout -" Define a short-lived vim mapping from spec that will only trigger once and +" Define a short-lived Vim mapping from spec that will only trigger once and " will also expire if 'timeoutlen' duration expires with 'timeout' setting " active. " " This is useful to detect if the user presses a key immediately after something " else happens, and respond with a particular behavior. " -" It can also be used for an improved version of vim's |map-ambiguous| behavior +" It can also be used for an improved version of Vim's |map-ambiguous| behavior " when one mapping is a prefix of another. You can create a prefix mapping that " does one thing immediately and then a different follow-up behavior on another " keystroke. @@ -117,7 +118,7 @@ endfunction " \.WithArgs(['']).MapOnceWithTimeout() " < " -" Caveat: Unlike vim's |map-ambiguous| behavior, this currently doesn't stop +" Caveat: Unlike Vim's |map-ambiguous| behavior, this currently doesn't stop " waiting for keypresses if another unrelated key is pressed while it's waiting. " Caveat: For long mappings, you might notice that the timeout is currently for " the entire mapping and not for each keystroke. If you need to work around that diff --git a/doc/maktaba.txt b/doc/maktaba.txt index 992922b..4ddf693 100644 --- a/doc/maktaba.txt +++ b/doc/maktaba.txt @@ -244,24 +244,21 @@ Flag.Translate({value}) *Flag.Translate()* running {value} through all registered translators). *maktaba.KeyMapping* -A maktaba representation of a vim key mapping, which is used to configure and -unmap it from vim. - -KeyMapping.Unmap() *KeyMapping.Unmap()* - Unmaps the mapping in vim. Returns 1 if mapping was found and unmapped, 0 if - mapping was gone already. +A maktaba representation of a Vim key mapping, which is used to configure and +unmap it from Vim. KeyMapping.IsMapped() *KeyMapping.IsMapped()* Returns 1 if the mapping is still defined, 0 otherwise - Caveat: This detection can currently false positive if the original mapping - was unmapped but then another similar one mapped afterwards. +KeyMapping.Unmap() *KeyMapping.Unmap()* + Unmaps the mapping in Vim. Returns 1 if mapping was found and unmapped, 0 if + mapping was gone already. KeyMapping.GetSpec() *KeyMapping.GetSpec()* Return a copy of the spec used to issue this mapping. *maktaba.KeyMappingSpec* -A spec for a key mapping that can be mapped in vim with +A spec for a key mapping that can be mapped in Vim with |KeyMappingSpec.Map()|. KeyMappingSpec.WithArgs({args}, [overwrite]) *KeyMappingSpec.WithArgs()* @@ -276,23 +273,24 @@ KeyMappingSpec.WithRemap({enabled}) *KeyMappingSpec.WithRemap()* Throws ERROR(WrongType) KeyMappingSpec.Map() *KeyMappingSpec.Map()* + Define a Vim mapping from spec via the |:map| commands. KeyMappingSpec.MapOnce() *KeyMappingSpec.MapOnce()* - Define a buffer-local one-shot vim mapping from spec that will only trigger + Define a buffer-local one-shot Vim mapping from spec that will only trigger once and then unmap itself. Not supported for recursive mappings. Throws ERROR(NotImplemented) if used with `WithRemap(1)` KeyMappingSpec.MapOnceWithTimeout() *KeyMappingSpec.MapOnceWithTimeout()* - Define a short-lived vim mapping from spec that will only trigger once and + Define a short-lived Vim mapping from spec that will only trigger once and will also expire if 'timeoutlen' duration expires with 'timeout' setting active. This is useful to detect if the user presses a key immediately after something else happens, and respond with a particular behavior. - It can also be used for an improved version of vim's |map-ambiguous| + It can also be used for an improved version of Vim's |map-ambiguous| behavior when one mapping is a prefix of another. You can create a prefix mapping that does one thing immediately and then a different follow-up behavior on another keystroke. @@ -304,7 +302,7 @@ KeyMappingSpec.MapOnceWithTimeout() *KeyMappingSpec.MapOnceWithTimeout()* \.WithArgs(['']).MapOnceWithTimeout() < - Caveat: Unlike vim's |map-ambiguous| behavior, this currently doesn't stop + Caveat: Unlike Vim's |map-ambiguous| behavior, this currently doesn't stop waiting for keypresses if another unrelated key is pressed while it's waiting. Caveat: For long mappings, you might notice that the timeout is currently for the entire mapping and not for each keystroke. If you need to @@ -1246,9 +1244,9 @@ maktaba#json#python#IsDisabled() *maktaba#json#python#IsDisabled()* disabled, and prevents further changes. maktaba#keymapping#Map({lhs}, {rhs}, [mode]) *maktaba#keymapping#Map()* - Set up a key mapping in vim, mapping key sequence {lhs} to replacement + Set up a key mapping in Vim, mapping key sequence {lhs} to replacement sequence {rhs} in the given [mode]. This is a convenience wrapper for - |maktaba#keymapping#Spec()| and its |KeyMappingSpec.Map| that supports the + |maktaba#keymapping#Spec()| and its |KeyMappingSpec.Map()| that supports the basic mapping options. It is equivalent to calling: > :call maktaba#keymapping#Spec({lhs}, {rhs}, [mode]).Map() @@ -1256,12 +1254,12 @@ maktaba#keymapping#Map({lhs}, {rhs}, [mode]) *maktaba#keymapping#Map()* See those functions for usage and behavior details. - [mode] is all of 'n', 'v', and 'o' (vim's default) if omitted. + [mode] is all of 'n', 'v', and 'o' (Vim's default) if omitted. maktaba#keymappingspec#Spec({lhs}, {rhs}, [mode]) *maktaba#keymappingspec#Spec()* Create a |maktaba.KeyMappingSpec| that can be configured with options and - then mapped in vim with |KeyMappingSpec.Map()|. The eventual mapping will + then mapped in Vim with |KeyMappingSpec.Map()|. The eventual mapping will map {lhs} to {rhs} in the given [mode]. Initialized with recursive mappings disallowed by default (see |:noremap|). @@ -1270,7 +1268,7 @@ maktaba#keymappingspec#Spec({lhs}, {rhs}, [mode]) Arguments will be configured with |map-| by default. Use the "overwrite" option of `.WithArgs(…, 1)` if you want to map without . - [mode] is all of 'n', 'v', and 'o' (vim's default) if omitted. + [mode] is all of 'n', 'v', and 'o' (Vim's default) if omitted. maktaba#library#Import({library}) *maktaba#library#Import()* Imports {library}. diff --git a/vroom/keymapping.vroom b/vroom/keymapping.vroom index fa37dc3..501ffba 100644 --- a/vroom/keymapping.vroom +++ b/vroom/keymapping.vroom @@ -29,7 +29,7 @@ Now let's try it out! :normal i ~ Nope! -Well, that was fun, but let's unlet our mapping and restore the original +Well, that was fun, but let's unmap our mapping and restore the original behavior. :call evil_mapping.Unmap() @@ -62,19 +62,36 @@ open parentheses. -Vim also supports special arguments to mappings, such as the "" arg to -avoid overriding any existing mapping. Let's define a unique mapping and verify -that it's behaving politely. +Vim also supports special arguments to mappings to affect mapping behavior (see +:help :map-arguments). Let's use the argument to define a buffer-local +mapping. Maktaba provides a builder interface for mappings configuration more complex than LHS, RHS, and mode. That will let us pass arguments in to the mapping we're defining. - :let first_mapping = maktaba#keymapping#Map('!', '?') - :let polite_spec = maktaba#keymappingspec#Spec('!', '??') - |.WithArgs(['']) - :call maktaba#error#Try(maktaba#function#Method(polite_spec, 'Map')) - ~ Vim(noremap):E227: * (glob) + :let buffer_mapping = maktaba#keymappingspec#Spec('!', '?') + |.WithArgs(['']) + |.Map() + :let mapping_info = maparg('!', '', 0, 1) + :echomsg mapping_info.buffer + ~ 1 + :call buffer_mapping.Unmap() + + +By default Maktaba uses and defines non-recursive mappings to avoid +unpleasant surprises, since programmatically-defined mappings usually wouldn't +intend to silently override existing mappings or expand recursively-nested +mappings. The spec interface allows you to override these default behaviors. + + :let recursive_nonunique_mapping = maktaba#keymappingspec#Spec('!', '?') + |.WithArgs([], 1) + |.WithRemap(1) + |.Map() + :let mapping_info = maparg('!', '', 0, 1) + :echomsg mapping_info.noremap + ~ 0 + :call recursive_nonunique_mapping.Unmap()