Keyboards, Consoles, and VT Cruising
“It's a GUI, GUI, GUI, GUI world!”—or so the major OS manufacturers would have you believe. The truth is that while this is increasingly the case, there are times when the command line interface (CLI) is still a very good choice for getting things done. It's fast, generally efficient, and is a good choice on memory or CPU constrained machines. And don't forget, there are still a lot of very nifty things that can be done at the console.
In this spirit, I'd like to start by following up on a delightful and informative article written by Alessandro Rubini entitled “The Best Without X” in the November 1995 issue (#19) of Linux Journal. Among a wealth of helpful ideas, Alessandro suggested converting the numeric keypad into a console-switch scratch pad to allow single key switching from one virtual terminal (VT) to another. We'll begin by looking at how this conversion can be done. We'll also look at:
Getting from Here to There: handy methods for VT cruising
The Useful Unused VT: where to put all that logging information, and where X-Windows really ends up
By the time that you get through tinkering around with these things I think you'll agree that the CLI isn't such a bad place after all. Also, the good news is that the programs you'll need to do this conversion are standard inclusions in most recent Linux distributions and include:
kbd 0.91 (keyboard font and utility programs)
utils 2.5 (Rick Faith's huge collection of utilities)
GNU shell-utils 1.12 (shell utilities including the stty program)
A listing of Linux FTP archives where these utilities can be found is included in the sidebar.
The numeric keypad is an ideal candidate for re-mapping into a virtual terminal-switching scratch pad since most of us have never learned “ten-key by touch”. In addition, the non-numeric functions on a 101-key keyboard are already duplicated by the home, end, page up, page down, insert, delete and arrow keys. Since there may be occasions in which we still want to use the keypad for numeric input, let's see how to set it up as a VT switcher while retaining numeric input ability. You'll need to have the kbd package installed on your system. The two programs we'll be using are showkey and loadkey. To check whether they are installed on your system type:
$ type loadkeys showkey
if you're using the BASH shell, or:
$ which loadkeys showkey
The which program or the BASH shell built-in function type will both print the path to the executable if they exist in the PATH search path. On my machine this produces:
$ type showkey loadkeys showkey is /usr/bin/showkey loadkeys is /usr/bin/loadkeys
$ which showkey loadkeys /usr/bin/showkey /usr/bin/loadkeys
If you don't have these programs installed, you'll need to get the the kbd package source, and install it yourself. This package is available only as source code, but installation is as simple as un-archiving it into a temporary directory, then typing:
$make && make install
Converting the keypad into a VT switcher involves defining a keyboard mapping and using loadkeys to actually load this information into the kernel keyboard translation tables. It's easier than it sounds—although you must keep in mind that indiscriminate tinkering can render your keyboard useless (requiring one of those dreaded cold reboots), and that changing the keyboard translation tables affects ALL VTs, not just the one you're working on. The kbd package's default installation location is under /usr/lib/kbd, with the key mapping files in the keytables subdirectory. Change to this directory and make a copy of the defkeymap.map file, which contains the default keyboard mapping and is a useful place to begin. You can name the new file anything you'd like—e.g.,
cp defkeymap.map custom.map
Use your favorite editor and load up the copied file. At this point it's probably helpful to have a look around at the current contents. The experience is rather like visiting one of those fine old curio shops—look, but don't touch! The first few lines may look something like this:
keycode 1 = Escape Escape alt keycode 1 = Meta_Escape keycode 2 = one exclam alt keycode 2 = Meta_one shift alt keycode 2 = Meta_exclam keycode 3 = two at at control keycode 3 = nul shift control keycode 3 = nul alt keycode 3 = Meta_two shift alt keycode 3 = Meta_at
I won't go into all the gory details of how to re-map the keyboard except to say that the basic format to use is:
keycode keynumber = keysym modifier keycode keynumber = keysym
in which keynumber is the internal identification number of the key and keysym represents the action to take. Now, before you bail out on me, let's put this into simple terms. Each key on the keyboard is identified by a unique number which is represented by keynumber. When a key is pressed or released, the press or release event is passed to the operating system, which responds by performing the appropriate action—represented here by keysym. The modifier is a key which is held down at the same time that the key is pressed. These modifier keys include the well-known control, alt and shift keys. The ability to define multi-key combinations extends the mapping available for each key.
So, using the example above, pressing the key associated with keynumber 3 actually causes the number 2 to be printed to the screen. If the shift key is held down at the same time as the key is pressed, the @ sign is printed to the screen, and if the three key combination shift-alt-3 is pressed, the output is the Meta_at (whatever that looks like).
Getting back to the task at hand, we want to change to a specified VT when we press one of the keypad keys: i.e., pressing keypad 1 should switch to VT number 1, pressing keypad 2 should switch to VT number 2, etc. In your customized key map file find the section that defines the keypad keys—it should look similar to this:
keycode 71 = KP_7 alt keycode 71 = Ascii_7 keycode 72 = KP_8 alt keycode 72 = Ascii_8 keycode 73 = KP_9 alt keycode 73 = Ascii_9 [...]
Now, edit this section so that it reads something like Listing 1.
Before continuing, let's make a couple of observations. First, it's not a bad idea to comment the file as you go. What seems clear and obvious now fades into obscurity as the weeks pass. Adding comments now will prevent your having to pore over manual pages, program documentation and magazine articles later, looking for the correct syntax or usage. Second, notice that with each entry there are sub-stanzas, beginning with the words alt keycode, shift keycode, etc. These stanzas define multi-key combinations in which a modifier key is pressed at the same time as the key being defined. A common example of this is the crtl-c combination used to terminate a program during execution.
Finally, you may be asking yourself how you're supposed to know which keynumber is associated with a key. Does anyone know off-hand what keynumber goes with the ; key? You can find this out by using the showkey program. After you invoke the program, showkey will print the keynumber for any key you press and will quit after 10 seconds of no input. So, now that we've edited the pertinent section in the custom.map file, let's see how we'd arrive at this from scratch. The basic steps would be:
Find the keynumber for the keypad keys.
Edit the customized mapping for the keys so that pressing them would change to the appropriate VT.
Edit the customized mapping for the keys so that the keypad could still be used for numeric input (using a modifier key combination in this case).
Load the customized mapping and see whether it works.
Optionally, have the default key mapping loaded at system boot.
To do this, let's begin by invoking the showkey program:
Now, any key you press causes showkey to print the keynumber. On my machine, invoking showkey and pressing keypad keys 1 through 9 results in the output shown in Listing 2. You can see that both key press and key release events are detected. Also note that the numbering of the keypad keys is not sequential. The numeric keys have the format shown in Table 1:
Actual Key: Keynumber: 7 8 9 71 72 73 4 5 6 75 76 77 1 2 3 79 80 81
Table 1 shows that keypad number 1 has keynumber 79, keypad number 2 has keynumber 80, etc, Knowing this, we can set up the appropriate key map entry for each of these keys. The keysym event that we're interested in is Console_x, in which x is the number of the VT to which the view is switched. A simple entry to map keypad number 1 to switching to VT 1 would look like:
keycode 79 = Console_1
If you look at Listing 1, you'll notice that this is what we've done. Suppose, however, we wanted to switch to a VT greater than 9—how are we to do that? The solution is to use a modifier key combination. Looking again at the example above, using the shift key with the keypad allows us to use Console_10 through Console_19. We also wanted to be able to use the numeric keypad as just that—a means of entering numeric data. In the example above, notice that the modifier alt was used to do this:
keycode 71 = Console_7 shift keycode 71 = Console_17 alt keycode 71 = KP_7 alt control keycode 71 = Console_7
In this stanza for the keypad_7 key, the first entry maps the keypad_7 key to switch to VT 7. The second line maps shift-keypad_7 to switch to VT 17 and the third line maps the alt-keypad_7 combination to KP_7 which is the keysym for numeric output when num lock is on. Thus, to use the keypad as a numeric keypad, press the num lock key so that it toggles to on, then hold down the alt key while you enter numbers at the keypad. Note, too, that alt-crtl-keypad was defined to switch to the same console as simply pressing the keypad key itself. In this case, it acts in exactly the same fashion as the alt-fn (alt-Function_key) or alt-crtl-fn (alt-crtl-Function key) combination. You may have noticed that using the function keys is how one is typically instructed to switch from one VT to another. Looking at the stanzas for the function keys you'll notice entries such as the following:
keycode 59 = F1 F13 Console_13 control keycode 59 = F25 shift control keycode 59 = F37 alt keycode 59 = Console_1 control alt keycode 59 = Console_1
Note that both alt-f1 and alt-crtl-f1 are used to switch to VT 1. Those of you using X will probably already have found that switching to a VT from X requires the three key alt-crtl-fn key combination while the two key alt-fn key combination is used at the console. Although you can change this default behavior, it's best not to. At this point, we've defined mappings for the keypad keys such that each key acts as a switch to the VT of the same number. Using shift-keypad_key switches to VT (10 + keypad number) and using alt-keypad key with the num lock on outputs the numeric value of the key. The final step is to actually load the new mapping and give it a try. The loading is done using loadkeys and can be done without logging on as root. To load the customized keymap, enter:
$ loadkeys /usr/lib/kbd/keytables/custom.map
This will print a message indicating that the custom.map file is being loaded. After this, you're all set! Give it a try. To revert back to the default mapping simply enter:
$ loadkeys /usr/lib/kbd/keytables/defkeymap.map
and the default mappings will be loaded once again. You can use this edit -> load customized map -> test -> load default map cycle to obtain the desired mapping. Once you've created a custom map file and wish to have it loaded at boot, you can add an entry to one of the rc.* files, such as rc.local, to have loadkeys automatically load your customized mapping:
if [ -r /usr/lib/kbd/keytables/custom.map ]; then loadkeys /usr/lib/kbd/keytables/custom.map fi
This entry ensures that the file is present and readable and invokes loadkeys to load the file. Again, keep in mind that loading a key mapping changes the keytable information for all VTs, not just your current one.
- New Products
- Android Candy: Google Keep
- A Little GUI for Your CLI
- Readers' Choice Awards 2014
- Handling the workloads of the Future
- How Can We Get Business to Care about Freedom, Openness and Interoperability?
- diff -u: What's New in Kernel Development
- Days Between Dates?
- December 2014 Issue of Linux Journal: Readers' Choice
Editorial Advisory Panel
Thank you to our 2014 Editorial Advisors!
- Jeff Parent
- Brad Baillio
- Nick Baronian
- Steve Case
- Chadalavada Kalyana
- Caleb Cullen
- Keir Davis
- Michael Eager
- Nick Faltys
- Dennis Frey
- Philip Jacob
- Jay Kruizenga
- Steve Marquez
- Dave McAllister
- Craig Oda
- Mike Roberts
- Chris Stark
- Patrick Swartz
- David Lynch
- Alicia Gibb
- Thomas Quinlan
- Carson McDonald
- Kristen Shoemaker
- Charnell Luchich
- James Walker
- Victor Gregorio
- Hari Boukis
- Brian Conner
- David Lane