使用 bash shell 时,我尝试使用Shift+LEFT突出显示并复制我输入的命令(而不是使用鼠标)。但是,我得到了很多C。后来我意识到Shift+UP使A
,Shift+DOWN使B
,Shift+RIGHT也使D
。
为什么会这样?
我认为它来自原始击键数据(^[[A
、^[[B
、^[[C
和^[[D
),但它只是一个大写字母(^[[
开头没有)。
使用 bash shell 时,我尝试使用Shift+LEFT突出显示并复制我输入的命令(而不是使用鼠标)。但是,我得到了很多C。后来我意识到Shift+UP使A
,Shift+DOWN使B
,Shift+RIGHT也使D
。
为什么会这样?
我认为它来自原始击键数据(^[[A
、^[[B
、^[[C
和^[[D
),但它只是一个大写字母(^[[
开头没有)。
这是一个可以追溯到 1980 年代的键盘输入协议,而您的外壳,而不是M. Vazquez-Abrams 的回答中的“终端驱动程序”(应该是什么),没有正确处理它。此外,它是一个完全有效的控制序列。
背景
终端发出功能键和扩展按键的控制序列。它们可以发出 DECFNK 控制序列,这是 CSI 引入的控制序列;Linux 功能键控制序列,这是一种不同的 CSI 引入序列;SCO控制台功能键控制序列,是CSI引入的第三种序列;移位的单个字符,以 SS3 为前缀;或者,在这种情况下,各种事物的 ECMA-48 标准序列。
(SS3 和 CSI 是控制字符,在 C1 范围内。Single Shift 3 和 Control Sequence Introducer。)
您的(IBM M 型类似或类似的)键盘上有两个特定的小键盘,一个计算器小键盘和一个光标小键盘。DEC VT 风格的终端仿真器(您可能会遇到的大多数终端仿真器,从内核中的终端仿真器到 unicode-rxvt)所采用的模型是两个键盘都有可单独切换的应用程序/正常模式。全屏 TUI 应用程序,使用 libedit 或 GNU readline 库(或 ZLE)的东西,例如你的 shell,以及一些其他类型的应用程序指定他们想要的模式,然后通过读取突发来监听来自终端的控制序列字符数(因为人类无法像终端或终端仿真器发送控制序列一样快地键入完整的 ECMA-48 控制序列,Esc来自终端仿真器的键发送以 ␛ 字符开头的控制序列)。
因此,人们可以在应用程序模式和普通模式之间进行选择,在这种模式下,人们无法知道按下了哪些修饰符,但可以区分两个左箭头键,而在普通模式下,人们无法区分两个箭头键,但可以知道按下了哪些修饰符。
更详细地说:ECMA-48 控制序列的 DEC 增强是控制序列有两个参数:
这就是 DEC VT 终端自 1980 年代以来一直在做的事情。近年来,一些终端仿真器终于引入了相同的功能(尽管如前所述,XTerm 搞错了)。
这是怎么回事。
问题是您的 GNU readline 库、libedit、ZLE 等并没有真正正确地处理协议。他们不应该完全受到责备。他们依赖于 termcap 和 terminfo 系统,这根本不能胜任这里的工作。termcap 和 terminfo 并没有真正的输入控制序列可以变化的概念,更不用说多模式键盘了。
为此,您必须查看 Vim 之类的东西,它可以使用对 terminfo 的特殊覆盖进行编程,以指定遵循上述协议(参见
:help xterm-modifier-keys
Vim 中)的控制序列,或使用Paul Evans 的 libtermkey及其CSI 驱动程序的 NeoVIM 。libtermkey 的 CSI 驱动程序是一个必须正确处理来自 DEC VT 类似终端仿真器的键盘输入的方法。它是一个实际的 ECMA-48 状态机解析器,可以正确解码控制序列。但是你的 shell 正在做的是在 terminfo 中查找箭头键的条目,并且只匹配那些特定的控制序列。
具体来说:
kcub1
其 terminfo 记录中查找您的终端的功能。这是记录中的一个,teken
例如:1
;
2
D
。相反,它使用 7 位替代方案和发送␛
[
1
;
2
D
,这␛
[
是将 CSI 编码为 7 位字符的方式。什么故障模式取决于它尝试模式匹配的输入序列集,因为这决定了它在确定它有一个没有可能匹配的序列之前吞下了多少个字符。当然,这又取决于您的终端的 terminfo/termcap 记录实际包含的内容以及您告诉 shell 您的终端是什么终端类型。
修复
这类事情的本地修复是在你的 shell 中使用键绑定来获得创意。这就是为什么,例如,你会发现人们在他们
.zshrc
的 s 中使用 Z shell 做这种事情:不幸的是,没有非本地修复。这将涉及非常显着地重新架构你的 shell 的输入处理。这种重新架构早就该进行了。(见证 NeoVIM。)但是还没有人解决它。
进一步阅读
DECFNK
. “ANSI 控制功能”。 VT510 终端程序员信息。EK-VT510-RM。1993 年 11 月。数字。按Ctrl+V将使下一个按键按字面意思输入。对于Shift+↑这将导致“^[[1;2A”。终端驱动程序使用“^[[1;2”作为无效的转义序列,只留下“A”。