要获取特定键盘快捷键的字符序列,我们使用showkey -a
或逐字插入 ( Ctrl+ V)。
它的反面是什么?如何从字符序列中获取人类可读格式的键盘快捷键?
例如,我使用了一些键绑定
^[^?
^X^U
^[[3;5~
^[[1;2D
^[[1;2C
^[[1;5C
^[[1;5D
^[[1;6C
^[[1;6D
....
现在我不记得它们用来代表哪个键/键组合。
我怎样才能找到它?
更新1
我正在寻找能够输出等的东西Ctrl+R
,Ctrl+Delete
我的意思是以人类可读的格式。
任何对具有可能的字符序列及其人类可读格式的表的引用也可以。
答案1
前几行
^[^?
^X^U
您可以找到以 ASCII 控件形式列出的代码
^[ (escape)
^U (control-U)
^X (control-X)
那^?
是 ASCII DEL 的常规表示形式(删除钥匙)。
如果您的终端描述 ( TERM
) 设置正确,
infocmp -1 -x
将以 terminfo 格式打印键的 ncurses 名称。还有其他信息,但您会看到这些行:
kDC5=\E[3;5~,
kRIT=\E[1;2C,
kRIT3=\E[1;3C,
kRIT4=\E[1;4C,
kRIT5=\E[1;5C,
kRIT6=\E[1;6C,
kRIT7=\E[1;7C,
kLFT=\E[1;2D,
kLFT3=\E[1;3D,
kLFT4=\E[1;4D,
kLFT5=\E[1;5D,
kLFT6=\E[1;6D,
kLFT7=\E[1;7D,
其中(鉴于 terminfo\E
是 ASCII 转义,或者^[
)您可以认为与您的示例相对应。这kLFT
和kRIT
名字告诉我那些是(xterm-style)修改的左/右光标键(参见XTerm 控制序列有关名称后数字的含义,请参见代码/修饰符表)。 terminfo 名称列在终端数据库:
# These are the extended keys defined in this file:
#
# kDC3 kDC4 kDC5 kDC6 kDC7 kDN kDN3 kDN4 kDN5 kDN6 kDN7 kEND3 kEND4 kEND5 kEND6
# kEND7 kHOM3 kHOM4 kHOM5 kHOM6 kHOM7 kIC3 kIC4 kIC5 kIC6 kIC7 kLFT3 kLFT4
# kLFT5 kLFT6 kLFT7 kNXT3 kNXT4 kNXT5 kNXT6 kNXT7 kPRV3 kPRV4 kPRV5 kPRV6 kPRV7
# kRIT3 kRIT4 kRIT5 kRIT6 kRIT7 kUP kUP3 kUP4 kUP5 kUP6 kUP7 ka2 kb1 kb3 kc2
并在中描述user_caps
手册页。
考虑到所有这些,有人可以制作一个程序或脚本来制作一个表格,显示可读格式(但知道它的记录位置应该会有所帮助)。
^[^?
如果您按下,某些终端会发送该信息AltDelete(但这不在终端描述中)。这^X^U
不是由终端模拟器中的单个按键发送的序列(除非您有反弹按键):更有可能是两次按键。
答案2
只要您的终端生成 ECMA-48 形式、DECFNK、Interix、SCO Console 或 Unicode RXVT 形式的输入控制序列,您就可以将其提供给我的console-decode-ecma48
工具,并使用--input
命令行选项告诉它字符流是输入而不是输出。对于当今您在实践中遇到的大多数终端和终端仿真器来说都是如此。
这是它对您的输入所做的操作,当然^[
替换为实际字符:␛
%控制台解码-ecma48 --输入 << EOF ^[^? ^X^U ^[[3;5~ ^[[1;2D ^[[1;2C ^[[1;5C ^[[1;5D ^[[1;6C ^[[1;6D EOF 德尔 如果 U+00000015 如果 DEC 控制+删除 如果 2级+CUB 1 如果 2级+CUF 1 如果 控制+CUF 1 如果 控制+CUB 1 如果 控制+级别2+CUF 1 如果 控制+Level2+CUB 1 如果 %
如所述https://unix.stackexchange.com/a/504056/5132,如果您想解码某些终端对⎇ Alt关键和弦的操作,您将还需要这个--no-7bit
选项;否则,您将获得 C1 控制字符的 7 位别名的 ECMA-48 标准解码。
CUF
CUB
当然,它们是标准 ECMA-48 名称:“CURSORF向前”和“CURSOR乙笨拙”。请参阅手册。
终端控制序列的规则可能会让您感到惊讶。您输入了␛
、DEL、␊
、␘
和␕
。终端控制序列的规则处理如下:
- 开始
␛
转义序列。 - DEL 立即作为控制字符处理,而转义序列仍然悬而未决。
- 会
␊
立即作为控制字符进行处理,而转义序列仍处于待处理状态。 - 取消
␘
(它在名称中)待处理的转义序列。 - 被
␕
处理为 C0 控制字符。console-decode-ecma48
对于该特定字符,打印其 Unicode 代码点。
请注意,据我所知,没有任何 shell 实际上包含正确的 ECMA-48 解码器。 Shell 进行模式匹配,这在处理终端一直发送的实际 ECMA-48 编码内容方面明显不完善。这会导致诸如以下讨论的问题之类的问题https://unix.stackexchange.com/a/499139/5132和https://unix.stackexchange.com/a/520429/5132等等。
console-decode-ecma48
实际上有一个带有控制序列状态机的适当的 ECMA-48 解码器,与 SCO Console、Interix 等有所不同。它不会向你展示确切地像 GNU Readline、libedit 和 ZLE 这样的东西会如何处理你的输入,因为它们没有得到正确的协议。
但它将要向您展示 ECMA-48 终端认为它正在发送的内容,这正是您想要的。
进一步阅读
- 乔纳森·德博因·波拉德 (2018)。 ”
console-decode-ecma48
”。 小吃指南。软件。
答案3
当您按下某个键(或组合键)时,终端发送什么字符或字符序列取决于终端本身。
虽然a
是准通用的,当您按下A 按键时所有终端都会发送(至少对于那些有这样一个键的终端),但对于、 或Home+Left等键,它在终端之间有很大差异。F1Ctrl6
但还是有一些共同点。值为 0 到 31 的 ASCII 控制字符通常表示为^@
, ^A
... ^Z
, ^[
, ^\
, ]
,^^
和^_
。您会注意到,对于所有这些,如果切换可打印字符的第 6 位,您将获得相应的控制字符(例如A
0x41,^A
is 0x1)。^?
是0x7f,?
是0x3f。
^X
当您按Ctrl+时,终端确实会发送字符X。
^I
Tab是 TAB 控制字符,对于那些有控制字符的按键(除了Ctrl+之外I),当您按该键时也会发送该字符。
与^[
、 又名\e
和Esc密钥相同。
^H
又名\b
是退格字符,但有些终端发送DEL
( ^?
) ,Backspace而另一些终端则发送^H
。
^M
aka\r
在 Return/Enter 时发送(但在某些模式下可以由终端设备驱动程序转换为^J
aka )。\n
^@
又名可以在+\0
上发送,但有时也可以在+上发送。Ctrl@CtrlSpace
某些终端具有Meta或Alt修饰键,当与另一个键组合时,该键会发送相同的字符,但设置了第 8 位(例如Meta+ A(不带Shift)在 0x61 时发送字节 0xE1 a
)。而其他一些(现在更常见)发送^[
字符后跟本来可以发送的字符或字符序列Meta(例如Meta+A发送^[a
)。
大多数其他功能键通常发送以 (ESC) 开头的字符序列^[
。一个例外是Delete在某些终端上发送 DEL ( ^?
)。
现在,处理键盘输入的终端应用程序在从终端设备接收到字符序列时,想要知道它们对应于哪个按键。如果不同的终端发送不同的序列,怎么办?
这就是$TERM
环境变量发挥作用的地方。该变量由getty
终端仿真器或用户设置,以告诉应用程序它们正在与哪个终端通信。该值是一个短名称,用于唯一标识终端的类型。
例如,现代xterm
终端模拟器会将其设置为xterm-256color
.
然后,这些应用程序能够使用该值查询终端描述数据库,以了解该终端的功能。例如,此类功能可以是:字符序列必须是什么发送到终端启用大胆的文本输出。其他一些可能是应用程序将使用的字符序列收到当您按下该键时从终端Delete。
从历史上看,有两个主要数据库:termcap
并且terminfo
每个数据库都有一组用于查询的 API。如今,terminfo
(更先进的)很普遍并且ncurses
(由@托马斯迪基在过去的几十年里)是一个用于与其交互的通用库(还使用相同的后端公开 termcap 接口)。
现在,可能的集合能力存储在该数据库中是固定的。它在terminfo(5)
手册页中进行了描述。
在按键正面,覆盖的按键数量有限。它仍然是一个很大的列表,包括我们大多数人从未听说过的按键,但它不包括过去和未来每个可能的终端的每个功能键。它涵盖了一些组合键(主要是Shift+ SomeFuncKeys),但不是所有可能的组合(例如Ctrl+ Shift+ Up)。
在 GNU 系统上,请参阅:
man 5 terminfo | grep -Po '^\s*\Kkey_.*'
对于列表。
现在,要从 shell 查询terminfo
数据库,有 3 个主要命令ncurses
:
toe
:列出数据库中的终端tput
:打印原始功能(通常用于发送转义序列,例如tput bold
启动大胆的模式)。infocmp
:从数据库中检索完整条目或比较它们。
在这里,后者对于找出哪个终端键可以发送给定序列非常有用:输出标识符存储在(因此您的终端)infocmp -xL1
中的终端的所有已知功能,每行并带有ong(更具描述性)功能名称。所以:$TERM
1
L
$ infocmp -xL1 | grep key_
key_b2=\EOE,
key_backspace=\177,
key_btab=\E[Z,
key_dc=\E[3~,
key_down=\EOB,
key_end=\EOF,
key_enter=\EOM,
[...]
为您提供所有已知键的所有序列。
在我的xterm
终端上,我看到:
key_sright=\E[1;2C,
key_sleft=\E[1;2D,
例如。
shell还在其特殊关联数组zsh
中公开当前终端的功能(在模块中,当您访问该变量时自动加载)。因此,获取信息的另一种方法是:$terminfo
zsh/terminfo
$ key=$'\e[1;2D'
$ echo ${(k)terminfo[(Re)$key]}
kLFT
(这就是短的terminfo 名称在那里)。
terminfo 数据库没有列出发送到我的终端的任何密钥,但如果我输入+或+或+ +例如,^[^?
我会得到该序列。Esc Ctrl?Ctrl[ ?AltCtrl?
也许您的终端^?
在 上发送Delete,那么您也可能在Meta+上收到它Delete。
^X^U
Ctrl将在+ X Ctrl+上发送U,我无法想象终端会有一个功能键发送该功能,但请注意,许多终端模拟器允许将任何字符序列绑定到任何键或键组合。
1 对于许多终端有一个额外的警告,因为终端可以在进入时为某些功能键发送不同的序列。键盘应用模式以及何时不。在这种情况下,terminfo 条目描述了键盘应用模式。应用程序可以通过发送与该功能相对应的序列将终端置于该模式smkx
。
答案4
巴什
$ bind -p | grep -F '[3;5~'
"\e[3;5~": delete-char