64

I'm always little bit confused when bash in vi-mode is switched to insert-mode, because it doesn't give any tip about used mode (command or edit). Is there any way to distinguish mods? May be automatic change of cursor color or something like that?

chuwy
  • 6,310
  • 4
  • 20
  • 29
  • nit-pick: you mean whether it is in `normal` mode or in `insert mode` (because there is no edit mode and bash doesn't implement the command mode) – sehe Oct 25 '11 at 11:16
  • Ok, according some [tutorials](http://www.hypexr.org/bash_tutorial.php#vi) they are named as `command mode` and `insert mode`. So my and your vision are both half-truth. – chuwy Oct 25 '11 at 11:37
  • 1
    If switching to zsh is an option, this is supported. See [here](http://stackoverflow.com/a/3791786/587717). – Edd Steel Jan 18 '12 at 00:09
  • Oh, wow. Indeed I switched to zsh only a few days ago. Your advice is appeared just in time:) – chuwy Jan 19 '12 at 00:15
  • Regarding terminology, the [POSIX specification for command-line editing](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sh.html#tag_20_117_13_03) uses the terms *insert mode* and *command mode*. – Anthony Geoghegan Aug 23 '19 at 14:09

3 Answers3

61

in /etc/inputrc (or ~/.inputrc) add this:

set show-mode-in-prompt on

this will prefix your prompt with + while in insert-mode, and : while in command mode in bash 4.3

EDIT: in the latest version of bash 4.4, you will instead get a prompt prefixed with "(ins)" or "(cmd)" by default. but, you can change that:

set vi-ins-mode-string "+"
set vi-cmd-mode-string ":"

also, you can use color codes like '\e[1;31m', but surround them with '\1' and '\2' to keep readline happy:

set vi-cmd-mode-string "\1\e[1;31m\2:\1\e[0m\2"
Isaac Hanson
  • 1,088
  • 9
  • 14
58

Building on @Isaac Hanson's answer you can set the cursor style to reflect the mode (just like in VIM) by setting these in your .inputrc:

set editing-mode vi
set show-mode-in-prompt on
set vi-ins-mode-string \1\e[6 q\2
set vi-cmd-mode-string \1\e[2 q\2

# optionally:
# switch to block cursor before executing a command
set keymap vi-insert
RETURN: "\e\n"

This will give you a beam cursor in insert mode or a block cursor for normal mode.

Other options (replace the number after \e[):

        Ps = 0  -> blinking block.
        Ps = 1  -> blinking block (default).
        Ps = 2  -> steady block.
        Ps = 3  -> blinking underline.
        Ps = 4  -> steady underline.
        Ps = 5  -> blinking bar (xterm).
        Ps = 6  -> steady bar (xterm).

Your terminal must support DECSCURSR (like xterm, urxvt, iTerm2). TMUX also supports these (if you set TERM=xterm-256color outside tmux).

laktak
  • 57,064
  • 17
  • 134
  • 164
  • 1
    Is it possible to do both i.e. set cursor and the prefix? – Ingadi Mar 25 '19 at 18:07
  • 3
    @MartianTomatoes yes, just append it to the string value – laktak Mar 25 '19 at 21:37
  • Do you have a link to your source? – winklerrr Feb 11 '20 at 23:21
  • @winklerrr: one proper ref. would be : https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_. Lookup the section with header "CSI Ps SP q" about half way down. It makes for a rather terse reading. You're warned! – Cbhihe May 01 '20 at 10:42
  • 1
    The hint with `set keymap vi-insert...` is great - it restores the block cursor when entering vim. Otherwise in vim command mode I had a bar cursor left from Bash so there was an inconsistency in vim. Btw. would you mind explaining what that syntax `set keymap ... RETURN: "\e\n"` means exactly? – bloody Jan 04 '21 at 09:28
  • 2
    @bloody - when you press enter in insert mode it switches to command mode first (\e = ESC) which updates the cursor before running the command – laktak Jan 04 '21 at 13:54
14

After years of using vi mode in korn shell, I have basically trained myself to just tap ESC a few times before I type any commands, and ESC then i to start typing.

The basic premise being that if you just hit ESC, you know precisely what mode you are in.

Clarkey
  • 1,553
  • 5
  • 22
  • 34