Difference between revisions of "Backspace and Delete key reversed"

From Exterior Memory
Jump to: navigation, search
(Terminal (terminfo))
(Vim)
 
(25 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
==Theory==
 
==Theory==
  
Sometimes the backspace/delete does not work as expect. In a terminal or editor, pressing the backspace results in a delete command, or vice versa.
+
Sometimes the backspace/delete does not work as expected. In a terminal or editor, pressing the backspace results in a delete command, or vice versa.
  
 
The mapping of the backspace and delete key to a given application behaviour has differed in the course of time, and per terminal and application. In fact, there are two mappings to take into account:
 
The mapping of the backspace and delete key to a given application behaviour has differed in the course of time, and per terminal and application. In fact, there are two mappings to take into account:
* The mapping of a keystroke to a character sequence in the terminal (tty)
+
* The '''mapping of a keystroke to a character sequence''' in the terminal (tty). This is configured on your '''local machine'''
* The mapping of a character sequence to a certain behaviour by an application, such as the shell (bash, tcsh, zsh) or editor (vi, emacs).
+
* The '''mapping of a character sequence to a certain behaviour''' by an application, such as the shell (bash, tcsh, zsh) or editor (vi, emacs). This is configured on the machine where the application runs (this may be a '''remote machine''').
  
 
===VT100===
 
===VT100===
Line 19: Line 19:
 
|}
 
|}
  
So the delete key was undefined and the not the backspace key but control-H was mapped to the BS (backspace) character. How convenient.
+
So the delete key was undefined and not the backspace key but control-H was mapped to the BS (backspace) character. How convenient.
  
 
===Xterm===
 
===Xterm===
  
