Is there a way to switch Bash or zsh from Emacs mode to vi mode with a keystroke?
I'd like to be able to switch temporarily from emacs mode to vi mode, since vi mode is sometimes better, but I'm usually half-way through typing something before I realize I want to use vi mode.
I don't want to switch permanently to vi mode, because I normally prefer emacs mode on the command line, mostly because it's what I'm used to, and over the years many of the keystrokes have become second nature. (As an editor I generally use emacs in viper mode, so that I can use both vi and emacs keystrokes, since I found myse开发者_如何学JAVAlf accidentally using them in vi all the time, and screwing things up, and because in some cases I find vi keystrokes more memorable and handy, and in other cases emacs.)
You can create a toggle since the key bindings are separate between vi mode and emacs mode.
$ set -o emacs
$ bind '"\ee": vi-editing-mode'
$ set -o vi
$ bind '"\ee": emacs-editing-mode'
Now Alt-e (or Esc e) will toggle between modes.
Add this somewhere in your definition for PS1
so you have an indicator in your prompt of which mode you're in. It won't show the change immediately when you toggle modes, but it will update when a new prompt is issued.
$(set -o | grep emacs.*on >/dev/null 2>&1 && echo E || echo V)
Aha! I looked at the readline source, and found out that you can do this:
"\M-v": vi-editing-mode
"\M-e": emacs-editing-mode
There doesn't appear to be a toggle, but that's probably good enough!
For posterity's sake, here's my original answer, which could be useful for people trying to do things for which there is no readline function.
Here's a way you could set it up, clearing the current command line in the process. Not what you want, I know, but maybe it'll help someone else who finds this question. In ~/.inputrc:
"\M-v": "\C-k\C-uset -o vi\C-j" # alt (meta)-v: set vi mode
"\M-e": "\C-k\C-uset -o vi\C-j" # alt (meta)-e: set emacs mode
or to toggle...this should work:
"\M-t": "\C-k\C-u[[ \"$SHELLOPTS\" =~ '\\bemacs\\b' ]] && set -o vi || set -o emacs\C-j"
These are essentially aliases, taken one step farther to map to keys in readline so that you don't have to type an alias name and hit enter.
The following .inputrc
lines allow Meta / Alt+E to switch between emacs
and vi-insert
modes.
Mooshing both j and k simultaneously will take you to vi-command
mode.
Note: The only English word with "kj" is "blackjack", no words contain "jk")
set keymap emacs
"\ee": vi-editing-mode
"jk": "\eejk"
"kj": "\eejk"
set keymap vi-insert
"\ee": emacs-editing-mode
"jk": vi-movement-mode
"kj": vi-movement-mode
set keymap vi-command
"\ee": emacs-editing-mode
Note: If you add a binding under keymap emacs
to vi-movement-mode
to try to switch straight to vi-command
mode, the prompt doesn't update if you have show-mode-in-prompt on
, hence the above work-around is needed.
I finally found out how to toggle vi and emacs mode with a single key e.g. [alt]+[i] in zsh:
# in the .zshrc
# toggle vi and emacs mode
vi-mode() { set -o vi; }
emacs-mode() { set -o emacs; }
zle -N vi-mode
zle -N emacs-mode
bindkey '\ei' vi-mode # switch to vi "insert" mode
bindkey -M viins 'jk' vi-cmd-mode # (optionally) exit to vi "cmd" mode
bindkey -M viins '\ei' emacs-mode # switch to emacs mode
精彩评论