Bash Vi Command Line Editing

related: Using the Bash CLI

Excerpts paraphrased from the GNU Bourne-Again SHell manual

Command line editing is provided by the Readline library, which is used by several different programs, including Bash. By default, the line editing commands are similar to those of Emacs. A vi-style line editing interface is also available. Line editing can be enabled at any time using the -o emacs or -o vi options to the set builtin command, or disabled using the +o emacs or +o vi options to set.

While the Readline library does not have a full set of vi editing functions, it does contain enough to allow simple editing of the line. The Readline vi mode behaves as specified in the POSIX standard.

When you enter a line in vi mode, you are already placed in ‘insertion’ mode, as if you had typed an 'i'. Pressing ESC switches you into ‘command’ mode, where you can edit the text of the line with the standard vi movement keys, move to previous history lines with 'k' and subsequent lines with 'j', and so forth.

In this blog post there may be some confusion. Mostly I’ll be talking about command line editing; Occasionally I may talk about using a command line editor. You can always fire up the vi text editor by issuing its command. The crux of this post is about using programs in the mode where they’ll be flavored with vi. For example: You may be running Git at the terminal. Some of the Git features ask you to edit text. If you want this done in vi-style then keep reading.

$ set -o vi

$ set -o emacs
# Undo set -o vi

Tells the Readline library to use vi-style. This will affect command editing, command history and programs you run in the terminal which do use the Readline library.

$ export EDITOR=vi VISUAL=vi

Signals to programs which do NOT use the Readline library that vi-style is your preferrence — by setting environment variables.

export — specifies that those two variables are to have global scope. In other words they are valid for any sub-shell or script you may run from the current shell. Child processes cannot export variables back to the parent processes that spawned them.

Both emacs- and vi-modes introduce the potential for clashes with control keys set up by the UNIX terminal interface. These control keys override their functions in the editing modes.

Changing command line editing to vi-style by using the set command or by assigning the variables EDITOR/VISUAL a value of vi (and export) will only affect the current shell and its child processes.

If you start bash with the -noediting option there will be no command line editing.

All of bash’s command history facilities depend on a list that records commands as you type them into the shell. Whenever you log in or start another interactive shell, bash reads an initial history list from the file .bash_history in your home directory. From that point on, every bash interactive session maintains its own list of commands. When you exit from a shell, it saves the list in .bash_history. You can call this file whatever you like by setting the environment variable HISTFILE.

Vi-mode essentially creates a one-line editing window into the history file.

Input mode — is for typing commands (as in normal bash use)

Control mode — is for moving around the command line and the history file.

Here’s more about input mode:

When you are in input mode, you can type commands in and hit RETURN to run them. In addition, you have minimal editing capabilities via control characters, which are summarized shown here.

Command Description
BACKSPACE Delete previous character
DEL Delete current character
CTRL-w Erase previous word (i.e., erase until a blank)
CTRL-v Quote the next character (meaning echo the next char I type)
ESC Enter control mode

When you use CTRL-v you are telling bash: “the next thing I enter at the keyboard is a single character which you will insert.”

Movement Commands (in Command Mode)

non-blank word — is any sequence of non-blank characters

word — is any sequence of only alphanumeric characters (letters and digits) plus the underscore (_), or any sequence of only non-alphanumeric characters

Command Description
h Move left one character
l Move right one character
w Move right one word
b Move left one word
W Move right to beginning of next non-blank word
B Move left to beginning of preceding non-blank word
e Move to end of current word
E Move to end of current non-blank word
0 Move to beginning of line
^ Move to first non-blank character in line
$ Move to end of line

All of these commands except the last three can be preceded by a number that acts as a repeat count. Whenever you type a number for the repeat count, the number replaces the command prompt for the duration of the repeat command. If your keyboard has cursor motion keys (“arrow” keys), you can use the left and right arrows to move between characters instead of the h and l keys. Repeat counts will work with the cursor keys as well.

Commands for Entering Input Mode

Command Description
i Text inserted before current character (insert)
a Text inserted after current character (append)
I Text inserted at beginning of line
A Text inserted at end of line
R Text overwrites existing text

