Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I want to switch to vi editing mode in a readline environment. But I don't want to use 'set -o vi'. I want to temporarily switch using a keyboard shortcut. The man page says I can do this with M-C-j. But that doesn't work for me.

I'm using Ubuntu and an xterm. Doesn't work under gnome-terminal either.

share|improve this question

I'd confirm that the keyboard mapping Meta+Control+j is in fact correct on your system. You can use this command to list all the keybinds for the various modes of Bash. On my system there wasn't a keybinding either.

$ bind -P| grep edit
edit-and-execute-command can be found on "\C-x\C-e".
emacs-editing-mode is not bound to any keys
vi-editing-mode is not bound to any keys

You can do the following so that when you type Esc+e it will toggle between the 2 modes.

$ set -o emacs
$ bind '"\ee": vi-editing-mode'
$ set -o vi
$ bind '"\ee": emacs-editing-mode'

The bind command now shows this:

in vi mode

$ bind -P |grep edit
edit-and-execute-command is not bound to any keys
emacs-editing-mode can be found on "\ee".
vi-editing-mode is not bound to any keys

in emacs mode

$ bind -P |grep edit
edit-and-execute-command can be found on "\C-x\C-e".
emacs-editing-mode is not bound to any keys
vi-editing-mode can be found on "\ee".

Now you can use Esc+e to toggle between the 2 different modes.

share|improve this answer
Note that you have to be quick when typing ESC E. If you pause you will go from vi-insert to vi-command mode, or just cancell the current vi command. – spelufo Feb 20 '15 at 3:05
up vote 2 down vote accepted

Bash explicitly disables this and a few other Readline shortcuts. See the initialize_readline() function in the bash source code (http://www.catonmat.net/download/bashline.c):

   /* In Bash, the user can switch editing modes with "set -o [vi emacs]",
      so it is not necessary to allow C-M-j for context switching.  Turn
      off this occasionally confusing behaviour. */
   rl_unbind_key_in_map (CTRL('J'), emacs_meta_keymap);
   rl_unbind_key_in_map (CTRL('M'), emacs_meta_keymap);
#if defined (VI_MODE)
  rl_unbind_key_in_map (CTRL('E'), vi_movement_keymap);

I don't seem to be able to override this behavior using the Readline configuration file (.inputrc).

share|improve this answer

Here's what I ended up using for my ~/.inputrc, based on slm's answer.

set show-mode-in-prompt on

set keymap emacs
"\ea": vi-editing-mode

set keymap vi-command
"k": history-search-backward
"j": history-search-forward
"z": emacs-editing-mode
"\ea": emacs-editing-mode

set keymap vi-insert
"\ea": emacs-editing-mode
"\C-l": clear-screen
"\C-e": end-of-line
"\C-k": kill-line

set editing-mode vi

I tried the $if mode= syntax, but I think that is resolved statically (one time, when reading the file), so it doesn't work as I expected. So we need to switch to each keymap and modify its key bindings, even if previously set on another keymaps. At the end I say which mode I want to start with.

share|improve this answer

I tried to have emacs-styled mappings being used in vi mode. I ended up with:

set keymap vi-command
"k": history-search-backward
"j": history-search-forward

set keymap vi-insert
"\C-A": beginning-of-line
"\C-B": backward-char
"\C-D": delete-char
"\C-E": end-of-line
"\C-F": forward-char
"\C-K": kill-line
"\C-L": clear-screen
"\C-N": next-history
"\C-P": previous-history
"\C-O": operate-and-get-next

# Enable Readline not waiting for additional input when a key is pressed.
# Needed for the mappings below.
set keyseq-timeout 0

# `yank-last-arg` does not work exactly as in emacs mode
"\e.": yank-last-arg
"\e\177": backward-kill-word
"\e0": digit-argument
"\e1": digit-argument
"\e2": digit-argument
"\e3": digit-argument
"\e4": digit-argument
"\e5": digit-argument
"\e6": digit-argument
"\e7": digit-argument
"\e8": digit-argument
"\e9": digit-argument
"\eb": backward-word
"\ec": capitalize-word
"\ed": kill-word
"\ef": forward-word
"\el": downcase-word
"\en": non-incremental-forward-search-history
"\ep": non-incremental-reverse-search-history
"\et": transpose-words
"\eu": upcase-word
"\ey": yank-pop

# some other useful mappings

"\e/": complete-filename
"\ek": kill-whole-line
"\eo": "\C-v\C-j"
# quickly switch to "normal" mode
"\C-[": vi-movement-mode
# perserve the currently editing line so that we can 
# do something else before restoring it.
"\eg": insert-comment
"\er": "\C-R#\C-A\C-D\C-E"

set editing-mode vi

It is helpful to read the man page for readline and the READLINE section on the bash man page.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.