Tuesday, April 01, 2025

Customizing the Bash command prompt for vi editing mode

Customizing readline with inputrc

A brief introduction to the GNU Readline library, customizing user input using the .inputrc file, and the vi editing mode.

(Skip ahead to setting the mode indicator configuration.)

Introduction

I've been using vi/vim as my preferred editor long enough for the basic movement and editing keyboard shortcuts(also know as a key binding) to become second nature to me. Learning that the Bash shell supports multiple editing modes, including vi, gave me the opportunity to use this niche skill with other tools. I appreciate the idea that the key bindings that I had learned through using vi had some usefulness outside of a single application.

Bash supports this functionality through a library called Readline. Switching from Bash's default Emacs editing mode over to vi editing mode made sense, to me. Being able to switch tools and not have to remember a different set of keyboard shortcuts is convenient.

One feature that was missing, however, was a visual indicator of which mode I was currently in. For this, I needed to look at setting a couple of readline-functions that would modify the command line prompt to visually indicate whether one was in either insert or edit mode.

Setting the editing mode

By default, the Bash shell is set to use the readline Emacs editing mode.

To switch your command-line editing mode to vi, enter the following at the console:

set -o vi

If you are unsure which editing mode is currently being used in the shell, enter the command set -o from the command line. This will list the current state of the option-names and which editing mode is currently enabled:

The set command is a bash built-in that "sets or unsets values of shell options and positional parameters". See set --help for more details.

To make this change permanent, settings can be added in one of two files, depending on one's requirements.
For changing only the Bash shell to use the vi-editing mode, add the line set -o vi to the .bashrc.
Enabling the vi-editing mode for the Bash shell and any other tool that uses the Readline library, add the following line to the .inputrc file:

set editing-mode vi

From the readline(3) manpage:

Readline is customized by putting commands in an initialization file (the inputrc file). The name of this file is taken from the value of the INPUTRC environment variable. If that variable is unset, the default is ~/.inputrc. If that file does not exist or cannot be read, the ultimate default is /etc/inputrc.

Adding a Mode Indicator in the Prompt

Do you use set -o vi in your shell and can't remember whether you are in insert or edit/cmd mode? I do.

From the command line, activating a visual indicator at the prompt can be toggled with the following two commands:


bind 'set show-mode-in-prompt on'  
bind 'set show-mode-in-prompt off'  

From the man page:

If set to On, add a string to the beginning of the prompt indicating the editing mode: emacs, vi command, or vi insertion. The mode strings are user-settable (e.g., emacs-mode-string)

By default, this will place a string ((cmd)/(ins)) at the beginning of the prompt.

Moving between the modes can be done by pressing the Esc to enter the command mode and pressing the I key to resturn to insert mode.
This prompt can be customized with the vi-ins-mode-string and vi-cmd-mode-string variables.

If set from the command line, these indicators will persist only for the duration of that shell's existence.
To make the change permanent, add the following line to your .inputrc to place a visual indicator at the beginning of your prompt: set show-mode-in-prompt on

Personally, I prefer my command prompt slightly less cluttered. This is what my .inputrc file looks like for the mode indicators:


# Add mode indicators to command line
set show-mode-in-prompt on  
set vi-ins-mode-string "+"  
set vi-cmd-mode-string ":"  

This is my prompt with the customized mode indicators:

Different cursor shapes can also be configured for each mode. See the Arch Linux Readline wiki page for examples and a few more tips on modifying readline using the inputrc file.

vi editing mode

When opening a command line, the user will be in insert mode where text can be entered normally. When Esc or Ctrl+[ is pressed, an emulation of vi's cmd or normal mode will be entered and vi's keybindings can be used to move around and edit the command line. To return to insert mode, press the I key and text can be entered normally. Below is a list of some of the common key combinations:

  • 0 — Move to start of line
  • $ — Move to end of line
  • b — Move back a word
  • w — Move forward a word
  • e — Move to the end of the next word
  • dw — Delete a word
  • d$ — Delete to end of line
  • dd — Delete entire line
For a more complete list of commands, take a look at the Bash vi editing mode cheat sheet.