Shell Editing Modes

Keyboard shortcuts to make life easier on the command line

Did you know that your shell probably has some very convenient editing keyboard shortcuts built right in, that will mostly work regardless of your terminal emulator, whether your logged in via a TTY, ssh, etc.? If we’re being honest, you probably did. But I didn’t learn about these until more recently than I would care to admit, and so I’m betting that there are at least a few people out there who also haven’t heard of them. This’ll be a pretty short one, but if you want to see some of these in action, check out my recent YouTube video on the subject.

Most Bourne shell derivatives (though not the Bourne Shell itself) support editing keybindings based on either emacs, or vi, the two major text editors on UNIX based systems. The major difference between the two is that emacs mode relies on combining CTRL and ALT with keys to trigger editing commands, whereas vi mode is modal: you transition between an editing mode and a command mode.

Default Editing Modes

Depending upon your shell, the default editing mode may differ. bash and tcsh will default to emacs mode. If you aren’t in emacs mode, check your shell’s rc and profile files and make sure that one of the commands from the next section isn’t present and changing the mode on you.

KornShell is little different. It’s “smarter” in that it determines the editing mode based on the value of the VISUAL environment variable, or EDITOR if VISUAL isn’t set. This means that it will use vi mode by default if those variables are set to vi or vim.

OpenBSD’s implementation of the KornShell1 behaves particularly badly in vi mode if you dare to attempt to use the arrow keys. So watch out for that one, it can easily catch you off guard.

As for zsh, the documentation claims that emacs is the default editing mode, however on my machine when I launch the shell (newly installed, without having made any configuration changes), I end up in vi mode. So I’m not sure what is going on there.

Changing Modes

On all three of the above Bourne shell derivatives, changing editing mode is done the same way. To enter vi mode, use

$ set -o vi

and to enter emacs mode,

$ set -o emacs

To make this change permanent, simply add the command to your shell’s rc or profile file (.bashrc, .profile, etc.).

On KornShell there is also a viraw mode, which is supposed to help with support for tab completion, but at least on the versions of the shell that I have used, I haven’t had any issues with completion in normal vi mode.

If you’re using tcsh, you need to use a different command. To enter emacs mode use,

% bindkey -e

and to enter vi mode, use

% bindkey -v

Emacs Mode Keybindings

I highly advocate the use of emacs mode in general. While I use neovim as my primary text editor, I find that vi mode for the shell is excessive. The modal nature of vi works very well when editing large text files, but on the shell you’re generally only working on a single line. It’s far more convenient to just hold down CTRL or ALT, rather than hit ESC to enter normal/command mode, do your editing command, and then return to insert mode. At least that is my opinion on the matter.

To that end, here’s a table of the emacs mode editing commands that I find most useful. There is a bit of variation between the editing commands from shell to shell, but they are more alike than they are different. I use bash and ksh generally, so I’ve included tables below for both of them.

Bash Editing Commands

Keybinding Effect
CTRL-a Move cursor to start of line
CTRL-e Move cursor to end of line
CTRL-f Move cursor right one character
ALT-f Move cursor right one word
CTRL-b Move cursor left one character
ALT-b Move cursor left one word
CTRL-d Delete character under the cursor2
ALT-d Delete word to the right of the cursor
CTRL-h Delete character to left of the cursor
ALT-h Delete word to left of cursor
CTRL-k Delete all characters to the right of the cursor
CTRL-u Delete all characters to the left of the cursor
CTRL-t Transpose the two characters immediately left of the cursor
ALT-u Convert next word to uppercase
ALT-l Convert next word to lowercase
ALT-c Capitalize first letter of next word
CTRL-l Clear the screen (equivalent to the clear command)

KornShell Editing Commands

Keybinding Effect
CTRL-a Move cursor to start of line
CTRL-e Move cursor to end of line
CTRL-f Move cursor right one character
ALT-f Move cursor right one word
CTRL-b Move cursor left one character
ALT-b Move cursor left one word
CTRL-d Delete character under the cursor2
ALT-d Delete word to the right of the cursor
CTRL-h Delete character to left of the cursor
ALT-h Delete word to left of cursor
CTRL-k Delete all characters to the right of the cursor
CTRL-u Delete all characters on current line
CTRL-t Transpose the two characters immediately left of the cursor
ALT-c Convert next word to uppercase
CTRL-l Redraw the current line (doesn’t clear screen like on bash)

I won’t list out the vi mode keybindings, as they are basically the same keybindings as vi itself uses; if you are thinking about using vi mode, you probably already know them.

Conclusion

These editing keybindings make a world of difference as you start to internalize them. If you spend a lot of time on a command line, I highly suggest that you work on learning them. Some of them, particularly CTRL-a, CTRL-e, ALT-d, and CTRL-t, can save you a lot of time when you’re fixing a command, or pulling down a command from history and modifying an argument or two.


  1. Which is actually based on the Public Domain KornShell (pdksh), and not on the more modern ksh93. ↩︎

  2. This one is interesting, as ^D is a shell control sequence for EOF as well. It will behave as the editing command if there is text on the line, and as EOF is the line is empty. This accounts for the difference in behavior between ^D as EOF in bash, and ^Z as EOF in Command Prompt. In Command Prompt, the ^Z character actually is entered into the input text, and can be added anywhere on a line. On bash, this is not the case. ↩︎

Related