开发者

Is there a way to switch Bash or zsh from Emacs mode to vi mode with a keystroke?

开发者 https://www.devze.com 2022-12-27 10:42 出处:网络
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'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
0

精彩评论

暂无评论...
验证码 换一张
取 消