123

When using vi mode (set -o vi) with Bash, it would be nice to have a prompt that depends on the mode you are currently in (insert or command). How does one find out this editing mode?

B.t.w, this seems to be possible in ZSH:

  • Am curious about this too. Been hunting through bash documentation, but haven't found anything. – Andrew Ferrier Jan 20 '10 at 11:06
  • [Consider toggling a single character in the prompt to indicate the mode.](https://unix.stackexchange.com/questions/4870/is-it-possible-to-have-vim-key-bindings-in-terminal#comment1039830_4872) – FriskySaga Dec 02 '21 at 20:01

9 Answers9

73

Fresh bash 4.3 and readline 6.3 have something for you guys.. from the changelog:

4.  New Features in Readline
j.  New user-settable variable, show-mode-in-prompt, adds a characters to the
    beginning of the prompt indicating the current editing mode.

So putting

set show-mode-in-prompt on

into /etc/inputrc or ~/.inputrc (thx stooj) should affect all your readline-enabled programs ;)

eMPee584
  • 1,945
  • 20
  • 20
  • any status on this? I'm trying to find something like this (not for bash but for other readline based prompts that I use). I've been googling and haven't found any other update (apart from this and the article [you referenced](http://cnswww.cns.cwru.edu/php/chet/readline/CHANGES)) – Mike H-R Mar 14 '14 at 12:28
  • 4
    Just adding on from eMPee584 - if you are running bash 4.3 or higher, add the following to your ~/.inputrc file set show-mode-in-prompt This adds a + to the very left of your prompt if you are in edit mode, and a : if you are in command mode. – stooj Mar 29 '14 at 04:25
  • 3
    So whilst this works; is there a way to move where this vi-mode character sits int he prompt? If you have multi-line prompts (custom) it doesn't work all that well :) – James Mills Oct 22 '15 at 14:40
  • For 4.3 it's always at the start of the prompt and, unfortunately, readline will only redraw the last line of a multiline prompt. See the "Multiline prompt and .inputrc" answer for a workaround or see the answer about patching bash 4.3 with 4.4's fix for this. – studgeek Jun 22 '16 at 15:36
26

Bash 4.4 / Readline 7.0 will add support for user-settable mode strings.

You can try the beta versions, but they seem a bit buggy at the moment. They also don't yet support specifying where in the prompt you want the mode indicator to occur (which I think is the killer feature).

If you don't want to wait, and aren't afraid of a little compilation, I've published patched versions of bash 4.3 and readline 6.3 to github that support this functionality.

With the patched versions you can do stuff like this:

enter image description here

More details, including how to install, are available at https://github.com/calid/bash

Dylan Cali
  • 1,463
  • 1
  • 13
  • 17
19

After searching google, looking through the bash man page and then looking through the bash source code (the lib/readline/vi_mode.c) it looks like there is no easy way to change the prompt when moving from insert mode to command mode. It looks like there might be an opportunity here for someone to patch the bash source though as there are calls for starting and stopping the modes in the source.

Upon seeing your post it got me interested in the bash vi mode setting. I love vi and would why not on the command line. However it looks like we will have to keep track of whether we are in insert mode without a prompt change (so sayeth many forum posts) For what it is worth you are always in insert mode unless you hit ESC. Makes it a little easier, but not always as intuitive.

I'm upping your question as I'm interested in seeing where this goes.

Jeremy Heslop
  • 568
  • 3
  • 8
8

This is what I have in ~/.inputrc

