Bind delete key in vi mode - zsh

I am using the vi-mode plugin of oh-my-zsh. In my .zshrc, I have
bindkey '^[[3~' delete-char
where ^[[3~ is the escape code of my delete key. However, this only works in insert mode, but not in command mode. When I type
$ abcd
move the cursor to the beginning of the line and hit del in command mode, I get
$ ABCd
so apparently the character sequence of the delete key is interpreted literally. How can I make the delete key actually delete a character in command mode?

bindkey -a '^[[3~' delete-char
Zsh has a variety of different keymaps and by default, bindkey will bind keys in the normal insert mode keymap. The command mode keymap is selected with -M vicmd. -a is a shortcut for that. You can list the keymaps with bindkey -l. You'll see that there is also viopp which is used for movements after a key like c or d. There's also visual for visual selection mode.

It's 2020 now, and I'm not sure if #okapi 's answer is out of date or just missing a piece, but for me, I had to use:
bindkey -a '^[[3~' vi-delete-char
delete-char without the vi- prefix didn't do the trick but adding it did.

Related

How to cancel a completion in zsh prezto in vi insert mode?

In zsh, with emacs key mapping mode, Control + _ will cancel a completion.
Example:
echo $EDITOR[tab]
will be completed as:
echo vim
Pressing Control + _ will restore the editor to:
echo $EDITOR
I want to do the same thing with vi key mapping mode.
Is there a way to do it? Is there already a key mapping to do it?
Control + _ does not work neither in insert mode nor in normal mode.
The u (undo) will remove the entire line.
I finally found how to do it.
bindkey -l will print a list of existing keymap names.
bindkey -M <keymap> will list all bindings for a given keymap.
So I compared emacs and viins bindings and added the following line:
bindkey -M viins "$key_info[Control]_" undo
to the .zprezto/modules/editor/init.zsh. And it works.
I made a pull request to add this mapping to prezto:
https://github.com/sorin-ionescu/prezto/pull/1860

How to setup Vi Editing Mode for zsh

I want to set vi in editing mode in zsh (I am using oh-my-zsh) at start automatically when I open my shell, so at the beginning of my .zshrc I have tried the following code:
set -o vi
or
bindkey -v
but when pressing enter in the shell I cannot enter the vi mode.
If I tried one of the two commands in the shell, it works.
Basically I want zsh to start in vi edit mode.
Any ideas how to solve this problem?
bindkey -v is enough to enable vi mode in ZSH. If you are worried the setting will be overwritten by another plugin, put the setting at the bottom of your ~/.zshrc.
After vi mode is enabled, you enter the "insert" mode by default. To enter "normal" mode, use Esc. And i or a to switch back to "insert" mode.
BTW, softmoth/zsh-vim-mode is the most powerful vim mode plugin I've ever used in ZSH.
Using bindkey -v may take over functionality such as history search with control+R and control+S. To restore that particular behavior, add the following lines after bindkey -v:
bindkey ^R history-incremental-search-backward
bindkey ^S history-incremental-search-forward
Other bindings can be found in the ZSH manual Standard Widgets section.
If you are using https://ohmyz.sh/ you can add vi-mode to the list of plugins in ~/.zshrc:
plugins=(git vi-mode)
If you don't mind to use a plugin for vi mode in zsh, here is a better choice for you to quickly reach it.
zsh-vi-mode: A better and friendly vi(vim) mode plugin for ZSH.
After adding this plugin, then you can input with vi-mode like this:
Features
Cursor movement (Navigation).
Insert & Replace (Insert mode).
Text Objects.
Searching text.
Undo, Redo, Cut, Copy, Paste, and Delete.
Surrounds (Add, Replace, Delete, and Move Around).
Switch keywords (Increase/Decrease Number, Boolean, etc. In progress).
...

List current existing or applied key bindings made via bindkey

My ZSH has at some point been told to bind Delete to some complicated function, key sequence, or macro, and I want to remove this binding from my configuration. In order to better find where this binding is being set, I'd like to see what Zsh is actually doing when I hit Delete.
How can I see a list of all the currently existing key bindings present in my Zsh environment?
Just run bindkey with no arguments:
$ bindkey
"^A"-"^C" self-insert
"^D" list-choices
"^E"-"^F" self-insert
"^G" list-expand
"^H" vi-backward-delete-char
"^I" expand-or-complete
"^J" history-substring-search-down
"^K" self-insert
"^L" clear-screen
...
However, the particular behavior you are describing with regards to Delete can be resolved by adding this to your .zshrc:
bindkey "^[[3~" delete-char
bindkey "^[3;5~" delete-char
Explanation
Depending on the terminal, Delete generates one of the following character sequences:
^[[3~
^[3;5~
You can see which sequence your terminal uses via sed -n l as explained here.
zsh tries to evaluate the longest match. In both cases, zsh matches ^[ first, which matches Esc. If you have vi mode enabled, this tells zsh to turn it on.
After this, vi mode reads the remaining characters, which are one of the following:
[3~ toggle the case of the next 3 characters
3;5~ repeat the last find operation 3 times then toggle the case of the next 5 characters
So if you haven't explicitly used bindkey on this character sequence, every time you press Delete with vi mode enabled, you will enter vi mode and the last character you typed will be uppercased.
Thanks to Adaephon in the comments below for help with this explanation.

In prezto how to get CTRL-RARROW working?

after installing prezto when I press CTRL - RIGHTARROW I can see these characters
source python;5C;5C;5C;5C
Whereas emacs key bindings like ALT- f work fine.
I just want my default keybindings where I can navigate using CTRL keys.
My efforts:
Raised a issue on github + browsed other similar issues as well.
Couldnt figure out how their solution would help my case.
Tried setting zstyle ':prezto:module:editor' key-bindings '' but it did not
work.
I have also checked modeles/editor/init.zsh but the script is
too long n I dont wanna make random changes and later keep
maintaining those.
Can anyone suggest a way so that my keybindings remain "UNCHANGED" even after .zpreztorc is loaded ?
If you're using the prezto editor module, it will override your key bindings. If you have it set to emacs mode with
zstyle ':prezto:module:editor' key-bindings 'emacs'
you will need to add your key bindings to that named keymap. You can do that with
bindkey -M emacs '^[[1;5C' forward-word
bindkey -M emacs '^[[1;5D' backward-word
This will need to be run after the editor module is loaded. You can do that by adding it to the bottom of your .zshrc file. I use the vi keymap, so I need to add the key bindings to both the viins and vicmd keymaps.
for keymap in 'emacs' 'viins' 'vicmd'; do
# [Ctrl-RightArrow] - move forward one word
bindkey -M $keymap '^[[1;5C' forward-word
# [Ctrl-LeftArrow] - move backward one word
bindkey -M $keymap '^[[1;5D' backward-word
done
unset keymap

In zsh how do you bind Ctrl+backspace to delete the previous word?

I'm trying to bind the command usualy binded to ^W with ctrl+backspace.
I have two problem here, one for each parameter of the bindkey command:
what is string to mean the ctrl+backspace
what is the command to delete the previous word
One may use bindkey '^H' backward-kill-word.
Note that, on old versions of GNOME terminal, it won't work; see How do I get Ctrl-Backspace to delete a word in vim within gnome-terminal? and Bug 420039 - VTE doesn't distinguish between backspace and control-backspace.
As reported by thorbjornwolf in his comment, commit 23c7cd0f fixed it.
As I pointed out here there is a chance that the keystrokes are different in some systems.
If the output of showkey -a is:
Ctrl+Backspace is ^?
then you should add the following line in your ~/.zshrc file:
bindkey '^?' backward-kill-word

Resources