old-www/LDP/LG/issue55/henderson.html

269 lines
13 KiB
HTML

<!--startcut ==============================================-->
<!-- *** BEGIN HTML header *** -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML><HEAD>
<title>How To Make A Hotkey On The Linux Console LG #55</title>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#0000AF"
ALINK="#FF0000">
<!-- *** END HTML header *** -->
<CENTER>
<A HREF="http://www.linuxgazette.com/">
<H1><IMG ALT="LINUX GAZETTE" SRC="../gx/lglogo.jpg"
WIDTH="600" HEIGHT="124" border="0"></H1></A>
<!-- *** BEGIN navbar *** -->
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="florido.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue55/henderson.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../faq/index.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="okopnik.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
<!-- *** END navbar *** -->
<P>
</CENTER>
<!--endcut ============================================================-->
<H4 ALIGN="center">
"Linux Gazette...<I>making Linux just a little more fun!</I>"
</H4>
<P> <HR> <P>
<!--===================================================================-->
<center>
<H1><font color="maroon">How To Make A Hotkey On The Linux Console</font></H1>
--or--
<H2>Why Bill Gates can have my keyboard when he pries it from my cold, dead hands</H2>
<H4>By <a href="mailto:bryanh@giraffe-data.com">Bryan Henderson</a></H4>
</center>
<P> <HR> <P>
<!-- END header -->
<h3>Introduction</h3>
<p>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.
<p>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 <i>F2</i> key to
bring up the mail in one touch. <i>F1</i> 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.
<p>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.
<p>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.
<h3>Background - How keystrokes become a command</h3>
<p>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.
<p>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.
<p>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.
<p>Readline gets a stream of characters from the terminal (and it can
be any old terminal &#8212; not just a Linux virtual console) and
recognizes certain sequences and executes certain functions when it
sees them. For example, when it sees <kbd>E</kbd>, it inserts
<kdb>E</kbd> in the line you are building. When it sees
<i>Control-A</i>, it backs the cursor up to the beginning of the line.
When it sees <i>Tab</i>, it reads your mind (at least I think it does).
<p>You get to choose what Readline does when it sees some character
sequence via a Readline configuration file, which is normally called
<tt>.inputrc</tt> in your home directory.
<h3>Making a hotkey</h3>
<p>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 <kbd>ps -a --forest</kbd> to the
character <kbd>z</kbd>. Once we do this, we will not be able to type
the letter <kbd>z</kbd> in any command, so it is truly ridiculous.
<p>To do this, we add the following to our <tt>~/.inputrc</tt> (if it
doesn't already exist, just make this the only line in a new file):
<xmp>
"z":"ps -a --forest"
</xmp>
The simplest way to make this binding take effect is to log out and
log in again.
<p>After doing this, you should find that when you hit the
<kbd>z</kbd> key, the characters <kbd>ps -a --forest</kbd> appear in
your command line buffer. Hit <i>Enter</i> and the <tt>ps</tt>
command executes. You will find that you don't have to type
<kdb>z</kbd> at the beginning of the line. Type <kbd>echo z</kbd> and
you have typed <kbd>echo ps -a --forest</kbd>.
<p>But let's be more reasonable and put this <tt>ps</tt> command on
the <i>F1</i> key. That's more complicated because pressing the
<i>F1</i> 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, <i>F1</i> sends the four characters <i>Escape</i>,
<kbd>[</kbd>, <kbd>[</kbd>, and <kbd>A</kbd>.
<p>But don't take my word for it. You can prove it by using
Readline's <tt>quoted-insert</tt> function, which you should find
bound to <i>Control-V</i>. <tt>quoted-insert</tt> 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 <i>Escape</i> character. So at a Bash
prompt, type <i>Control-V</i> followed by <i>F1</i>. As Readline
places the <i>Escape</i> 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 <tt>^[</tt>, which means
<i>Control-[</i>, which is another name for <i>Escape</i>. This trick
is the easiest way to find out the exact sequences generated by
essentially any key on your keyboard.
<p>Knowing that <i>F1</i> sends
<i>Escape</i>-<kbd>[</kbd>-<kbd>[</kbd>-<kbd>A</kbd>, we just need to
put that into <tt>~/.inputrc</tt>. Putting an <i>Escape</i> character
into a file isn't pretty with any editor. Readline helps you out by
accepting <kbd>\e</kbd> in the configuration file to represent
<i>Escape</i>. So replace that <kbd>z</kbd> assignment above with the
following in <tt>~/.inputrc</tt>:
<xmp>
"\e[[A":"ps -a --forest"
</xmp>
<p>Now if you're up for something more sophisticated than logging out
and in again, just hit <i>Control-X</i> <i>Control-R</i>. That should
reload the Readline configuration file. Now press <i>F1</i> and you'll get
<kbd>ps -a --forest</kbd>.
<p>But having to hit <i>Enter</i> after <i>F1</i> ruins everything.
It's like having to get up to reach the TV remote.
<p>The stuff after the colon (:) is called a <i>macro</i> (If it were
not in quotes, it would be a <i>function</i>, like
<tt>end-of-line</tt>). 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 (<i>p</i>,
<i>s</i>, etc.), we can also use characters that do more exotic
things. One such character is the <i>Carriage Return</i> (you
remember typewriters, don't you?), which is what your terminal sends
when you hit Enter.
<i>Carriage Return</i> is also known as <i>Control-M</i>, so you can
use Readline's special notation "\C-M" to represent it. So put the
following in your <tt>~/.inputrc</tt>, reload, and you'll see that you
have a one-touch <tt>ps</tt> command.
<xmp>
"\e[[A":"ps -a --forest\C-M"
</xmp>
That's all there is is to it. Assign whatever command you want to
whatever key you want. Use the <tt>quoted-insert</tt> technique to
find out what sequences associate with your F keys and numeric keypad.
Beware that numeric keypads have modes &#8212; a bunch of them. The
keys send different sequences when the pad is in different modes.
<p>For Alt and Control shifted keys, use the syntax <kbd>C-x</kbd> and
<kbd>M-x</kbd> in <tt>~/.inputrc</tt> (<kbd>M</kbd> is for Meta, a
forerunner of the Alt key).
<p>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.
<h3>Things That Don't Work</h3>
<p>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.
<p>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 <tt>stty</tt> program. Readline
turns off most of this tty interference by placing the console in raw
tty mode, but <i>Control-S</i>, <i>Control-Q</i>, <i>Control-C</i>,
and <i>Control-Z</i> are likely never to make it to Readline, being
hijacked by the tty driver and acted on accordingly.
<p>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 <kbd>q</kbd> 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
<i>Alt-F1</i> 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 <i>Alt-F1</i>.
<p>Under X (in, say, an <tt>xterm</tt> 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.
<h3>More information</h3>
<p>If you're interested in the wide world of keyboard mapping, start
with the <a
href=http://www.linuxdoc.org/HOWTO/Keyboard-and-Console-HOWTO.html>
Keyboard-And-Console HOWTO</a> and also read the Readline User's Guide
and of course documentation for X.
<!-- *** BEGIN copyright *** -->
<P> <hr> <!-- P -->
<H5 ALIGN=center>
Copyright &copy; 2000, Bryan Henderson<BR>
Published in Issue 55 of <i>Linux Gazette</i>, July 2000</H5>
<!-- *** END copyright *** -->
<!--startcut ==========================================================-->
<HR><P>
<CENTER>
<!-- *** BEGIN navbar *** -->
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="florido.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue55/henderson.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../faq/index.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="okopnik.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
<!-- *** END navbar *** -->
</CENTER>
</BODY></HTML>
<!--endcut ============================================================-->