LINUX GAZETTE

[ Prev ][ Table of Contents ][ Front Page ][ Talkback ][ FAQ ][ Next ]

"Linux Gazette...making Linux just a little more fun!"


How To Make A Hotkey On The Linux Console

--or--

Why Bill Gates can have my keyboard when he pries it from my cold, dead hands

By Bryan Henderson


Introduction

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.

Background - How keystrokes become a command

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 E in the line you are building. When it sees Control-A, it backs the cursor up to the beginning of the line. When it sees Tab, it reads your mind (at least I think it does).

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.

Making a hotkey

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):

"z":"ps -a --forest" The simplest way to make this binding take effect is to log out and log in again.

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 z at the beginning of the line. Type echo z and you have typed echo ps -a --forest.

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:

"\e[[A":"ps -a --forest"

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.

"\e[[A":"ps -a --forest\C-M" That's all there is is to it. Assign whatever command you want to whatever key you want. Use the quoted-insert technique to find out what sequences associate with your F keys and numeric keypad. Beware that numeric keypads have modes — a bunch of them. The keys send different sequences when the pad is in different modes.

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.

Things That Don't Work

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.

More information

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.


Copyright © 2000, Bryan Henderson
Published in Issue 55 of Linux Gazette, July 2000

[ Prev ][ Table of Contents ][ Front Page ][ Talkback ][ FAQ ][ Next ]