jeffreytse / zsh-vi-mode

💻 A better and friendly vi(vim) mode plugin for ZSH.
MIT License
2.93k stars 102 forks source link

zvm_bindkey doesn't seem to play nice with repeated multikey sequences #261

Open cohml opened 5 months ago

cohml commented 5 months ago

General information

Basic examination

Problem description

Sorry for the poor issue title, I wasn't sure how to concisely describe the problem. Basically it's this:

Given two widgets A and B, zvm_bindkey doesn't work well when I try to bind one to e.g., ^x and another to ^x^x. No matter what I do, I can't seem to get both keybindings working simultaneously. Which one works also seems to depend on the order in which they were bound using zvm_bindkey.

Extra observations

Based on my own reading of the source code, the problem seems to stem in part from these lines. However because I don't understand the intent, I can't recommend a fix.

Reproduction steps

❯ # define two arbitrary functions
❯ function x_func() { echo hello from x }
❯ function xx_func() { echo hello from xx }
❯
❯ # register the functions as zsh widgets
❯ zle -N x_func
❯ zle -N xx_func
❯
❯ # note that the x key is unused for any keybindings
❯ bindkey -L | grep -i x
❯ 
❯ # bind using zvm_keybind (first x_func then xx_func)
❯ zvm_bindkey viins "^x" x_func
❯ zvm_bindkey viins "^x^x" xx_func
❯ 
❯ # observe the results
❯ bindkey -L | grep -i x
bindkey "^X" zvm_readkeys_handler  # <-- note that i didn't do this myself, and i suspect it's related to the issue reported here
bindkey "^X^X" xx_func
❯ 
❯ # now try to use the keybindings; note that ^x does nothing...
❯
❯ # ...meanwhile, ^x^x works as intended
❯ hello from xx
❯
❯ # now unbind both ^x and ^x^x for good measure
❯ bindkey -r -M viins "^x"
❯ bindkey -r -M viins "^x^x"
❯
❯ # sanity check that there are no "x" keybindings
❯ bindkey -L | grep -i x
❯
❯ # now re-bind, but this time in the opposite order (first xx_func then x_func)
❯ zvm_bindkey viins "^x^x" xx_func
❯ zvm_bindkey viins "^x" x_func
❯ 
❯ # observe the results
❯ bindkey -L | grep -i x
bindkey "^X" x_func  # <-- seems correct now, no avm_readkeys_handler here like there was before
bindkey "^X^X" xx_func
❯
❯ # note that now ^x works...
❯ hello from x
❯
❯ # ...meanwhile, ^x^x no longer does (instead, it just triggers the ^x keybinding)
❯ hello from x

As you can see, in no case am I able to get both keybindings working simultaneously.

Furthermore, using zvm_bindkey with bindings like ^x and ^x^x yields different results depending on the order in which things are bound

Finally, zvm_readkeys_handler also pops up, muddying the debugging waters. (ref. #260)

Expected behavior

Both keybindings should work, lol. The possibility for ambiguity (e.g., when I type ^x, do I want to execute ^x, or am I just not finished typing ^x^x?) should already be resolvable by the existence of the KEYTIMEOUT variable.

Moreover, ideally order shouldn't matter, though I understand there may be some constraints there.