Note again that the main issue that confuses people trying to fix their system is that usually they are fixing thing in the wrong place. Since the parts that work often just work by chance, trying to fix the system assuming something is broken will often lead to change correct settings into incorrect settings.
The first step towards a clean solution is to know exactly which terminals are deviant and which not. Usually they all behave like the console, and in this case the modifications to get everything working are minimal. If, however, you have some deviant terminal (e.g., a deviant version of gnome-terminal), you will have to treat it in a special way.
The following C one-liner
void main(void) {int c; while(c = getchar()) printf("%d 0x%02X\n", c, c);} |
DEL
(127), you have a standard emulator, if it emits a BS (8) you have
a deviant one.If you have some deviant terminal emulator, you must distinguish
it from the standard ones. Theoretically, this should not be a problem
because there are different entries in the terminal database for
terminals with different sequences (the entry used depends on the value
of the TERM variable).
Here we take the approach that the gnome entry should be used for all deviant VT100 emulators, and the xterm entry for the standard ones. This is in line with several distributions (except a few cases like RedHat ≤5.0, where the xterm entry is deviant).
However, gnome-terminal uses by
default the same entry as xterm, so if one
is deviant and the other one is not you will need to find a way to tell
them apart. The option termname of
gnome-terminal allows the user to set the
TERM variable to a more sensible name. However, in older
versions of gnome-terminal the option does
not work. Moreover, sometimes it is not easy to modify the way
gnome-terminal is started.
A good idea here is to exploit the fact that
gnome-terminal sets the
COLORTERM variable to
gnome-terminal. Thus, by adding a simple test to the
shell configuration files we can fix the TERM
variable.
Our problem now is that the terminal database could lack a gnome entry for deviant terminals (this happens on a number of termcap and terminfo versions). Recent terminfo databases have an entry gnome, but, in any case, since gnome-terminal behaves essentially like xterm modulo our famous two keys, it is possible to automagically generate a brand new correct entry.
The readline library used by the
bash and by many other programs to read the
input line can be customized so to recognize specific sequences of
characters. The customization can also depend on the
TERM variable, so once we can distinguish terminals we
can do fine tuning of the keyboard.
Moreover, if you want less and other
application that do raw line input to work correctly, you must convince
the shell that under a deviant terminal emulator the erase character is
BS, and not DEL (in the other case
the Backspace key is already emitting
DEL, so we do not have to do anything). This can be
done using the command stty.
![]() | These fixes have some drawbacks. First, they work only for the specified terminals. Second, in theory (but this is unlikely to happen) they could confuse the readline library on other terminals. Both limitations are however mostly harmless. |
First of all, check with infocmp gnome whether you already have a gnome entry in your terminfo database (we will fix termcap later). If the entry does not exist, the following command
bash$ tic <(infocmp xterm |\
sed 's/xterm|/gnome|/' |\
sed 's/kbs=\\177,/kbs=^H,/' |\
sed 's/kdch1=\\E\[3~,/kdch1=\\177,/') |
TERMINFO to
~/.terminfo). Note that if your xterm
entry is already deviant (e.g., you have a Red Hat ≤5.0) the script will copy it unchanged, which is
exactly what we want.Now, add the following snippet to ~/.inputrc[1]:
"\e[3~": delete-char |
DEL character on deviant terminals, for instance
by adding
$if term=gnome DEL: delete-char Meta-DEL: kill-word "\M-\C-?": kill-word $endif |
Note that the conditional assignments make deviant terminal
emulators work given that the TERM variable is
set correctly. To guarantee this, there are a number of
techniques. First of all, since the default value of the
TERM variable for
gnome-terminal is xterm, if
all terminals are not deviant then we do nothing. If, however, a terminal
that by default uses the xterm entry is deviant you
must find a way to set the TERM variable correctly; assume
for instance this is true of
gnome-terminal.
The simplest way to obtain this effect is to start gnome-terminal with the argument --termname=gnome, for instance by suitably setting the command line in the launcher on the GNOME panel. If however you have an old version, and this method does not work, you can add the lines
if [ "$COLORTERM" = "gnome-terminal" ]
then
export TERM=gnome
fi |
TERM variable.![]() | Setting the terminal to gnome could prevent ls from using colours, as many versions of ls do not know that gnome-terminal is colour capable. To avoid this problem, create a configuration file ~/.dircolors with dircolors --print-database >~/.dircolors, and add a line TERM=gnome to the configuration file. |
We will now generate on-the-fly a suitable termcap entry for deviant terminal emulators; this can be done as follows, always in ~/.bashrc:
if [ "$TERM" = "gnome" ]
then
export TERMCAP=$(infocmp -C gnome | grep -v '^#' | \
tr '\n\t' ' ' | sed 's/\\ //g' | sed s/::/:/g)
fi |
Finally, we must explain to the terminal device which character is generated by the erase key. Since usually the erase key is expected to backspace, there is a nice trick taken from the Red Hat /etc/bashrc that works: add this to ~/.bashrc:
KBS=$(tput kbs)
if [ ${#KBS} -eq 1 ]; then stty erase $KBS; fi |
![]() | Certain distributions could have fixes already in place in the system-wide /etc/inputrc configuration file. In this case you can eliminate redundant lines from your ~/.inputrc. |
In the case of the tcsh, the fixes go all in ~/.tcshrc, and follow the same rationale as the ones for the bash:
bindkey "^[[3~" delete-char
if ($?COLORTERM) then
if ($COLORTERM == "gnome-terminal") then
setenv TERM gnome
endif
endif
if ($?TERM) then
if ($TERM == "gnome") then
setenv TERMCAP \
"`infocmp -C gnome | grep -v '^#' | tr '\n\t' ' ' | sed 's/\\ //g' | sed s/::/:/g`"
bindkey "^?" delete-char
bindkey "^[^?" delete-word
bindkey "\377" delete-word
endif
endif
set KBS=`tput kbs`
if (${%KBS} == 1) then
stty erase $KBS
endif
|
| [1] | On older
version of the bash, you must remember to set
| |
| [2] | More precisely, to the shell configuration file that is read in every shell, not only in login shells. The right file depend on startup sequence of your bash. |