为什么“shift-tab”会在终端中导致“Escape”?

为什么“shift-tab”会在终端中导致“Escape”?

我只是偶然注意到这一点。

我使用vireadline模式(运行set -o vibash)所以它特别引人注目;在emacsreadline模式下我认为不会Esc做任何事情,但在vi模式下它退出插入模式(进入正常模式)。

我没有看到Shift-Tab中记录man bash,并且它作为密钥的解释似乎Esc比 更基本bash。可能在阅读线上?

它可以在 Mac OS X 和 Linux 上运行。

我在哪里可以找到此文档?

答案1

Shift+Tab在多个终端上发送这样的转义序列

ESC [ Z

它是在Linux控制台终端中使用的自1995年以来,xterm 的一部分自2002年以来,并用于从那时起模拟其中一个或另一个的终端。

terminfo描述中,这将表示为

kcbt=\E[Z,

kcbt记录在terminfo(5):

key_btab                  kcbt   kB   back-tab key

从解析的角度来看,这和按某个功能键没有区别。 readline 确实有几个编辑键的特殊情况(依赖于 bash 中的 termcap 字符串表)lib/readline/terminal.c),但 termcap"kB"不属于其中。

作为一个额外的复杂性,配置更改开始于2007年这导致 Linux 控制台上的 shift-tab 发送不同的转义序列,即

ESC TAB

这是 2021 年报道的,并对终端数据库进行了修复。这样做给 Emacs 开发人员带来了一些痛苦(请参阅邮件列表线程),其程序确实检查“kB”。但截至 2022 年 5 月,这个问题似乎已得到解决。

无论哪种方式,bash 都会忽略该 termcap 字符串。

当 bash 没有 termcap 信息时,它依赖于.inputrc.如果在任何一个中都找不到匹配项,该ESC(转义)字符将如前所述退出插入模式(毕竟是 vi)。


用于此的转义序列恰好与ECMA-48标准后选项卡控制序列。这也记录在terminfo(5):

   back_tab                    cbt       bt     back tab (P)

对特殊键使用与控制序列相同的转义序列并非完全偶然。硬件终端通常提供本地编辑模式,其中光标移动键将在屏幕上移动光标,而不依赖主机回显特殊键。 ncurses 终端数据库中大约一半的终端描述显示了特殊键和控制序列之间的这种关联:

 439 entries with cbt == kcbt
  73 entries with clear == kclr
 383 entries with cub1 == kcub1
 505 entries with cud1 == kcud1
 885 entries with cuf1 == kcuf1
 868 entries with cuu1 == kcuu1
 174 entries with dch1 == kdch1
 186 entries with dl1 == kdl1
 502 entries with home == khome
  52 entries with ich1 == kich1
 139 entries with il1 == kil1

cub1和的计数cud1低于cuf1和 ,cuu1因为终端描述通常使用 1 个字符的退格键或换行符,而不是 2-3 个字符的控制序列。尽管如此,后选项卡的 439 表明大约四分之一的终端描述使用了这个特定的功能。

Linux 控制台并未首先使用shift-tab 发送后退制表符转义序列。有一些较旧的条目,例如安娜堡以及使用此功能的 AT&T 条目。后者关于位保护器的手册很少,但是美国电话电报公司 610美国电话电报公司 630提供手册。

答案2

看起来它作为 Esc 键的解释比 bash 更基础。可能在阅读线上?

它甚至比那还要低。这是终端在 Unices 和类 Unix 操作系统上工作的基本属性。操作系统将终端 I/O 视为 8 位(甚至 7 位)字符的序列。功能键和扩展键作为多字符转义序列进行传输。

在真实的终端中,这些转义序列是由终端本身的固件生成的。在终端仿真器程序中,终端仿真器将击键数据(通过与键盘对话的任何用户界面接收到的数据,无论是 X Window 系统、USB hid 设备还是 Linux 事件设备)转换为转义序列。

诸如vim各种行编辑库之类的应用程序试图Esc通过(实际上)计时读取转义字符和读取后续字符之间的时间间隔来区分它们与简单的按键操作。如果字符足够快地相继到达,它们将被视为转义序列。

我在哪里可以找到此文档?

输入中转义序列的超时处理记录在手册页中 Z Shell 的 ZLE 的vim下面和中。终端生成转义序列的基本思想已被广泛记录。 :help ttimeoutzshzle

生成的特定转义序列的文档很难获得。许多(现在可能是大多数)终端(特别是模拟终端)使用 DEC VT 终端(当它们处于 Digital 所谓的“ANSI 模式”时)多年来使用的转义序列。 DEC 提供了其终端的文档,您可以在 VT525 程序员信息 doco 第 8 章中找到它明确讨论Shift+编码的内容。Tab

但是:如果您在 Linux 或 BSD 上使用内核虚拟终端,其中终端仿真器程序是操作系统内核的一部分,则在涉及到以下内容时,对 DEC VT 约定的遵守情况明显不稳定:输入控制序列。部分原因是 FreeBSD 等操作系统实际上默认遵守 SCO XENIX 虚拟终端约定。结果是 DEC VT 和 SCO XENIX 的奇怪混合体,与任何真实的终端没有对应关系。

这种混合不仅仅是输入和输出终端仿真之间的不匹配。现代配置试图覆盖输入控制序列的 SCO XENIX 默认值,但只是部分地这样做,这一事实进一步加剧了这一情况。因此,例如:在最近的 FreeBSD 上,我们可以发现 是F6DEC VT 控制序列CSI 1 7 ~,而不是编译到内核终端仿真器中的 SCO XENIX 序列,但是Shift+F6仍然是编译到 SCO XENIX 控制序列CSI d而不是 DEC VT控制序列CSI 1 7 ; 2 ~

而这些根本不在 FreeBSD doco 中。

进一步阅读

相关内容