Use Vim editing mode on the command line without losing recursive history search

historyvimzsh

I'm uzing zsh and, because I'm an avid Vim user, I just switched to using Vim-style editing on the command line. (That means if I type ls foo/bar and decide I want to cd instead, I can hit Esc ^ to hop back to the beginning and cw cd to change ls to cd.

That's all dandy, but the problem is that I can no longer use Ctrl+R to do recursive history search. Is there another way to do it, or can I somehow override the Vim keybinding to get it back?

Best Answer

Of course you can no longer use Ctrl+R. If you consult the Z Shell manual you'll see that there's only a key binding for the history-incremental-search-backward widget in the emacs keymap. There are no key bindings for it in the vi keymaps.

But as you'll also find from reading the manual (It's chapter 18.), adding a key binding is a fairly simple exercise in the use of the bindkey command:

bindkey "^R" history-incremental-search-backward

You don't even have to use the zle command to map the widget onto a shell function, since this is a standard widget.

If you consult the answer to this same question that is on the Z Shell wiki, you'll see the commands for specifically adding this to the vi "command" and "insert mode" keymaps:

bindkey -M viins '^R' history-incremental-search-backward
bindkey -M vicmd '^R' history-incremental-search-backward

Also note that, as garyjohn points out, in the vi "command" keymap, the / character is bound to the vi-history-search-backward widget. The difference between this widget and the history-incremental-search-backward widget is the widget behaviour that applies once one is in history search mode. Here are a couple of the differences that you will notice:

  • Switching vi modes:
    • The search mode in history-incremental-search-backward toggles between the main and vicmd keymaps when you invoke the vi-cmd-mode widget whilst still staying in search mode. i.e. from emacs mode presssing the Esc key or Ctrl+XCtrl+V keys toggles the search mode between the emacs and vicmd keymaps. (Invoking history-incremental-search-backward from the vicmd keymap is thus troublesome, unless you bind something to vi-cmd-mode in the vicmd keymap as well.)
    • The search mode in vi-history-search-backward treats the vi-cmd-mode widget as accept-line and will end the search, re-entering the command mode that you entered the search from. i.e. (with the default bindings) / enters search mode from command mode and Esc goes back to command mode.
  • Repeating a search:
    • In history-incremental-search-backward, both the history-incremental-search-backward and the vi-rev-repeat-search widgets are recognized. i.e. (presuming that you have altered the bindings as above) both Ctrl+R and N will search for a preceding matching line.
    • In vi-history-search-backward, only the vi-rev-repeat-search widget is recognized. i.e. (presuming that you have altered the bindings as above) Ctrl+R will cause a beep and be ignored.
Related Question