How to change cursor shape depending on VI mode in Bash?

SOLUTION:

I am posting my answer to my own question here as recommended.

This solution works for Bash 4.4+, since, starting with that version of Bash, version 7.0 of the GNU readline library is used, which includes the necessary additions of the vi-cmd-mode-string and vi-ins-mode-string variables.

These variables can be set as follows in your .inputrc file in order to achieve the functionality I described above:

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

EXPLANATION:

For those who are actually interested in how the above solution works.

These two variables, vi-cmd-mode-string and vi-ins-mode-string, are printed to your terminal along with the command prompt in order to provide a sort of visual indicator as to which mode you are currently in (i.e. command mode vs. insert mode).

The defaults for these two variables are “(cmd)” and “(ins)” for command and insert modes, respectively. So if you were to just leave them as the defaults and had a command prompt of, say, PS1='>>>', then your prompt would look like the following:

  • Command mode:

      (cmd) >>>
    
  • Insert mode:

      (ins) >>>
    

According to the man-page for readline (see below), you can also specify non-printable characters, such as terminal control sequences, by embedding the sequences between the \1 and \2 escape characters.

vi-cmd-mode-string ((cmd))
       This  string  is  displayed immediately before the last line of the primary prompt when vi editing mode is active and in command mode.  The value is expanded like a key binding, so the
       standard set of meta- and control prefixes and backslash escape sequences is available.  Use the \1 and \2 escapes to begin and end sequences of non-printing characters, which  can  be
       used to embed a terminal control sequence into the mode string.
vi-ins-mode-string ((ins))
       This  string is displayed immediately before the last line of the primary prompt when vi editing mode is active and in insertion mode.  The value is expanded like a key binding, so the
       standard set of meta- and control prefixes and backslash escape sequences is available.  Use the \1 and \2 escapes to begin and end sequences of non-printing characters, which  can  be
       used to embed a terminal control sequence into the mode string.

Therefore, in my above solution, I am embedding the terminal control sequences, \e[2 q (make the cursor a vertical bar) and \e[6 q (make the cursor a pipe), between these \1 and \2 escape characters, resulting in my cursor having the shape of a vertical bar while in command mode and a pipe shape while in insert mode.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)