|
http://www.ibbnet.org/~anne/keyboard.html
version 0.6
Index |
||||||||||
---|---|---|---|---|---|---|---|---|---|---|
Configuration of environments...
|
||||||||||
... and applications
|
||||||||||
Athena-apps | Emacs | Joe | KDE | Less | Nedit | Netscape | Pico and Pine | Vim | Mutt | Telnet |
The keymapping problem can be traced back to the time when computers used punched tapes. The only way to correct a wrongly punched character was to punch additional bits in the tape. Characters with all the bits punched were treated as deleted characters. See 'man ascii' for a list of the ASCII characterset, you'll see that DEL, (octal 177, decimal 127 and hexadecimal 7F) is the one with all the bits punched in (the ASCII code with the highest value). To be able to overwrite a character it is necessary to undo the feed between the characters first. For this the ASCII BS (octal 010, decimal 8, hexadecimal 08) was used. So to erase the last-typed character, you would have to press first BS and then DEL. In newer computers either BS or DEL was chosen to do it in one press.
The question to use BS or DEL was (and is...) just a matter of choice, just as different operating systems chose different ways to represent newlines, which was done by first issuing a carriage return (CR) and then a line-feed (LF). UNIX chose ASCII LF (hexadecimal 0A) to do both at the same time, Macintosh chose CR and MS-DOS both. Unfortunately, in the BS-DEL case, Linux ended up with two possibilities.
The essential point in this issue is to go for one way consistently. This page describes a way to consistently use DEL to erase the previous character, the page called The Alternative Way describes a way to consistently use BS. On the latter page there are some tips which may be useful regardless of what approach you take.
At this point the best way to fix the keys on your machine is to install Debian from version 2 (Hamm) and up, or SuSE.
If you miss an application on this page, it's either because the keys are ok in the application ("If it ain't broken, don't fix it"), or because I don't know about it. In either case, don't hesitate to mail me about it.
Throughout this document, [<---] and [Delete] are used to denote the physical keys on the keyboard, the things you actually press to erase characters. There are a few things to keep in mind: ASCII values can be represented in several equivalent ways. This means that ASCII BS is equivalent to 010 in octal, 8 in decimal and 08 in hexadecimal notation. To show that a number is in hexadecimal notation '0x' is put in front of it. Finally it should be noted that BS and DEL are known to applications by their corresponding control sequences. To sum it up:Note: |
---|
ASCII BS == 0x08 == ^H |
ASCII DEL == 0x7f == 0177 == ^? |
.inputrc/.cshrc
already helps a lot) and a
more difficult issue which I will try to describe below.
The linux console emulates a vt220 terminal which has the following key-mapping:
Linux console/VT220 Key KeySymName Console characters -------------------------------------------------- Ctrl+H ---> Control_H ---> ASCII BS (0x08) [<---] ---> Backspace ---> ASCII DEL (0x7f) [Delete] ---> Delete ---> "\e[3~"Note 1: BS (0x08) is equivalent to ^H, which is left to be used by applications (e.g. for help menus in emacs, but it could be anything). DEL is equivalent to ^?, or 0177 (octal) and 0x7f (hex) and "\e[3~" will show up in your xterm (using the ^v-trick) as ^[[3~. Xterms on the other hand, emulate the vt100 terminal, which didn't have a [Delete]. It did have a [<---] which generated ASCII BS (but it was in an awkward position and did not serve as rubout).
VT100 -- Key KeySymName Console characters -------------------------------------------------- Ctrl+H ---> Control_H ---> ASCII BS (0x08) [<---] ---> Backspace ---> ASCII DEL (0x7F)Now here's how xterm emulates the VT100 terminal:
Xterm's emulation of VT100 Key KeySymName Console characters -------------------------------------------------- Ctrl+H ---> Control_H ---> ASCII BS (0x08) [<---] ---> Backspace ---> ASCII BS (0x08) [Delete] ---> Delete ---> ASCII DEL (0x7F)It may be clear that by default the keys are mapped differently on the console and in xterm. This would be ok if it weren't for the fact that while on the console ^H is free to be used by applications, in an xterm it is not (instead it's mapped to the [<---] key). Differences between terminal types are generally dealt with by the terminfo database (see below), mapping terminal specific strings to the correct key. However, in this case, the ^H should not be mapped. Terminfo is not enough, the settings of the terminal (xterm) have to be modified such that ^H is not used.
In my previous attempt at working around the problem, I put most of my effort in trying to map all keys to suit xterm's vt100 emulation. However, I now propose another way to deal with the problem. This basically means getting xterm to work with the consoles' default settings: [<---] will do ASCII DEL (0x7F, or ^?), and [Delete] will do "\e[3~". This way ^H is not used for any terminal specific functions, it can be used by applications.
There is no clear solution, but there are some pretty good work-arounds. What is needed is to tell xterm how to handle the keys, and then to tell other applications about it (i.e. how xterm handles the keys). The terminfo database contains descriptions of how all kinds of terminals handle (terminal specific) keys. Applications look at the TERM variable, and then search the corresponding database for the value of a certain key, e.g. the left-arrow key, and find the string that corresponds to it. This means that the strings in the database had better correspond to your current xterm settings. This involves modifying xterm's terminfo entry.When you change the keymapping on your own system, you may have problems when accessing other systems. Luckily, this can be worked-around by a script which changes the input it receives to the output that is expected by the application (telnet, rlogin). See the telnet section.
This table summarizes the modifications needed in the different environments, and the tools it is done with:
Environment
|
Configuration
files
|
Configuration
|
|
user
|
systemwide
|
||
Terminfo | - |
terminfo |
infocmp/tic |
Xterm | ~/.Xdefaults (*) |
/etc/X11/Xresources |
xrdb ~/.Xdefaults (*) |
X | - |
/etc/X11/xinit/.Xmodmap (**) |
xmodmap .Xmodmap |
Bash | ~/.inputrc |
/etc/inputrc |
export INPUTRC=/etc/inputrc |
Tcsh | ~/.cshrc |
/etc/cshrc |
bindkey
(shellcommand) |
.Xresources
/etc/X11/XF86Config
also affects the keyboard
settings under X
infocmp | grep kbs
should return a line which includes kbs=\177
. This
means DEL (or ^?) is mapped to the backspace key, which is what we
want.
infocmp | grep kdch1
should return a line with kdch1=\E[3~
. This means that
\E[3~ is mapped to the delete key. Often you will find kbs=^H
and/or kdch1=\177, or there will be no kdch1 at all. You can either
edit the terminfo entry as described on the Troubleshooting-page (simply
setting or adding kdch1=\E[3~
and
kbs=\177
, but make a backup first!) or you could download
(click shift or right) a modified debian
xterminfo or redhat xterminfo and
test it. Put the file in ~/.terminfo/x/xterm
(for
testing purposes) and do for bash:
export TERMINFO=~/.terminfo
and/or for tcsh:
setenv TERMINFO ~/.terminfo
Make sure that the TERM variable is set to xterm:
echo $TERM
should return "xterm". If it works as intended (do 'toe' to check
whether the terminfo dir you specified is indeed used, toe will
return a list of available terminfo types, only xterm in this
case), you can run tic as root, which will copy the file to
/etc/terminfo/x/xterm
(debian) or
/usr/lib/terminfo/x/xterm
(redhat, slackware). Make backups first, and
test it before you replace any files!
/etc/X11/Xresources
or ~/.Xdefaults
(or
wherever it's merged with the other xresources) add the line:
*VT100.Translations: #override \
<Key>BackSpace: string(0x7F)\n\
<Key>Delete: string("\033[3~")\n\
<Key>Home: string("\033[1~")\n\
<Key>End: string("\033[4~")
*ttyModes: erase ^?
Rxvt only uses Xresources
if it is compiled with
this option. Since rxvt uses readline, to get home and end to work
you will have to edit .inputrc
, see the Bash section). Redhat users can pick up the SRPM
(source) and compile rxvt themselves with this
feature.h, ensuring the right keybindings.
Putting xterm
or nxterm
in front of
*vt100.translations
makes the settings specific for
xterm or nxterm. Sometimes this does not seem to work properly, in
that case try using both nxterm*VT100.Translations
and
xterm*VT100.Translations
.
1. The syntax of the Xresources
files is very
strict, make sure you don't leave blank spaces after the backslash
on each line. Also watch the newline (\n\
) sequences,
there shouldn't be one at the last line of an entry.
2. The sections are named, if you only use
*VT100.Translations
it will work for all xterm and
friends.
3. For info about Xresources
and other X related stuff
refer to 'man X'
.
/etc/X11/XF86Config
. It is enable by default, so it should
be okay. Note the different keyboard layout-options. Now XFree86
will translate the console mapping, and everything should work in
X. If you have problems, or want to fiddle with additional
characters and things, create an Xmodmap
. Also if you
want the keyboard to generate special characters in X,
xmodmap
can also be used to configure the function-keys.
This is adequately described in the manual page ('man
xmodmap'
. Make sure that the following lines are included in
your Xmodmap
:
keycode 22 = BackSpace
keycode 107 = Delete
Note that the keycodes in X are not the same
as in a VT. Use showkey
to see the keycodes generated
by the keyboard in a VT, and xev
in X. There is an
excellent graphical front end for X-keyboard configuration:
xkeycaps
. Refer to the
Netscape section.
Another way of generating special characters in X (without
using xmodmap
) is by defining a Compose-key (for use
as a "dead key") in XF86Config
in the Keyboard
section:
RightCtl Compose
Now you have a compose-key with the same properties as the one
described in the VT section. Remember
to set the environment variable LC_CTYPE=iso-8859-1
(see VT optional...). Consult
'man XF86Config'
if
you want to know more. Note: this doesn't seem
work rxvt.XKEYBOARD
extension (enabled per default) in
XF86Config
and uncomment the line (follow the instructions
in the file):
XkbModel "microsoft"
Now you can use the button with the windows flag on it to produce a
great number of exotic characters, just press it in combination
with e.g. a, producing á (a clear disadvantage is that there
is no logic in the location of the special characters at all...).
Yet another way to use "dead keys" in X is by installing a
modified version of libX11 which includes support for dead keys
(transparent for all apps). First, get the modified version of
libX11 (make sure you get the right version, if you use glibc
replace both libX11, ELF-libc5 and ELF-libc6). Now, deactivate the
XKB extension of XFree86 (edit XF86Config
and run
xmodmap on a Xmodmap file with dead keys like dead_acute,
dead_grave, dead_cedilla, dead_ogonek and a Multi_keys one too.
A special case is if you use xdm, you need to deactivate XKB
from the /etc/X11/xdm/Xservers
file, passing a -kb
parameter to the server like this:
:0 local /usr/X11R6/bin/X -kb
then in /etc/X11/xdm/Xsetup_0
file add a line to load
the Xmodmap, like this:
if [ -r /etc/X11/xinit/.Xmodmap ]; then
/usr/X11R6/bin/xmodmap /etc/X11/xinit/.Xmodmap
fi
Now chars accesible by AltGr, dead keys or compose are usable in
xdm too.
¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ® ¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ Ç
È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î
ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
Now you need a way to display them (millions of options here, I bet
you can do all kinds of crazy things with fonts, colors, pixmaps,
borders...). The script assumes the file with the characters is in
/usr/local/lib
.
#!/bin/bash
export LESSCHARSET=latin1
exec xterm -T Iso_8859_1-TABLE -geometry 77x4 +sb -bg SteelBlue -fg white \
-fn lucidasanstypewriter-bold-12 -e less /usr/local/lib/iso_8859_1
Refer to the manual page of iso_8859_1. If you do 'man iso_8859_1'
but you don't see any special characters, edit
/etc/man.config
, and change the following line:
NROFF /usr/bin/groff -Tascii -mandoc
to:
NROFF /usr/bin/groff -Tlatin1 -mandoc
Now try 'man -c iso_8859_1' (the -c option is to make sure man does
not use an old cat file).
Create a file, /etc/inputrc
for system wide use or
~/.inputrc
for personal use. Actually, this is the
readline initialization file, readline is a library that some
programs (bash, kvt) use to read input (try bind -v
to
see a list of readline key and function bindings). Cut and paste
the following in the file to make the Delete key delete characters
under the cursor, and make Home and End work as well:
"\e[3~": delete-char
# this is actually equivalent to "\C-?": delete-char
# VT
"\e[1~": beginning-of-line
"\e[4~": end-of-line
# kvt
"\e[H":beginning-of-line
"\e[F":end-of-line
# rxvt and konsole (i.e. the KDE-app...)
"\e[7~":beginning-of-line
"\e[8~":end-of-line
If a system-wide /etc/inputrc
was created, add the
following line to /etc/profile
:
export INPUTRC=/etc/inputrc
Make sure that the stty erase character is set to
^?
. Type
stty -a | grep erase
and check if it says
erase = ^?;
If it is set to something else (e.g. ^H
) then put
the following line in both .bashrc
and in either
.bash_profile
or /etc/profile
:
if tty --quiet ; then
stty erase '^?'
fi
and for xterm and rxvt add this to .Xdefaults
:
*ttyModes: erase ^?
If you create /etc/inputrc
, note that Bash will
ignore ~/.inputrc
(currently this happens in all
distributions except Debian, however, this might change in the
future). As an alternative, you can edit ~/.inputrc
,
and copy this to /etc/skel/
, so it's in the home
directories of all new users.
Push the key-combination 'Ctrl-x-r
' (push the
control-key, the x-key. release it, push the r-key, release it, and
then release the control-key) to see if the changes in
inputrc
take effect. Or just login again, and it will work.
You can also change the keybindings on the fly with the
bind
command, e.g:
[localhost]> bind "\C-?": backward-delete-charThis is useful to test different keybindings, if they work you can put them in
~/.inputrc
. Read all about it in the
readline manpage.
People using keymaps with e.g. Scandinavian characters who
would like bash to display these characters (øl;-) have to
add the following lines in .inputrc
:
set convert-meta off
set output-meta on
set input-meta on
For more info, check the
Danish-HOWTO
.
/etc/cshrc
or your personal ~/.cshrc file:
#.cshrc
if ($term == "xterm" || $term == "vt100" \
|| $term == "vt102" || $term !~ "con*") then
# bind keypad keys for console, vt100, vt102, xterm
bindkey "\e[1~" beginning-of-line # Home
bindkey "\e[7~" beginning-of-line # Home rxvt
bindkey "\e[2~" overwrite-mode # Ins
bindkey "\e[3~" delete-char # Delete
bindkey "\e[4~" end-of-line # End
bindkey "\e[8~" end-of-line # End rxvt
endif
To see whether it works or not, type:
[localhost]> source .cshrc
.Xdefaults
to get Delete to work:
*Text.translations: #override \
~Shift ~Meta <Key>Delete: delete-next-character()
In emacs, [<---] and [Delete] are by default configured to both
erase the character on the left of the cursor. To change this, you
can either edit the file x-win.el
in the emacs root
directory, and find the following:
;; Map certain keypad keys into ASCII characters
;; that people usually expect.
(define-key function-key-map [backspace] [127])
(define-key function-key-map [delete] [127])
and change the last line to
(define-key function-key-map [delete] [deletechar])
Alternatively you can add
(define-key function-key-map [delete] [deletechar])
to your ~/.emacs file.
On a related note, by default in emacs the HOME key brings you to the beginning
of the buffer (i.e. top of the document). Likewise the END key brings you to
the end of the buffer. Adding the lines
(define-key global-map [home] `beginning-of-line)
(define-key global-map [end] `end-of-line)
to your ~/.emacs
make these keys move you to the beginning and
end of the current line. Note that the M-< and M-> keybindings remain
untouched and can still be used to go to the beginning and end of the buffer.
First find the file joerc. It is most likely
/usr/lib/joe/joerc
, but sometimes /etc/joerc
,
or maybe even /usr/local/lib/joerc
. Try 'locate
joerc'
if you can't find the file. Make a backup for safety,
or copy it to .joerc in your home directory, and change/add the
following lines in the section "Standard JOE user interface" in
joerc:
bol ^[ [ H # Standard xterm escape seq.
bol ^[ [ 1 ~ # Standard VT escape seq.
bol ^[ [ 7 ~ # rxvt
eol ^[ [ F # Standard xterm escape seq.
eol ^[ [ 4 ~ # Standard VT escape seq.
eol ^[ [ 8 ~ # rxvt
Note that you first have to make sure that Home
and End work in an xterm. Check
out 'man joe'
. BTW, these
modifications apply to jpicorc
, jstarrc
and jmacsrc
as well.
KDE provides a new alternative to
kvt called konsole. To get the home/end keys to work in konsole you
have to put:
"\e[H":beginning-of-line
"\e[F":end-of-line
in .inputrc
. Additionally, make sure that you have
checked the 'BS sends DEL
' checkbox (right mouse
click, or through the 'Options' pulldown menu). In kvt, KDE's home and end can be configured by
editing ~/.inputrc
(tcsh
users too, it
uses readline):
"\e[H":beginning-of-line
"\e[F":end-of-line
Less is ok on some systems. If it is not on yours, try the
following. Create a file, /etc/lesskey
, for
system-wide use. This will be a lesskey
input file.
Put the following lines in the file:
#line-edit
\e[3~ delete
\e[1~ home
\e[4~ end
[localhost]> lesskey -o /etc/less /etc/lesskey
Add the following line to /etc/profile:
export LESS="-MM -k/etc/less"
Now type:
[localhost]> . /etc/profile
By fiddling with these settings you should be able to get less
to accept (all of) the holy keycodes, at least, it works on my
computer. For some exciting reading, check
'man lesskey'
.
~/.Xdefaults
:
nedit.remapDeleteKey: False
Save the file, and the next time you start nedit the Delete
key will do what we want it to: delete under the cursor. Note: you
can also put the line in ~/.nedit
, but every time you
save the default settings, the .nedit
file will be
overwritten, and you'll have to (n)edit it again.
Note the nedit, as e.g. netscape, is a motif application. This means that it uses the XKeysymDB, see thet netscape section.
The keys should be ok, as long as the XKeysymDB is installed in one of the places where netscape looks (where netscape itself is installed, or/usr/X11R6/lib/X11/
). XKeysymDB is
similar to an xmodmap file, but with a very cryptic and poorly
documented syntax. Luckily, it does do the delete/backspace thing
right, so no sweat.
If you use xmodmap, you may want to check out the graphical
front end for X-keyboard configuration: xkeycaps
. Get
the .rpm at RedHat
Powertools, or get the
Debian-package (or plain tarball). It's a nice tool. You can
also look for a default Xmodmap file on your system. At any rate,
make sure that the following is in the file:
keycode 22 = BackSpace
keycode 107 = Delete
alternatively, you can put it in e.g. your .Xclients file, or in
/etc/X11/xdm/Xsetup_0
):
# map the [<---] key to the [BackSpace] keysym.
xmodmap -e "keycode 22 = BackSpace"
# map the [Delete] key to the [Delete] keysym.
xmodmap -e "keycode 107 = Delete"
I found that wile the keys worked in a VT, in xterms only backspace
works. This was caused by the .Xdefaults
modifications. If you use the ~/.inputrc
to get Delete
to work in xterms (and then pico and pine will be able to use
Delete), however, this creates problems with other apps (e.g. joe)
which cannot be easily solved because joe relies on the
.Xdefaults
modifications to get the keys right. Anyway, it
turns out that pine
and pico are simply broken, as the workaround will clearly
demonstrate. Admittedly broken is a relative thing in all this
keyboard-confusion: from the other method's perspective they are
perfectly ok. One thing is for sure, these two apps are exceptions.
Try the following: make an expect script (let's call it picofix):
#!/usr/bin/expect
eval spawn -noecho $argv
interact {
\177 {send "\008"}
"\033\[3~" {send "\004"}
}
Make picofix executable, and start the editor (or pine) with
picofix pico
and it will work (then you can make an alias or a wrapper). Thanks
to Philip Hands for this ingenious (and powerful!) workaround. You
can also use an alternate editor. Edit .pinerc
and
find the following lines:
# Specifies the program invoked by ^_ in the Composer,
# or the "enable-alternate-editor-implicitly" feature.
editor=
You can enter the command for any editor here, e.g.
joe
or vi
.
If you want the editor to be started right away, start
pine
, enter SETUP
and Config
and
select the enable-alternate-editor-implicitly
option.
Now the editor of choice will be started automagically when you
start writing a message.
Pico fans may want to try jpico, which is basically joe with
pico keybindings (and all the extra's joe offers). Others my be
even smarter and switch to vim and
mutt. Note that the first can be
taught to do the Ctrl-j
-trick, the latter can use pine
keybindings.
:help fixdel
in vim and read all about it.
Put the following line in ~/.muttrc
:
bind editor <delete> delete-charThis will make [Delete] do its job in mutt's internal pager. If you have modified terminfo and you are e.g. telnetting to a machine with a default terminfo (for xterm usually), you can use the following script (let's call it kbdfix) to change the keysequences you generate to the ones the program expects:
#!/usr/bin/expect
eval spawn -noecho $argv
interact {
\177 {send "\008"}
"\033\[3~" {send "\177"}
}
If you press [<---], expect will receive \177 (equivalent to
0x7F and ^?, see the VT220 table)
and it will send \008 (equivalent to ^H) along to telnet, which
will result in [<---] at the other end. Make it executable and
use kbdfix telnet brokenhost
. Thanks to Philip Hands
for this clever workaround.
The logical next step is to automate the trick. Create a file,
/etc/broken-backspace-hosts
(or a shorter name...). In
this file, list the hosts which expect ^H and ^? instead of ^? and
^[[3~. Now you can make a wrapper for telnet as shown below. This
particular script assumes that the telnet binary has been renamed
telnet.orig, and that the kbdfix script described in the previous
section is somewhere in your path):
#!/bin/sh
if grep -wq "$@" /etc/broken-backspace-hosts ; then
exec kbdfix telnet.orig "$@"
else
exec telnet.orig "$@"
fi
From now on, when you use telnet, the script will check whether the
host you are telnetting to is considered broken (listed in the
/etc/broken-backspace-hosts file). If it is, the expect script
(kbdfix) will be used, if not, telnet will be started directly. You
can do the same for rlogin, although rlogin can't be moved (i.e.
won't work when it isn't called rlogin).
Danish-HOWTO
Tcsh
documentation
Bash
documentation 'man X'
'man
XF86Config'
'man lesskey'
'man joe'
This document was put together by Anne Baretta (anne@ibbnet.org). Please mail me if you find mistakes, tY-pO's, alternative or plain better solutions. A few people have already pointed out many mistakes (there simply cannot be that many left...), which improved the document a lot. I would like to thank all the people who contributed to the page, and Thomas Telkamp for hosting the site.