Difference between revisions of "Home and End keys not working"

From ArchWiki
Jump to: navigation, search
m (Zsh: corrected link)
m (add ja link)
 
(57 intermediate revisions by 13 users not shown)
Line 1: Line 1:
{{accuracy|reason=Escape codes should not be hardcoded as is done on this page. These escape codes vary in meaning per terminal, which is why terminfo exists in the first place. In zsh you can use the {{ic|$terminfo}} associative array, and in other shells you can use {{ic|tput}}.}}
 
 
[[Category:Command shells]]
 
[[Category:Command shells]]
 
[[Category:Keyboards]]
 
[[Category:Keyboards]]
{{Note|This page previously contained some bad advice.  Setting the TERM environment variable in your ~/.bashrc is a '''BAD''' idea.  Please do not do it. Follow the advice below.}}
+
[[ja:Home や End キーが機能しない]]
 +
A frequent problem in command line programs is that keys like Home and End do not work as expected. This is usually because the terminal emulator sends multi-character escape codes when such keys are pressed, which the running program (such as your shell) does not know how to interpret correctly. Usually this problem can be fixed by configuring the offending program to perform the correct action when receiving certain escape codes. Thus the solution varies from program to program.
  
==Why do not my Home and End keys work in terminals?==
+
First you should check the common culprits that can affect the behavior of many programs.
  
Technically, this is a little wrong.  Your home and end keys work fine in a terminal.  They ''don't'' work, however, in your shell (bash).
+
== TERM ==
  
Typically, command line applications use ''libreadline'' for interaction. If you know it does not use readline, this tactic may or may not work. For instance, ncurses applications most likely do not use libreadline, BUT ncurses is usually smart enough to map your Home/End keys properly.
+
The '''number one cause of broken keys''' is overriding the TERM environment variable to something that conflicts with your shell. All modern terminals are smart enough to set their own TERM variable, so before you go delving into program configurations ensure that you are not incorrectly overriding it (for example, in your {{ic|~/.bashrc}}). Again, '''do not set TERM manually - let the terminal do it.'''
  
===libreadline problem===
+
If you do not like the TERM value chosen by your terminal (e.g. 'xterm' when you want 'xterm-256color'), there is typically a way to configure your terminal to properly override it without changing the TERM variable.
  
Usually applications are able to fix this on their own.  The '''number one cause of this problem''' is setting your $TERM variable to something it is not in bashrc.  All modern terminals are smart enough to set their own term variable.
+
For xterm and urxvt, you can set it in your [[X resources]]
 
+
'''Do not set $TERM manually.  Let the terminal do it.'''
+
 
+
When in bash, do the following:
+
echo $TERM
+
 
+
You may or may not like the value it sets (i.e. 'xterm' when you want 'xterm-256color').  That is fine.  Typically there is a way to configure your terminal to change this without changing the TERM variable.
+
 
+
For xterm and urxvt, it is in <code>~/.Xresources</code>
+
 
  XTerm*termName: xterm-256color
 
  XTerm*termName: xterm-256color
 
  ...
 
  ...
 
  URxvt*termName: rxvt-unicode
 
  URxvt*termName: rxvt-unicode
  
For screen, you can set the $TERM variable in your ~/.screenrc with:
+
For [[Screen]], you can set it in your ~/.screenrc:
 
  term screen-256color
 
  term screen-256color
  
''TODO add more terminal configurations here''
+
For [[Tmux]], you can set it in your ~/.tmux.conf:
 +
set -g default-terminal screen-256color
  
===I do not touch my TERM value, and the keys still do not work right===
+
== Readline ==
  
This can happen.  Not everything is covered 100% of the time. But libreadline had a workaround for this.
+
Many command line applications use the [[Readline]] library to read input. So properly configuring Readline can fix Home and End in many cases. Readline maintains mappings for more obscure keys in {{ic|/etc/inputrc}} and {{ic|~/.inputrc}} for global and per-user mappings, respectively.
libreadline maintains mappings for more obscure keys in /etc/inputrc (or ~/.inputrc for user-by-user changes).
+
  