The X-term emulation of VT100 did it different:
+
The X-term emulation of VT100 did it differently:
  
 
{|
 
{|
Line 41: Line 41:
 
The disadvantage of the X-term behaviour was that control-H could not be used by applications just like other control-shortcuts by GUI applications (e.g. control-F for find, or perhaps control-H for help).
 
The disadvantage of the X-term behaviour was that control-H could not be used by applications just like other control-shortcuts by GUI applications (e.g. control-F for find, or perhaps control-H for help).
  
For this reason, the behaviour was changed again, to the following mapping, which is now the default by most Linux distributions:
+
For this reason, the behaviour was changed again, to the following mapping, which is now the default in most Linux distributions:
  
 
{|
 
{|
Line 59: Line 59:
 
If you read this page, you most likely have problems with your current application behaviour and want to change the keystroke and characters mappings.
 
If you read this page, you most likely have problems with your current application behaviour and want to change the keystroke and characters mappings.
  
The VT220 mapping is more-or-less the default by most Linux distributions. You first action is to [[#Determine_Current_mapping|make sure you are already using the VT220 mapping]]. You shouldn't use anything else, or you will be in trouble as soon as you log in from another computer. '''Do not simply change the keystroke to character mapping'''. Do not deviate from the VT220 behaviour unless you Really understand what you are doing. If you use the VT220 mapping, but one or more applications still behave incorrectly, '''change the mapping of characters to application behaviour instead'''.
+
The VT220 mapping is more-or-less the default in most Linux distributions. Your first action is to [[#Determine_Current_mapping|make sure you are already using the VT220 mapping]]. You shouldn't use anything else, or you will be in trouble as soon as you log in from another computer. So, do not deviate from the VT220 behaviour unless you Really understand what you are doing. If you use the VT220 mapping, but one or more applications still behave incorrectly, '''do not change the keystroke to character mapping but change the mapping of characters to application behaviour instead'''.
  
 
The rest of this article contains information to make sure your terminal uses the VT220 keymapping, and the applications make use of this.
 
The rest of this article contains information to make sure your terminal uses the VT220 keymapping, and the applications make use of this.
Line 70: Line 70:
 
==Keystroke to TTY mapping==
 
==Keystroke to TTY mapping==
  
===Determine Current mapping===
+
===Determine Current Mapping===
  
 
You can determine the current mapping using the "control-V trick": First press control-V, then the keystroke you like to examine. This will print the characters that are sent to the terminal.
 
You can determine the current mapping using the "control-V trick": First press control-V, then the keystroke you like to examine. This will print the characters that are sent to the terminal.
Line 102: Line 102:
  
 
If it lists <tt>erase = ^H</tt>, then you have the wrong keymapping.
 
If it lists <tt>erase = ^H</tt>, then you have the wrong keymapping.
 +
 +
===Xterm===
 +
 +
To make matters slightly more complex, Xterm not only has a mapping from keys to TTY characters, but has the following mappings:
 +
* keystrokes on the keyboard to keycode(s)
 +
* keycode to keysyms
 +
* keysyms to TTY mappings.
 +
 +
The mapping between keys on the keyboard and keycodes is fixed. You can determine the keycodes using the <tt>xev</tt> program, which diplays all X events.
 +
 +
With this information, you can use the <tt>xmodmap</tt> program to define a mapping from keycode to a keysym. For example, my keyboard correctly maps keycodes 59 and 125 to BackSpace and Delete keysyms:
 +
xmodmap -e 'keycode 59 = BackSpace'
 +
xmodmap -e 'keycode 125 = Delete'
 +
 +
Another keyboard (with keys at a different position may have the following mapping:
 +
xmodmap -e 'keycode 22 = BackSpace'
 +
xmodmap -e 'keycode 107 = Delete'
 +
 +
Usually this is the default binding already.
 +
 +
Finally, you can map keysyms to TTY characters by creating a <tt>.Xdefaults</tt> file in your home directory:
 +
 +
*VT100.Translations: #override \
 +
              <Key>BackSpace: string(0x7F)\n\
 +
              <Key>Delete:    string("\033[3~")
 +
*ttyModes: erase ^?
 +
 +
Beware that the syntax of the <tt>.Xdefaults</tt> file is very strict, be careful to include a \ as the last character of each line, except the last line and that no space follows the \ character.
 +
 +
If you are using plain xterms, you most likely only want to create a  <tt>.Xdefaults</tt> file.
 +
 +
If you are using X windows, like Gnome or KDE, you first may want to read that documentation. I haven't dived into it, but both GUIs come with tools to change the keyboard mapping. I presume this changes the keycode to keysyms mapping. So you better configure this mapping before you dive into the keysyms to TTY character mapping.
 +
 +
===Screen===
 +
 +
If a shell works correctly, but if screen is started, the keys are reversed, then the best solution is to turn off screen mappings. This can be done by setting the environmental variable TERM:
 +
TERM=screen
 +
In order to always set this, define the alias:
 +
alias screen='TERM=screen screen'
 +
 +
===Apple Terminal application===
 +
 +
The default behaviour of the Apple's Terminal application is good.
 +
 +
In the Preference dialog, Setting item:
 +
* In the ''Keyboard'' tab, make sure that "forward delete" maps to "\033[3~"
 +
* In the ''Advanced'' tab, make sure the "Delete sends Ctrl-H" checkbox is '''off'''
 +
 +
===iTerm (Mac OS X application)===
 +
 +
iTerm is an alternative to Apple's Terminal. By default it comes with two Keyboard profiles, ''Global'' and ''xterm''. Both profiles use the correct (VT220) mapping by default.
 +
 +
Unfortunately, the key names are ill-defined. "del" refers to the delete key, while "delete" refers to the backspace key.
 +
 +
The xterm defines the "delete" (= backspace, really) key to be mapped to "send hex 7f". Indead, it sends ^?. This is the correct default for the backspace key.
 +
 +
If you want to make the keys explicit, set:
 +
 +
{|
 +
| delete (backspace key) || send hex code "7F"
 +
|-
 +
| del (delete key) || send escape sequence "[3~"
 +
|}
  
 
===Terminal (terminfo)===
 
===Terminal (terminfo)===
 +
 +
''Warning: I do no longer recommend to fiddle with the terminfo settings. It is a hassle and there are often better ways to achieve the same results. See above.''
  
 
Run the command
 
Run the command
  infocmp
+
  infocmp -1 | grep kbs
 +
infocmp -1 | grep kdch1
 
And look for the settings:
 
And look for the settings:
  
Line 124: Line 190:
  
 
For example, this term is wrong:
 
For example, this term is wrong:
  % infocmp xterm | grep kbs
+
  % infocmp -1 xterm | grep kbs
  kPRV=\E[5;2~, kRIT=\E[1;2C, kb2=\EOE, kbs=^H, kcbt=\E[Z
+
  kbs=^H
  
 
While this xterm-color (on another machine) is correct:
 
While this xterm-color (on another machine) is correct:
  % infocmp xterm-color | grep kbs
+
  % infocmp -1 xterm-color | grep kbs
  is2=\E[m\E[?7h\E[4l\E>\E7\E[r\E[?1;3;4;6l\E8, kbs=\177,
+
  kbs=\177,
  
 
If you found to correct one, set $TERM=xterm-color to pick the correct xterm. If you can't locate a good option on your machine, copy it (from another machine) to <tt>~/.terminfo/x/</tt> and set $TERM to whatever file yu copied (thus <tt>export TERM=xterm-color</tt> if you copied <tt>~/.terminfo/x/xterm-color</tt>)
 
If you found to correct one, set $TERM=xterm-color to pick the correct xterm. If you can't locate a good option on your machine, copy it (from another machine) to <tt>~/.terminfo/x/</tt> and set $TERM to whatever file yu copied (thus <tt>export TERM=xterm-color</tt> if you copied <tt>~/.terminfo/x/xterm-color</tt>)
  
If you want to create your own custom terminfo file, know that ther terminfo files are compiled. You can extract them using <tt>infocmp</tt> and compile them with <tt>tic</tt>.
+
If you want to create your own custom terminfo file, know that the terminfo files are compiled. You can extract them using <tt>infocmp</tt> and compile them with <tt>tic</tt>.
  
===Terminfo===
+
==TTY to Application mapping==
  
 +
===Zsh===
  
===Xterm GUI===
+
Add the following lines to your <tt>.zshrc</tt> file:
  
 +
bindkey "^?" backward-delete-char
 +
bindkey "^[[3~" delete-char
  
 +
===Bash===
  
===Apple Terminal application===
+
Bash uses the GNU readline library, so you will have to edit your <tt>.inputrc</tt> file:
  
The default behaviour of the Apple's Terminal application is good.
+
"\e[3~": delete-char
  
In the Preference dialog, Setting item:
+
If a system-wide /etc/inputrc was created, add the following line to /etc/profile:
* In the ''Keyboard'' tab, make sure that "forward delete" maps to "\033[3~"
+
* In the ''Advanced'' tab, make sure the "Delete sends Ctrl-H" checkbox is '''off'''
+
  
===iTerm (Mac OS X application)===
+
export INPUTRC=/etc/inputrc
  
iTerm is an alternative to Apple's Terminal. By default it comes with two Keyboard profiles, ''Global'' and ''xterm''. Both profiles use the correct (VT220) mapping by default.
+
===Tcsh===
  
Unfortunately, the key names are ill-defined. "del" refers to the delete key, while "delete" refers to the backspace key.
+
Add the following lines to your <tt>.cshrc</tt> file:
  
The xterm defines the "delete" (= backspace, really) key to be mapped to "send hex 7f". Indead, it sends ^?. This is the correct default for the backspace key.
+
bindkey "\e[3~" delete-char
  
If you want to make the keys explicit, set:
+
===Emacs===
  
{|
+
Emacs works fine by default for me when using the VT220 settings.
| delete (backspace key) || send hex code "7F"
+
|-
+
| del (delete key) || send escape sequence "[3~"
+
|}
+
  
==TTY to Application mapping==
+
However, I read that by default emaps maps both the backspace and the delete key to delete-backward-char. This is by design. To map the backspace to delete-backward-char and delete to delete-char, put the following lines in your <tt>.emacs</tt> file:
  
===Vim===
+
(normal-erase-is-backspace-mode 0)
  
 +
or
  
However, this is annoying, and there are two solutions to this problem.
+
(global-set-key [backspace] 'delete-backward-char)
 +
(global-set-key [delete] 'delete-char)
 +
 
 +
===Vim===
  
 +
Vi and vim seem to work fine with the default VT220 mapping.
  
The biggest problem with backspace vs. delete was caused by some
+
If you still have problems with vi, type <tt>:help fixdel</tt> for information how to fix it in you <tt>.vimrc</tt> file. If you feel brave, you can also edit your terminfo file.
terminal manufacturer many years ago.
+
  
The button on your keyboard in the upper right corner that usually has
+
===Pine/Pico/Nano===
the glyphs "backspace" on it originally sent ASCII character 127 to
+
the host.  This was with vt100's or something "original" like that.
+
IIRC they don't even have a key labeled "delete".
+
  
In the ASCII table, however, you will notice a character with the name
+
Nano seems to work fine using the VT220 settings.
"BS" (backspace) but it has the value 8.  Some manufacturer at one
+
time decided that the button labeled "backspace" on your keyboard
+
should send the ASCII backspace character (8) and made the delete key
+
send 127 (which is labeled DEL in man ascii on at least some systems).
+
  
The BS character also has the representation ^H, and the DEL character
+
If you use pine or pico, it may not be possible to fix it, and you may want to switch to nano (a pico clone).
has the representation ^?.
+
  
If you look at your terminal and type "stty -a" you will see which
 
character has the "erase" function (commonly known as "backspace").
 
Then you can check your terminal emulator settings to see character it
 
sends when you press the backspace and delete keys.  (At a shell
 
simply type ^V[backspace] -- that is Ctrl-V then Backspace -- and you
 
will see either ^H or ^?)
 
  
As you can see this is a big mess, but you just need to make sure that
+
[[Category:Unix Tools]]
all your terminals and shells agree on what the backspace and delete
+
[[Category:Keyboard]]
buttons on your keyboard mean.
+

Latest revision as of 12:31, 8 November 2012

Theory

Sometimes the backspace/delete does not work as expected. In a terminal or editor, pressing the backspace results in a delete command, or vice versa.

The mapping of the backspace and delete key to a given application behaviour has differed in the course of time, and per terminal and application. In fact, there are two mappings to take into account:

  • The mapping of a keystroke to a character sequence in the terminal (tty). This is configured on your local machine
  • The mapping of a character sequence to a certain behaviour by an application, such as the shell (bash, tcsh, zsh) or editor (vi, emacs). This is configured on the machine where the application runs (this may be a remote machine).

VT100

Originally, VT100 defined the keymapping:

Keystroke Glyph on keyboard ASCII Character(s) TTY representation Expected application behaviour
Control-H BS (8, 0x08) ^H Erase to the left
Backspace DEL (127, 0x7F) ^? Erase to the right

So the delete key was undefined and not the backspace key but control-H was mapped to the BS (backspace) character. How convenient.

Xterm

The X-term emulation of VT100 did it differently:

Keystroke Glyph on keyboard ASCII Character(s) TTY representation Expected application behaviour
Control-H BS (8, 0x08) ^H Erase to the left
Backspace BS (8, 0x08) ^H Erase to the left
Delete DEL (127, 0x7F) ^? Erase to the right

This is slightly more logical, and the advantage was that the mapping of TTY character to application behaviour did not have to be changed.

VT220

The disadvantage of the X-term behaviour was that control-H could not be used by applications just like other control-shortcuts by GUI applications (e.g. control-F for find, or perhaps control-H for help).

For this reason, the behaviour was changed again, to the following mapping, which is now the default in most Linux distributions:

Keystroke Glyph on keyboard ASCII Character(s) TTY representation Expected application behaviour
Control-H BS (8, 0x08) ^H (Passed on to application)
Backspace DEL (127, 0x7F) ^? Erase to the left
Delete ESC (27, 0x1B) + [3~ ("\e[3~") ^[[3~ Erase to the right

The disadvantage of the change is of course that both the TTY keymapping as well as the default application behaviour had to be changed.

How To Solve It

If you read this page, you most likely have problems with your current application behaviour and want to change the keystroke and characters mappings.

The VT220 mapping is more-or-less the default in most Linux distributions. Your first action is to make sure you are already using the VT220 mapping. You shouldn't use anything else, or you will be in trouble as soon as you log in from another computer. So, do not deviate from the VT220 behaviour unless you Really understand what you are doing. If you use the VT220 mapping, but one or more applications still behave incorrectly, do not change the keystroke to character mapping but change the mapping of characters to application behaviour instead.

The rest of this article contains information to make sure your terminal uses the VT220 keymapping, and the applications make use of this.

More information can be found at:

Keystroke to TTY mapping

Determine Current Mapping

You can determine the current mapping using the "control-V trick": First press control-V, then the keystroke you like to examine. This will print the characters that are sent to the terminal.

For example typing control-V + backspace prints:

^?

meaning that backspace is mapped to the DEL (127, 0x1F) character.

Make sure that you are currently using the VT220 mapping:

Keystroke to Type Expected Output (for VT220 mapping)
control-V backspace ^?
control-V delete ^[[3~
control-V control-H ^H

If it isn't, change the mapping, as explained in this section. If it is correct, do not change the terminal settings, but instead, change the application behaviour.

An alternative (but less reliable) way to find the keymap is to use the stty command:

stty -a

look for the line

erase = ^?

If it lists erase = ^H, then you have the wrong keymapping.

Xterm

To make matters slightly more complex, Xterm not only has a mapping from keys to TTY characters, but has the following mappings:

  • keystrokes on the keyboard to keycode(s)
  • keycode to keysyms
  • keysyms to TTY mappings.

The mapping between keys on the keyboard and keycodes is fixed. You can determine the keycodes using the xev program, which diplays all X events.

With this information, you can use the xmodmap program to define a mapping from keycode to a keysym. For example, my keyboard correctly maps keycodes 59 and 125 to BackSpace and Delete keysyms:

xmodmap -e 'keycode 59 = BackSpace'
xmodmap -e 'keycode 125 = Delete'

Another keyboard (with keys at a different position may have the following mapping:

xmodmap -e 'keycode 22 = BackSpace'
xmodmap -e 'keycode 107 = Delete'

Usually this is the default binding already.

Finally, you can map keysyms to TTY characters by creating a .Xdefaults file in your home directory:

*VT100.Translations: #override \
             <Key>BackSpace: string(0x7F)\n\
             <Key>Delete:    string("\033[3~")
*ttyModes: erase ^? 

Beware that the syntax of the .Xdefaults file is very strict, be careful to include a \ as the last character of each line, except the last line and that no space follows the \ character.

If you are using plain xterms, you most likely only want to create a .Xdefaults file.

If you are using X windows, like Gnome or KDE, you first may want to read that documentation. I haven't dived into it, but both GUIs come with tools to change the keyboard mapping. I presume this changes the keycode to keysyms mapping. So you better configure this mapping before you dive into the keysyms to TTY character mapping.

Screen

If a shell works correctly, but if screen is started, the keys are reversed, then the best solution is to turn off screen mappings. This can be done by setting the environmental variable TERM:

TERM=screen

In order to always set this, define the alias:

alias screen='TERM=screen screen'

Apple Terminal application

The default behaviour of the Apple's Terminal application is good.

In the Preference dialog, Setting item:

  • In the Keyboard tab, make sure that "forward delete" maps to "\033[3~"
  • In the Advanced tab, make sure the "Delete sends Ctrl-H" checkbox is off

iTerm (Mac OS X application)

iTerm is an alternative to Apple's Terminal. By default it comes with two Keyboard profiles, Global and xterm. Both profiles use the correct (VT220) mapping by default.

Unfortunately, the key names are ill-defined. "del" refers to the delete key, while "delete" refers to the backspace key.

The xterm defines the "delete" (= backspace, really) key to be mapped to "send hex 7f". Indead, it sends ^?. This is the correct default for the backspace key.

If you want to make the keys explicit, set:

delete (backspace key) send hex code "7F"
del (delete key) send escape sequence "[3~"

Terminal (terminfo)

Warning: I do no longer recommend to fiddle with the terminfo settings. It is a hassle and there are often better ways to achieve the same results. See above.

Run the command

infocmp -1 | grep kbs
infocmp -1 | grep kdch1

And look for the settings:

Keystroke Expected Mapping
kbs (backspace key) \177 (or ^?)
kdch1 (delete key) \E[3~

If this is incorrect, you may want to try another terminfo setting, or (if you are the daring type) create your own terminfo file.

The terminfo files are typically stored in the /usr/share/terminfo/ directory. Run toe to get a (long) list of all available terminal types:

toe             # on BSD-like systems
toe -a          # on Linux-like systems

For example, this term is wrong:

% infocmp -1 xterm | grep kbs
kbs=^H

While this xterm-color (on another machine) is correct:

% infocmp -1 xterm-color | grep kbs
kbs=\177,

If you found to correct one, set $TERM=xterm-color to pick the correct xterm. If you can't locate a good option on your machine, copy it (from another machine) to ~/.terminfo/x/ and set $TERM to whatever file yu copied (thus export TERM=xterm-color if you copied ~/.terminfo/x/xterm-color)

If you want to create your own custom terminfo file, know that the terminfo files are compiled. You can extract them using infocmp and compile them with tic.

TTY to Application mapping

Zsh

Add the following lines to your .zshrc file:

bindkey "^?" backward-delete-char
bindkey "^[[3~" delete-char

Bash

Bash uses the GNU readline library, so you will have to edit your .inputrc file:

"\e[3~": delete-char

If a system-wide /etc/inputrc was created, add the following line to /etc/profile:

export INPUTRC=/etc/inputrc

Tcsh

Add the following lines to your .cshrc file:

bindkey "\e[3~" delete-char

Emacs

Emacs works fine by default for me when using the VT220 settings.

However, I read that by default emaps maps both the backspace and the delete key to delete-backward-char. This is by design. To map the backspace to delete-backward-char and delete to delete-char, put the following lines in your .emacs file:

(normal-erase-is-backspace-mode 0)

or

(global-set-key [backspace] 'delete-backward-char)
(global-set-key [delete] 'delete-char)

Vim

Vi and vim seem to work fine with the default VT220 mapping.

If you still have problems with vi, type :help fixdel for information how to fix it in you .vimrc file. If you feel brave, you can also edit your terminfo file.

Pine/Pico/Nano

Nano seems to work fine using the VT220 settings.

If you use pine or pico, it may not be possible to fix it, and you may want to switch to nano (a pico clone).