Deletion (in Command Mode)

Command Description
dh Delete one character backwards
dl Delete one character forwards
db Delete one word backwards
dw Delete one word forwards
dB Delete one non-blank word backwards
dW Delete one non-blank word forwards
d$ Delete to end of line
d0 Delete to beginning of line

These commands have a few variations and abbreviations. If you use a c instead of d, you will enter input mode after it does the deletion. You can supply a numeric repeat count either before or after the d (or c). This table lists the available abbreviations.

Command Description
D Equivalent to d$ (delete to end of line)
dd Equivalent to 0d$ (delete entire line)
C Equivalent to c$ (delete to end of line, enter input mode)
cc Equivalent to 0c$ (delete entire line, enter input mode)
X Equivalent to dl (delete character backwards)
x Equivalent to dh (delete character forwards)

un-delete commands — vi-mode maintains a delete buffer that stores all of the modifications to text on the current line only (note that this is different from the full vi editor). The command u undoes previous text modifications. A related command is . (dot), which repeats the last text modification command.

There is also a way to save text in the delete buffer without having to delete it in the first place: just type in a delete command but use y ("yank") instead of d. This allows you to retrieve the yanked text as many times as you like later on. The commands to retrieve yanked text are p, which inserts the text to the right of the cursor, and P, which inserts it to the left of the cursor.


Command Description
k or - Move backward one line
j or + Move forward one line
G Move to line given by repeat count
/string Search backward for string
?string Search forward for string
n Repeat search in same direction as previous
N Repeat search in opposite direction of previous

(more) Movement

Command Description
fx Move right to next occurrence of x
Fx Move left to previous occurrence of x
tx Move right to next occurrence of x, then back one space
Tx Move left to previous occurrence of x, then forward one space
; Redo last character-finding command
, Redo last character-finding command in opposite direction

One final command rounds out the vi control mode commands for getting around on the current line: you can use the pipe character (|) to move to a specific column, whose number is given by a numeric prefix argument. Column counts start at 1; count only your input, not the space taken up by the prompt string. The default repeat count is 1, of course, which means that typing | by itself is equivalent to 0.

Text Completion

Although not a feature of the vi editor — Text completion is available in vi-mode.

Backslash (\) is the command that tells bash to do completion. If you type in a word, hit ESC to enter control mode, and then type \, one of four things will happen:

  1. If there is nothing whose name begins with the word, the shell will beep and nothing further will happen.
  2. If there is a command name in the search path, a function name, or a filename that the string uniquely matches, the shell will type the rest of it, followed by a space in case you want to type in more command arguments. Command name completion is only attempted when the word is in a command position (e.g: at the start of a line).
  3. If there is a directory that the string uniquely matches, the shell will complete the filename, followed by a slash.
  4. If there is more than one way to complete the name, the shell will complete out to the longest common prefix among the available choices. Commands in the search path and functions take precedence over filenames.

A related command is *. It behaves similarly to ESC-\, but if there is more than one completion possibility (number four in the previous list), it lists all of them and allows you to type further. Thus, it resembles the * shell wildcard character.

Less useful is the command =, which does the same kind of expansion as *, but in a different way. Instead of expanding the names onto the command line, it prints them, then gives you your shell prompt back and retypes whatever was on your command line before you typed =.

Other Bash vi command mode commands:

CTRL-L — Clear the screen and redraw the current line on it.

_ — Append last word of previous command, enter input mode. A repeat count preceding _ causes the nth word in the previous command to be inserted in the current line; without the count, the last word is used. Omitting the repeat count is useful because a filename is usually the last thing on a UNIX command line, and because users often run several commands in a row on the same file.

~ — Invert (twiddle) case of current character(s). A repeat count of n preceding the ~ changes the case of the next n characters. The cursor will advance accordingly.

# — Prepend # (comment character) to the line and send it to the history file; useful for saving a command to be executed later without having to retype it.


About samehramzylabib

See About on
This entry was posted in Configure My Systems, UNIX Command Line. Bookmark the permalink.

One Response to Bash Vi Command Line Editing

  1. Pingback: Using the Bash CLI | Sam's PHP


Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s