jeffreytse / zsh-vi-mode

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

Using zvm_bindkey to bind widget to "ESC-<key>" renders backslash unusable #260

Open cohml opened 5 months ago

cohml commented 5 months ago

General information

Basic examination

Problem description

The README states that custom widgets should be bound to a key (or key sequence) using zvm_bindkeys. However, in certain cases, zvm_bindkey can "steal" the first key of the sequence and bind it to zvm_readkeys_handler.

When the sequence begins with ESC - for which I believe the ANSI escape code is \e - this means that \ gets bound to zvm_readkeys_handler, making it impossible to type out a backslash.

After reading the source code, I'm quite certain the offending logic occurs here:

https://github.com/jeffreytse/zsh-vi-mode/blob/master/zsh-vi-mode.zsh#L608-L622C33

Reproduction steps

❯ # define arbitrary function
❯ function foo() {}
❯ 
❯ # register function as zsh widget
❯ zle -N foo
❯ 
❯ # note that zvm_readkeys_handler IS NOT bound to backslash
❯ bindkey -L | grep zvm_readkeys_handler
bindkey "^[" zvm_readkeys_handler
❯ 
❯ # note that i can still type backslashes
❯ \\\
❯ 
❯ # use zvm_bindkey to bind function to sequence beginning with backslash
❯ zvm_bindkey viins "\ef" foo
❯ 
❯ # note that zvm_readkeys_handler IS now bound to backslash
❯ bindkey -L | grep zvm_readkeys_handler
bindkey "^[" zvm_readkeys_handler
bindkey "\\\\" zvm_readkeys_handler
❯ 
❯ # i am unable to type backslashes
❯
❯ # when i try, it seems to try to register the subsequent key as a widget;
❯ # for example, here i will press "\f"
❯
No such widget `f'

Expected behavior

My widget should be bound to the specified sequence without rendering the initial key in the sequence unusable on its own.