Home 键和 End 键无法工作

出自 ArchWiki

命令行程序中一个常见的问题是 Home 键和 End 键无法按预期工作。这通常是因为终端模拟器在按下这些键时发送了多字符转义码,而正在运行的程序(例如您的 shell)不知道如何正确解释这些代码。通常,可以通过配置有问题的程序在接收到某些转义码时执行正确的操作来解决此问题。因此,解决方案因程序而异。

首先,您应该检查可能影响许多程序行为的常见原因。

TERM

按键失效的首要原因是 TERM 环境变量被覆盖为与您的 shell 冲突的值。所有现代终端都足够智能,可以设置自己的 TERM 变量,因此在您深入研究程序配置之前,请确保您没有错误地覆盖它(例如,在您的 ~/.bashrc 中)。再次强调,不要手动设置 TERM - 让终端来完成。

如果您不喜欢终端选择的 TERM 值(例如,当您想要 'xterm-256color' 时却得到 'xterm'),通常有一种方法可以配置您的终端来正确地覆盖它,而无需更改 TERM 变量。

对于 xterm 和 urxvt,可以在 X resources 中设置

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

对于 GNU Screen,可以在 ~/.screenrc 中设置

~/.screenrc
term screen-256color

对于 Tmux,可以在 ~/.tmux.conf 中设置(参见 tmux#配置

~/.tmux.conf
set -g default-terminal screen-256color

Shell 提示符

Home 键和 End 键行为异常的另一个可能原因是格式错误的自定义 shell 提示符。shell 尝试计算 PS1 环境变量中包含的提示符的实际长度,但如果 PS1 包含一些转义序列(例如,用于彩色文本),shell 可能会认为它们是具有非零长度的实际可打印字符。这显然会导致文本渲染错误。

本文或章节需要扩充。

原因: 以下说明是 Bash 特有的。添加其他 shell 的说明,例如 Zsh%{...%}。(在 Talk:Home and End keys not working 中讨论)

为了避免这种情况,您应该将 PS1 中的非打印内容用 \[\] 括起来,以便 shell 可以理解它实际上是不可打印的。例如,您 .bashrc 中的这一行

PS1="\e[32m\u \e[34m\w \e[37m\$ \e[0m"

应该变成这样

PS1="\[\e[32m\]\u \[\e[34m\]\w \[\e[37m\]\$ \[\e[0m\]"

更多信息,请参阅 Bash/提示符自定义

Readline

许多命令行应用程序使用 Readline 库来读取输入。因此,正确配置 Readline 可以在许多情况下修复 Home 键和 End 键的问题。Readline 在 /etc/inputrc~/.inputrc 中维护更晦涩的按键映射,分别用于全局和用户特定的映射。

在默认的 /etc/inputrc 中,有几行尝试处理常见的 Home/End 转义码

"\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

如果您的按键无法工作,可能是因为您的特定终端发送的转义码不在列表中。首先,您需要找出发送了哪些转义码。要查看它们,您可以使用名为 "quoted-insert" 的 Readline 命令或运行命令 showkey --scancodes,该命令逐字输出按键的值。quoted-insert 的默认绑定是 Ctrl+v

例如,您可以在终端中输入以下一系列输入

  1. Ctrl+v
  2. 首页
  3. 空格
  4. Ctrl+v
  5. End

并获得如下输出

^[[1~ ^[[4~

^[ 表示 shell 中的转义字符,因此这意味着您的 Home 键的转义码为 [1~,而 End 键的转义码为 [4~。由于这些转义码未在默认 Readline 配置中列出,因此您需要添加它们

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

请注意,Readline 使用 \e 来表示转义字符。

Terminfo

对于不使用 Readline 的程序(例如 ncurses),您可以尝试编辑 terminfo 以更改为某些操作发送到终端的转义码。

首先将您现有的 terminfo 保存到文件

$ infocmp $TERM > terminfo.src

然后编辑它以更改转义码。例如,更改 khomekend

khome=\E[1~, kend=\E[4~,
警告: 确保没有其他按键使用相同的字符序列。

然后编译新的 terminfo(将其保存到您的 ~/.terminfo 目录)

$ tic terminfo.src

最后,在您的 shell 的 环境变量 中指定新的 terminfo

export TERMINFO=~/.terminfo

其他应用程序

如果上述步骤未能解决问题,则可能是程序特定的问题,而不是系统范围的问题。您可能需要查阅给定程序的文档,了解如何修复它。以下是常见程序的修复方法。

Lynx

您可以使用与 Readline 相同的 quoted-insert 字符添加按键绑定,但使用 \033 来表示转义字符

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

URxvt/Rxvt

使用与 Lynx 相同的转义序列格式将转义码绑定添加到您的 X resources

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

其中 KP_HomeKP_End 是数字键盘的 Home 键和 End 键。这些绑定也可能修复在 URxvt 中运行的程序,例如 nano

另一个解决方案是将以下部分添加到 /etc/inputrc

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

Zsh

使用 terminfo(5) 数据库来设置正确的按键绑定,请参阅 Zsh#按键绑定

Less

lesskey 源文件

对于 less 582 及更高版本,可以使用 $XDG_CONFIG_HOME/lesskey$HOME/.config/lesskey$HOME/.lesskey 下的纯文本配置文件。

$HOME/.config/lesskey
#line-edit
\e[1~ home
\e[4~ end