I'm a command line guy. I know on a modern Linux system, I can point and click my way through the world like I were illiterate, or a Windows user, but I'm most comfortable in a Linux virtual console with my Bash prompt. I was using Linux happily for two years before I ever installed X (which I did only when the Worldwide Web got to where it was unusable without a graphical browser). I used to keep my mouse on the floor.
But still, there are times when typing out commands is really annoying, like to read my mail twenty times a day. Infamous two-character Unix commands, aliases, and word completion can only go so far to ease the keystroke burden. So I set up my F2 key to bring up the mail in one touch. F1 edits a certain file to which I refer throughout the day. Other keys type out option strings, filenames, and directory names that I used to type a lot.
I can put any command or part of a command on any key on the keyboard, and with the Alt and Control shifts, plus that pointless numeric keypad, not to mention the F keys, there are plenty from which to choose.
If you don't know how to do this, read on; it's not hard. But I'm going to give a little background on keyboard stuff first.
I've only worked with the IBM standard keyboard attached to an IBM (ISA) type computer, and some of the gritty details below may not apply to your keyboard. But I know the basic techniques work on any Linux keyboard.
Bash gets all of its commands (by "command," I mean your response to its command prompt) via the GNU Readline library. Readline is a subroutine library any program can use get a line of input from the keyboard. The advantage to a program of using Readline instead of just doing an ordinary file read of the terminal is that the Readline code lets the user do fancy editing of the line and perform a variety of magic to build up the line the way he wants before Readline passes it on to the program. All that command line editing that you do at a Bash prompt, such as backspace, delete word, history recall, and insert, are done not by Bash itself, but by the Readline subroutine that Bash calls.
Bash (also a GNU product) is the premier user of Readline and tends to get credit for all these fancy line editing functions (there are about sixty of them), and in fact they are described in the Bash man page. (And why not, if millions of users think amazon.com is a feature of AOL?) But all Bash does is call routines in the Readline library, and many other programs call the same routines and have the same line editing capability. Gdb, for example, and Postgresql's SQL prompt (Psql), and some Ftp clients.
Readline gets a stream of characters from the terminal (and it can
be any old terminal — not just a Linux virtual console) and
recognizes certain sequences and executes certain functions when it
sees them. For example, when it sees E, it inserts
You get to choose what Readline does when it sees some character
sequence via a Readline configuration file, which is normally called
.inputrc in your home directory.
The Readline function we will be using is the one to insert a string
into the line being built. To make the first example easy, we will do
something ridiculous: Assign the string ps -a --forest to the
character z. Once we do this, we will not be able to type
the letter z in any command, so it is truly ridiculous.
To do this, we add the following to our ~/.inputrc (if it
doesn't already exist, just make this the only line in a new file):
After doing this, you should find that when you hit the
z key, the characters ps -a --forest appear in
your command line buffer. Hit Enter and the ps
command executes. You will find that you don't have to type
But let's be more reasonable and put this ps command on
the F1 key. That's more complicated because pressing the
F1 key does not cause a single typeable character to be sent to
Readline. Instead, it causes a terminal-type-dependent sequence of
characters to be sent. Let's concern ourselves with a Linux console
only, and one that's using the default Linux console configuration.
In that case, F1 sends the four characters Escape,
[, [, and A.
But don't take my word for it. You can prove it by using
Readline's quoted-insert function, which you should find
bound to Control-V. quoted-insert means put the
following character into the line instead of executing any function
that might be assigned to it. You need this to keep Readline from
trying to interpret that Escape character. So at a Bash
prompt, type Control-V followed by F1. As Readline
places the Escape and the three characters after it in the
input line, it naturally echoes them so you can see them. The Escape
character probably types out as ^[, which means
Control-[, which is another name for Escape. This trick
is the easiest way to find out the exact sequences generated by
essentially any key on your keyboard.
Knowing that F1 sends
Escape-[-[-A, we just need to
put that into ~/.inputrc. Putting an Escape character
into a file isn't pretty with any editor. Readline helps you out by
accepting \e in the configuration file to represent
Escape. So replace that z assignment above with the
following in ~/.inputrc:
Now if you're up for something more sophisticated than logging out
and in again, just hit Control-X Control-R. That should
reload the Readline configuration file. Now press F1 and you'll get
ps -a --forest.
But having to hit Enter after F1 ruins everything.
It's like having to get up to reach the TV remote.
The stuff after the colon (:) is called a macro (If it were
not in quotes, it would be a function, like
end-of-line). Readline executes each character in the string
as if you had typed it. While up until now we've just used characters
that are defined to insert themselves into the line buffer (p,
s, etc.), we can also use characters that do more exotic
things. One such character is the Carriage Return (you
remember typewriters, don't you?), which is what your terminal sends
when you hit Enter.
Carriage Return is also known as Control-M, so you can
use Readline's special notation "\C-M" to represent it. So put the
following in your ~/.inputrc, reload, and you'll see that you
have a one-touch ps command.
For Alt and Control shifted keys, use the syntax C-x and
M-x in ~/.inputrc (M is for Meta, a
forerunner of the Alt key).
See the Readline User's Guide, available wherever fine Info documents
are hyperlinked on your system, for all the details. The man page for
the Readline subroutine also works.
Now I should point out a few cases where things won't work as you
expect because your keystrokes are interpreted at a level below
Readline.
First of all, the tty device driver (that's a driver a level above
the actual keyboard device driver) recognizes a few special
characters, as controlled by the stty program. Readline
turns off most of this tty interference by placing the console in raw
tty mode, but Control-S, Control-Q, Control-C,
and Control-Z are likely never to make it to Readline, being
hijacked by the tty driver and acted on accordingly.
Then there's the keyboard driver. It lets you customize every key,
and I don't mean at the same level as Readline. You can make the left
shift key generate a q character if you're feeling a little
psychotic. More important, the keyboard driver assigns certain
console functions to certain keystrokes, which means those keystrokes
will not generate anything that gets sent up to the tty driver, and
then to Readline. For example, the driver normally associates
Alt-F1 with "switch to Virtual Console 1." So don't even try
to program Readline to insert the name of your Napster pirated music
directory when you press Alt-F1.
Under X (in, say, an xterm window), the Linux keyboard
device driver is mostly bypassed, with the X server substituting its
own driver. So the keys won't necessarily generate the same character
stream, to be seen by Readline, as you would see from a regular Linux
virtual console.
If you're interested in the wide world of keyboard mapping, start
with the
Keyboard-And-Console HOWTO and also read the Readline User's Guide
and of course documentation for X.
Making a hotkey
Things That Don't Work
More information
Copyright © 2000, Bryan Henderson
Published in Issue 55 of Linux Gazette, July 2000