If you look at the Arch /etc/inputrc, you will see the following lines:
+
In the default {{ic|/etc/inputrc}}, there are several lines that attempt to handle common Home/End escape codes:
 
  "\e[1~": beginning-of-line
 
  "\e[1~": beginning-of-line
 
  "\e[4~": end-of-line
 
  "\e[4~": end-of-line
Line 46: Line 37:
 
  "\e[F": end-of-line
 
  "\e[F": end-of-line
  
All of these try to map your Home/End key values. To see the actual value of yours, you can use yet another libreadline binding, called "quoted-insert" which outputs the actual value of a key, rather than issuing the keypress. quoted-insert is typically "Ctrl-v".
+
If your keys are not working, it could be because your particular terminal sends escape codes not in this list. First you need to find out what escape codes are being sent. To see them, you can use a Readline command called "quoted-insert" or run the command {{ic|showkey --scancodes}} which outputs the value of a key verbatim. The default binding for quoted-insert is <kbd>Ctrl</kbd>+<kbd>V</kbd>.
Let's try an example (done on urxvt):
+
Ctrl-v F6 outputs ^[[17~
+
Ctrl-v Ctrl-c outputs ^C
+
Ctrl-v Home outputs ^[[1~
+
Ctrl-v End outputs ^[[4~
+
  
For future reference, the ^[ is a literal (quoted-insert) Esc keypress.  This means that these keys are actually sending "ESC [ 4 ~". In inputrc syntax, the ESC key is expressed with "\e" (as you can see above).
+
For example, you could give the following series of inputs in your terminal:
 +
# <kbd>Ctrl</kbd>+<kbd>V</kbd>
 +
# <kbd>Home</kbd>
 +
# <kbd>Spacebar
 +
# <kbd>Ctrl</kbd>+<kbd>V</kbd>
 +
# <kbd>End</kbd>
 +
And get as output
 +
$ ^[[1~ ^[[4~
 +
 
 +
The {{ic|^[}} indicates an escape character in your shell, so this means that your Home key has an escape code of {{ic|[1~}} and you End key has an escape code of {{ic|[4~}}. Since these escape codes are not listed in the default Readline config, you will need to add them:
  
For example the urxvt keys shown above would be:
 
 
  "\e[1~": beginning-of-line
 
  "\e[1~": beginning-of-line
 
  "\e[4~": end-of-line
 
  "\e[4~": end-of-line
  
If your Home and End key values are not listed in /etc/inputrc (as you can see, with the ^[ to \e conversion, mine ARE listed), you need to add them there.  99% of the time this will not effect other terminals.  Technically, one should add these settings to ~/.inputrc, because it's easier to keep track of, and stays with your user that way.  You can also do '''MUCH''' cooler things with a user-specific inputrc (See [[Inputrc]] for more details).
+
Note that Readline uses {{ic|\e}} to indicate an escape character.
  
===Adjusting terminfo (If nothing helps)===
+
== Terminfo ==
* Do <pre>infocmp $TERM &gt;terminfo.src</pre>
+
* Edit terminfo.src file in current directory to adjust keystrings. For example change khome and kend.
+
<pre>khome=\E[1~, kend=\E[4~, </pre>
+
{{Warning|1=Please check that no other key use the same character sequence.}}
+
* Run <pre>tic terminfo.src</pre> This command creates ~/.terminfo directory
+
* Add <pre>export TERMINFO=~/.terminfo</pre> to your profile
+
{{Tip|1=Of course this works only for termcap/terminfo capable programs. Other ones should have own keymap configuration mechanism}}
+
  
==Why do not my Home and End keys work in application XYZ?==
+
For programs that do not use Readline (e.g. ncurses), you can try editing your terminfo to change which escape codes are sent to the terminal for certain actions.
  
If you've gone through the above, and your TERM is set properly, and your Home and End keys are properly entered into /etc/inputrc and ~/.inputrc, this is no longer system wide. Your keys are correct, but the application is not.  You will have to consult the documentation for the given app on how to do this. Hopefully we can add some examples here as we come across broken applications.
+
First save your existing terminfo to a file
 +
infocmp $TERM &gt;terminfo.src
 +
Then edit it to change the escape codes. For example change khome and kend:
 +
khome=\E[1~, kend=\E[4~,
 +
{{Warning|1=Ensure that no other key use the same character sequence.}}
 +
Then compile the new terminfo (which saves it to your {{ic|~/.terminfo}} directory)
 +
tic terminfo.src
 +
And lastly specify the new terminfo in your shell's environment variables
 +
export TERMINFO=~/.terminfo
 +
 
 +
== Other Applications ==
 +
 
 +
If the above steps do not resolve the issue, it is probably a program-specific problem rather than a system-wide one. You may have to consult the documentation for the given program on how to fix it. Below are fixes for common programs.
  
 
===Lynx===
 
===Lynx===
In lynx.cfg, use the quoted-insert characters above, replacing ^[ with \033:
+
You can add key binds using the same quoted-insert characters as used for [[#Readline|Readline]], but use {{ic|\033}} to represent an escape character:
setkey "\033[1~" HOME
+
{{hc|lynx.cfg|setkey "\033[1~" HOME
setkey "\033[4~" END
+
setkey "\033[4~" END}}
  
 
===URxvt/Rxvt===
 
===URxvt/Rxvt===
  
In your X resources (in ~/.Xresources file) you should add something like following:
+
Add escape code binds to your [[X resources]] using the same escape sequence format as for [[#Lynx|Lynx]]:
  
<pre>
+
{{bc|URxvt.keysym.Home: \033[1~
URxvt*keysym.Home: \033[1~
+
URxvt.keysym.End: \033[4~
URxvt*keysym.End: \033[4~
+
URxvt.keysym.KP_Home: \033[1~
</pre>
+
URxvt.keysym.KP_End:  \033[4~}}
 +
 
 +
Where KP_Home and KP_End are the numpad Home and End keys. These binds might also fix programs running within URxvt e.g. Nano.
 +
 
 +
Another solution is to add the following section to {{ic|/etc/inputrc}}
 +
 
 +
# those two are for rxvt
 +
"\e[7~":beginning-of-line
 +
"\e[8~":end-of-line
  
 
===Zsh===
 
===Zsh===
  
See [[Zsh#Key_bindings]].
+
In short, use the terminfo database to set the correct keybind.
 +
 
 +
{{hc|~/.zshrc|bindkey "${terminfo[khome]}" beginning-of-line
 +
bindkey "${terminfo[kend]}" end-of-line}}
 +
 
 +
See [[Zsh#Key bindings]] and [http://zshwiki.org/home/zle/bindkeys#reading_terminfo zshwiki: bindkeys] for more complete information.
  
 
===Less===
 
===Less===
Create file ~/.less with
+
Create a config file using {{ic|lesskey}} and the same escape codes for [[#Readline|Readline]]:
  
<pre>
+
{{hc|$ lesskey -o .less -|#command
$ lesskey -o .less -
+
#command
+
 
\e[4~ goto-end
 
\e[4~ goto-end
 
\e[1~ goto-line
 
\e[1~ goto-line
</pre>
+
}}
  
or for making less work in xterm
+
or for [[xterm]] you may have to use different escape codes
  
<pre>
+
{{hc|$ lesskey -o .less -|#command
$ lesskey -o .less -
+
#command
+
 
\eOF goto-end
 
\eOF goto-end
\eOH goto-line
+
\eOH goto-line}}
</pre>
+
 
+
or you may create systemwide config the same way.
+

Latest revision as of 14:57, 6 August 2016

A frequent problem in command line programs is that keys like Home and End do not work as expected. This is usually because the terminal emulator sends multi-character escape codes when such keys are pressed, which the running program (such as your shell) does not know how to interpret correctly. Usually this problem can be fixed by configuring the offending program to perform the correct action when receiving certain escape codes. Thus the solution varies from program to program.

First you should check the common culprits that can affect the behavior of many programs.

TERM

The number one cause of broken keys is overriding the TERM environment variable to something that conflicts with your shell. All modern terminals are smart enough to set their own TERM variable, so before you go delving into program configurations ensure that you are not incorrectly overriding it (for example, in your ~/.bashrc). Again, do not set TERM manually - let the terminal do it.

If you do not like the TERM value chosen by your terminal (e.g. 'xterm' when you want 'xterm-256color'), there is typically a way to configure your terminal to properly override it without changing the TERM variable.

For xterm and urxvt, you can set it in your X resources

XTerm*termName: xterm-256color
...
URxvt*termName: rxvt-unicode

For Screen, you can set it in your ~/.screenrc:

term screen-256color

For Tmux, you can set it in your ~/.tmux.conf:

set -g default-terminal screen-256color

Readline

Many command line applications use the Readline library to read input. So properly configuring Readline can fix Home and End in many cases. Readline maintains mappings for more obscure keys in /etc/inputrc and ~/.inputrc for global and per-user mappings, respectively.

In the default /etc/inputrc, there are several lines that attempt to handle common Home/End escape codes:

"\e[1~": beginning-of-line
"\e[4~": end-of-line
"\e[7~": beginning-of-line
"\e[8~": end-of-line
"\eOH": beginning-of-line
"\eOF": end-of-line
"\e[H": beginning-of-line
"\e[F": end-of-line

If your keys are not working, it could be because your particular terminal sends escape codes not in this list. First you need to find out what escape codes are being sent. To see them, you can use a Readline command called "quoted-insert" or run the command showkey --scancodes which outputs the value of a key verbatim. The default binding for quoted-insert is Ctrl+V.

For example, you could give the following series of inputs in your terminal:

  1. Ctrl+V
  2. Home
  3. Spacebar
  4. Ctrl+V
  5. End

And get as output

$ ^[[1~ ^[[4~

The ^[ indicates an escape character in your shell, so this means that your Home key has an escape code of [1~ and you End key has an escape code of [4~. Since these escape codes are not listed in the default Readline config, you will need to add them:

"\e[1~": beginning-of-line
"\e[4~": end-of-line

Note that Readline uses \e to indicate an escape character.

Terminfo

For programs that do not use Readline (e.g. ncurses), you can try editing your terminfo to change which escape codes are sent to the terminal for certain actions.

First save your existing terminfo to a file

infocmp $TERM >terminfo.src

Then edit it to change the escape codes. For example change khome and kend:

khome=\E[1~, kend=\E[4~,
Warning: Ensure that no other key use the same character sequence.

Then compile the new terminfo (which saves it to your ~/.terminfo directory)

tic terminfo.src

And lastly specify the new terminfo in your shell's environment variables

export TERMINFO=~/.terminfo

Other Applications

If the above steps do not resolve the issue, it is probably a program-specific problem rather than a system-wide one. You may have to consult the documentation for the given program on how to fix it. Below are fixes for common programs.

Lynx

You can add key binds using the same quoted-insert characters as used for Readline, but use \033 to represent an escape character:

lynx.cfg
setkey "\033[1~" HOME
setkey "\033[4~" END

URxvt/Rxvt

Add escape code binds to your X resources using the same escape sequence format as for Lynx:

URxvt.keysym.Home: \033[1~
URxvt.keysym.End: \033[4~
URxvt.keysym.KP_Home: \033[1~
URxvt.keysym.KP_End:  \033[4~

Where KP_Home and KP_End are the numpad Home and End keys. These binds might also fix programs running within URxvt e.g. Nano.

Another solution is to add the following section to /etc/inputrc

# those two are for rxvt
"\e[7~":beginning-of-line
"\e[8~":end-of-line

Zsh

In short, use the terminfo database to set the correct keybind.

~/.zshrc
bindkey "${terminfo[khome]}" beginning-of-line
bindkey "${terminfo[kend]}" end-of-line

See Zsh#Key bindings and zshwiki: bindkeys for more complete information.

Less

Create a config file using lesskey and the same escape codes for Readline:

$ lesskey -o .less -
#command
\e[4~ goto-end
\e[1~ goto-line

or for xterm you may have to use different escape codes

$ lesskey -o .less -
#command
\eOF goto-end
\eOH goto-line