Saturday, December 13, 2008

Surfing the Keyboard in BASH

You are probably familiar with common keyboard sequences like Ctrl-C to end a program, but there are dozens of useful shortcuts you can use in BASH to edit the command line, move around your command history, and control jobs. I've collected 18 useful Ctrl and Meta (Option) sequences to make you more productive in BASH. So grab your 'board and leave the wet suit at home, the water is warm this time of year.

Command Line Editing

BASH keyboard sequences come in two flavors, Ctrl and Meta. Ctrl sequences are straightforward, you hold down the Ctrl key while pressing another key. On a PC with Linux, the Meta key is usually mapped to Alt, but on a Mac, it is usually mapped to the Esc key. Since the Esc key is poorly placed for serious keyboarding, I suggest mapping the Meta key to the Option key.

To map Meta to Option in the OS X Terminal, use the menu and go to Terminal / Window Settings, select Keyboard in the drop down box at the top, and check 'Use option key as meta key'.

To map Meta to Option in iTerm, use the menu and go to Bookmarks / Manage Profile, expand Keyboard Profiles, select Global, and check the 'Option Key as Meta' radio button.

With that out of the way, here are some shortcuts to edit commands.

Key Sequence Result
Ctrl-A moves the cursor to the beginning of the line
Ctrl-E moves the cursor to the end of the line
Ctrl-D deletes the character under the cursor
Ctrl-F moves the cursor forward one character
Ctrl-B moves the cursor backward one character
Ctrl-K deletes from the cursor to the end of the line
Option-B moves the cursor back one word
Option-F moves the cursor forward one word
Option-L downcase a word starting from the cursor
Option-U upcase a word starting from the cursor

Moving through history

BASH records all commands you enter in a personal history file called .bash_history in your home directory. Notice the dot (.) at the start of the name, indicating it is a hidden file. Finder won't show you hidden files without some tweaking, but you can easily see hidden files in Terminal with the ls -a command. If you are paranoid, BASH has options to turn history off, but it is very useful if you work much at the command line. Here are the history shortcuts:

Key Sequence Result
Ctrl-R start an incremental reverse history search, Ctrl-J to stop
Ctrl-S start an incremental forward history search, Ctrl-J to stop
Ctrl-J stop incremental search, leaving command to edit
Ctrl-P (also up arrow) fetch the previous command from history
Ctrl-N (also down arrow) fetch the next command from history

Incremental searches work by matching the string entered with the most recent history command that contains the string. The more you type, the more accurate the match. Use Ctrl-J (or the left or right arrow keys) to end the search, leaving the matched command on the command line ready to either edit or run.

Job Control

OK, nothing new here...

Key Sequence Result
Ctrl-Z suspends the foreground job, returns control to user
Ctrl-C send signal 3 (SIGQUIT) to the foreground job


Key Sequence Result
Ctrl-X Ctrl-V show current version of BASH

All examples given above are default key bindings in BASH. There are additional BASH functions that are not automatically bound to a key sequence. To see all current key bindings, plus all unmapped functions, run this command:

bind -P

If you want to set your own key sequences or macros, you can define them in a readline run control file in your home directory called .inputrc (you will need to create one). Readline is a library that provides command line control for BASH. To define a new key sequence, edit the .inputrc file and enter your new definitions one per line. You need to use the readline syntax as follows:

key-sequence: function

\C- means Ctrl plus another key
\M- means Meta (Option) plus another key
\e is the ESC character
\\ is a backslash
\" is a double quote
\' is a single quote

For example, to bind Option-z (meta-z) to the tty-status function, add this line to your .inputrc file:

"\M-z": tty-status

Close Terminal and start a new shell so it reads the .inputrc file, then try Option-z and you should see something like this:

load: 0.61 cmd: bash 10561 running 0.00u 0.00s

You can create your own key sequences for anything BASH supports, or change them to taste. Few people have a burning desire to change the default BASH key sequences, but if you need to change your keyboard surfing style, you know how... dude.