mirror of
https://github.com/zdharma-continuum/zinit.git
synced 2026-09-10 07:36:38 -04:00
fix(zsh): probe the bound keymap for a -M bindmap's previous binding
.zinit-tmp-subst-bindkey records the widget a key carried before the plugin bound it, so unload can put it back. That probe always read the `main' keymap, even when the intercepted bind itself carried `-M <keymap>'. Unloading a plugin whose bindmap'' remapped a key bound with -M therefore restored main's widget into the other keymap, silently replacing whatever had been bound there. Pass the same -M <keymap> to the probing `bindkey' whenever opts[-M] is set. The existing -M case only asserted that a remap does not leak out of `emacs', and it assumed `main' was linked to `viins' in the test shell -- `main' is `emacs' unless EDITOR/VISUAL is vi-flavored, so the leak it was meant to catch was invisible. Link `main' to `viins' explicitly and add a case that pre-binds the remapped key to different widgets in `emacs' and `main', which makes restoring the wrong keymap's widget detectable. Signed-off-by: Vladislav Doster <mvdoster@gmail.com>
This commit is contained in:
parent
72c7154664
commit
2007a1ce8f
|
|
@ -126,27 +126,52 @@
|
|||
}
|
||||
|
||||
@test 'bindmap confines a -M remap to that keymap' {
|
||||
# `main' is linked to `viins' in the test shell, so `emacs' is used to tell
|
||||
# the keymaps apart.
|
||||
# `main' defaults to `emacs' unless EDITOR/VISUAL is vi-flavored; pin it to `viins' so a remap
|
||||
# that leaked out of `emacs' (a dropped -M) is actually observable in `main'.
|
||||
unsetopt ERR_EXIT
|
||||
bindkey -A viins main
|
||||
bindmap_fixture bm-keymap
|
||||
function zunit-bm-keymap() { }
|
||||
function zunit-bm-keymap() { ; }
|
||||
zle -N zunit-bm-keymap
|
||||
|
||||
zinit as"null" id-as"test/bm-keymap" bindmap'^A -> "^Y"' \
|
||||
atload'!bindkey -M emacs "^A" zunit-bm-keymap' for test/bm-keymap
|
||||
zinit for \
|
||||
as"null" \
|
||||
atload'!bindkey -M emacs "^A" zunit-bm-keymap' \
|
||||
bindmap'^A -> "^Y"' \
|
||||
id-as"test/bm-keymap" \
|
||||
@test/bm-keymap
|
||||
|
||||
local -a in_emacs=( ${(f)"$(bindings_for zunit-bm-keymap emacs)"} )
|
||||
local -a in_main=( ${(f)"$(bindings_for zunit-bm-keymap)"} )
|
||||
assert $#in_emacs equals 1
|
||||
assert ${#in_emacs} equals 1
|
||||
assert "${in_emacs[1]}" contains '"^Y"'
|
||||
assert $#in_main equals 0
|
||||
assert ${#in_main} equals 0
|
||||
|
||||
zinit unload -q test/bm-keymap
|
||||
in_emacs=( ${(f)"$(bindings_for zunit-bm-keymap emacs)"} )
|
||||
assert $#in_emacs equals 0
|
||||
}
|
||||
|
||||
@test 'bindmap -M restores the keymap-specific previous binding' {
|
||||
# Regression: the previous-binding probe read `main' even for a `-M <map>' bind, so unload
|
||||
# restored the wrong keymap's widget. The remapped key is pre-bound differently in `emacs' and
|
||||
# `main' so restoring the wrong one is detectable.
|
||||
unsetopt ERR_EXIT
|
||||
bindkey -A viins main
|
||||
bindmap_fixture bm-keymap-prev
|
||||
function zunit-bm-keymap-prev() { }
|
||||
zle -N zunit-bm-keymap-prev
|
||||
bindkey -M emacs '^Y' clear-screen # emacs prior -- must be restored on unload
|
||||
bindkey '^Y' self-insert # different main prior -- must NOT be what's restored
|
||||
|
||||
zinit as"null" id-as"test/bm-keymap-prev" bindmap'^A -> "^Y"' \
|
||||
atload'!bindkey -M emacs "^A" zunit-bm-keymap-prev' for test/bm-keymap-prev
|
||||
assert "$(bindkey -M emacs '^Y')" contains 'zunit-bm-keymap-prev'
|
||||
|
||||
zinit unload -q test/bm-keymap-prev
|
||||
assert "$(bindkey -M emacs '^Y')" contains 'clear-screen'
|
||||
}
|
||||
|
||||
@test 'bindmap ! form remaps the widget, not the key' {
|
||||
unsetopt ERR_EXIT
|
||||
bindmap_fixture bm-bang
|
||||
|
|
|
|||
|
|
@ -547,7 +547,10 @@ builtin setopt noaliases
|
|||
[[ $bmap_val = hold ]] && return 0
|
||||
|
||||
# Quoted - the key sequence may contain spaces, e.g. bindmap'^X -> "^ "'.
|
||||
local prev="${(q)${(s: :)$(builtin bindkey "${(Q)string}")}[-1]#undefined-key}"
|
||||
# Probe the same keymap the bind targets, so unload restores the right prior widget.
|
||||
local -a Mprobe
|
||||
(( ${+opts[-M]} )) && Mprobe=( -M "${opts[-M]}" )
|
||||
local prev="${(q)${(s: :)$(builtin bindkey "${Mprobe[@]}" "${(Q)string}")}[-1]#undefined-key}"
|
||||
|
||||
# "-M map" given?
|
||||
if (( ${+opts[-M]} )); then
|
||||
|
|
|
|||
Loading…
Reference in a new issue