set show-mode-in-prompt on
set vi-ins-mode-string \1\e[34;1m\2└──[ins] \1\e[0m\2
set vi-cmd-mode-string \1\e[33;1m\2└──[cmd] \1\e[0m\2

Insert mode it is colored blue.

└──[ins]

Command mode it is colored yellow.

└──[cmd]

The downside is it does not display on a tty meaning it only works on a terminal emulator only the colors.

Jetchisel
  • 7,493
  • 2
  • 19
  • 18
7

Multiline prompt and .inputrc

Inputrc has an option to show a + for insert and : for normal mode, by adding set show-mode-in-prompt on in the ~/.inputrc as eMPee584 wrote, but this does not work well with multiline prompt (with older versions of bash and readline).

A solution is have a single line PS1 (>), and a function that echo something before the prompt. It is built into bash and called PROMPT_COMMAND.

function prompt {
    PS1=' > '
    echo -e "$(date +%R)  $PWD"
}

PROMPT_COMMAND='prompt' 

The usual prompt strings are not available in echo of printf. The -e is to interprete color codes, and it is not necessary to add \[ or \], which doesn't work anyway.

Insert mode:

20:57   /home/sshbio/dotfiles/bash
+ > _

Normal mode:

20:57   /home/sshbio/dotfiles/bash
: > _

Pressing tab, only the PS1 is repeated, which makes sense for me:

20:57   /home/sshbio/dotfiles/bash
+ > ls _
bashrc      bash_profile     inputrc
+ > ls _

Preview (Source)

  • 1
    If using colours in `vi-cmd-mode-string` or `vi-ins-mode-string`, these should be prefixed by `\1` and postfixed by `\2`. See [here](https://www.gnu.org/software/bash/manual/bash.html#Readline-Init-File). Also, `\[` and `\[` should still be emitted, but you'll need `\\[` and `\\]` inside printf. – Tom Hale May 09 '17 at 07:38
7

Different Prompt and Cursor Style via .inputrc

First you should make sure that you're running a bash version higher than 4.3:

$ bash --version
GNU bash, version 4.4

Then put the following lines in your ~/.inputrc:

#################### VIM ####################
# FOR MORE INFORMATION CHECK:
# https://wiki.archlinux.org/index.php/Readline

# TURN ON VIM (E.G. FOR READLINE)
set editing-mode vi

# SHOW THE VIM MODE IN THE PROMPT (COMMAND OR INSERT)
set show-mode-in-prompt on

# SET THE MODE STRING AND CURSOR TO INDICATE THE VIM MODE
#   FOR THE NUMBER AFTER `\e[`:
#     0: blinking block
#     1: blinking block (default)
#     2: steady block
#     3: blinking underline
#     4: steady underline
#     5: blinking bar (xterm)
#     6: steady bar (xterm)
set vi-ins-mode-string (ins)\1\e[5 q\2
set vi-cmd-mode-string (cmd)\1\e[1 q\2

In command mode, the cursor is displayed as block.
In insert mode, the cursor is displayed as vertical bar.

The prompt itself will then look like this depending on the mode:

(cmd)$ ... 
(ins)$ ...
winklerrr
  • 13,026
  • 8
  • 71
  • 88
  • Incredible!- Ty! and I've just learned doing something like this `set vi-cmd-mode-string \033[1;32m\1\e[1 q\2` will just change the color of your prompt symbol.. Which is exactly what I wanted!- not another `()` – Nealium Dec 11 '22 at 03:18
7

Spacemacs style colored cursor

This setup matches the spacemacs cursor with dotspacemacs-colorize-cursor-according-to-state set to t.

set editing-mode vi

set vi-ins-mode-string \1\e[5 q\e]12;green\a\2
set vi-cmd-mode-string \1\e[1 q\e]12;orange\a\2

set show-mode-in-prompt on

enter image description here

Sam Hasler
  • 12,344
  • 10
  • 72
  • 106
  • 2
    Can you explain what those ansi term codes are doing? – Lin May 08 '21 at 08:43
  • 1
    @Lin I know this is an old comment and an even older post but after digging through literal decades-old documents I have found an explanation for all this magical knowledge people here seem to possess. Looking to change my prompt and cursor colors I stumbled upon 2 different escape sequences: \e[ and \e] The first one is called a CSI (Control Sequence Introducer) The second one is called a OSC (Operating system command). followed by a ;12 it tells the term emulator to change the color of the cursor. Check it out here: https://www.xfree86.org/current/ctlseqs.html Look for "Change text" – Orel Fichman Feb 14 '22 at 21:23
  • Sam, what terminal emulator and OS are you using? I'm using iTerm of MacOS Monterey and it doesn't seem to work for me although I read some extensive documentation of this (link in my previous comment addressing Lin). I know this is an old comment but I hope you'll see this and maybe shed some light on this for me :) Thanks in advance. – Orel Fichman Feb 14 '22 at 21:25
  • @OrelFichman I'm using Windows Terminal with Git Bash (Git for Windows). It says it's GNU bash, version 4.4.23(2)-release (x86_64-pc-msys) – Sam Hasler Feb 15 '22 at 23:25
  • @SamHasler thanks, after reading some more I found out this seems to be a GNU-specific escape code. I managed to get it to work on my Iterm2 using their proprietary escape codes. – Orel Fichman Feb 16 '22 at 04:45
2

for Multiline prompt like this image

my work arround is like this

my bash prompt

export PS1=" ┌錄 \[\e[32m\]\u\[\e[m\]\[\e[32m\]@\[\e[m\]\[\e[32m\]\h\[\e[m\] \w \\$ \n "

.inputrc

set show-mode-in-prompt on
set vi-ins-mode-string " └──錄 (ins):"
set vi-cmd-mode-string " └──錄 (cmd):"

hope this helped you

mark
  • 44
  • 2
0

I try to get a indicator for BASH vi mode also, and you all learned it's sound simple and just no way to do it yet.

My current approach is: hit 'a' when I not sure which mode is. IF 'a' appears after BASH PROMOT, I learn I am in 'INSERT' mode. THEN, I hit 'RETURN' and continue. This is a easy way for me to solve the small annoyance.

By the way, I 'alias a='cal', or something else to give the empty hit 'a' little usefulness.

Andrew_1510
  • 12,258
  • 9
  • 51
  • 52
  • 2
    Would make more sense to me to just hit "esc||c-[" rather than a. Then you don't have to look to know what mode your in; or insert unwanted characters you have to remove (or press return) – wom Sep 26 '12 at 19:12