一次按键可以返回多少字节?元化密钥应该返回更多吗?

一次按键可以返回多少字节?元化密钥应该返回更多吗?

我一直在用这个工具输入阅读器最近。目前,它只为运行时按下的每个键打印一份报告到标准输出,但我想尽快将其升级到更高的目的,因为它似乎进展顺利。到目前为止,它有一些优点:

  1. 它的所有输出都是单个管道中几个并发进程的结果。
  2. 它会在每次按键按下后立即对其进行解释和报告。
  3. (尽我所知)报告每次按键发送的字节数。

例如,如果我运行它并按顺序按以下键/组合键...

  1. a
  2. CTRL+J
  3. ALT+SPACE
  4. UP
  5. ALT+UP

...它会在终端屏幕上打印以下内容,每次按键打印一行,并且每次按键后立即打印:

 a:97
 \n:10
 \240:160
 \e:27 [:91 A:65
 \e:27 [:91 1:49 ;:59 5:53 A:65

...每次按键中的每个字节都打印得像...

<space>(printable char|\C-escape|\octal-escape):[decimal byte value]

...我认为合适的。

但其中一些让我感到困惑:

  1. 虽然我想我已经尝试了所有的键,并且虽然我已经明确设置stty发送 8 位字符(带cs8ALT+SPACE组合似乎是唯一报告高于 ASCII 十进制 127 的任何组成字节的组合。
    • ALT这特别令人困惑,因为我认为它与修饰符有关飞行(我承认我对这个概念知之甚少)键序列,但在似乎所有其他情况下ALT+只是在序列前面 anykey加上前缀,或者以其他方式巧妙地修改已经转义的序列。ESC
    • 应该ALT 不是将发送的序列移至更高的 128 - 255 范围?
    • (在 derobert 下面的评论中表示读者成功解释并报告了多字节 UTF-8compose序列) 注意:locale报告所有LC_*类别设置为en_US.UTF-8
  2. 另外令人担忧的是,虽然我似乎获得了每次按键的所有字节,但在当前形式下,我的脚本将以8 个字节(现在最大为 32 个字节)来分隔按键。
    • 我之前以为8字节足够了,但是当我考虑其他语言环境中的多字节字符是否可以与我看到的一些较长的转义序列组合时,我现在变得怀疑。因此我扩展了缓冲区 - 但其确定性不如最初提供给我的 8 字节。
    • 单次按键可发送的字节数是否有上限?

答案1

这其实是几个问题。有些处理特定于终端的行为,有些处理组合。

首先,存在一个关于Alt用作修饰符的预期行为的问题。有些人将Alt键(在许多键盘上都有标记)等同于Meta(在终端键盘上很少这样标记)。有些人更进一步,将其等同于转义字符。称其为传统的使用。至少在 xterm 中,关联是可配置的(因为1999 年第 122 号补丁,它有metaSendsEscape资源,并且2007 年第 225 号补丁添加altIsNotMetaaltSendsEscape资源)。其他终端仿真器(也许还有它们的用户)则没有那么灵活。所以有一个习俗这等同于逃逸和元。约定不是标准。

元键的记录行为位于terminfo(5) 手册页:

如果终端有“元键”它充当移位键,设置传输的任何字符的第 8 位,这一事实可以用km。否则,软件将假定第 8 位是奇偶校验位,并且通常会被清除。如果存在用于打开和关闭此“元模式”的字符串,则可以将它们指定为smmrmm

对于元模式关闭的情况没有标准行为(只是约定)。

根据eightBitInputxterm 中的资源,它可能使用元密钥构造高于 128 的代码。例如,在2003 年第 183 号补丁,进行此更改是为了避免使元模式产生非法的 UTF-8:

  • 修改 UTF-8 模式下 everyBitInput 资源的处理,将值转换为 UTF-8。否则,非法的 UTF-8 代码将发送到应用程序(Bram Moolenaar 报告)。

然而,一般来说,您可能与终端和终端一起使用的大多数转义序列传统的键盘返回的转义序列使用 7 位 ASCII。VT100 也不例外;这就是从2002 年第 177 号补丁:

  • 修改解析器表以改进对格式错误的控制序列的检测,使 xterm 的行为更像真正的 DEC 终端(Paul Williams 的补丁)。

也就是说,解析器表是大多组织忽略输入字符的第八位。其他终端可能会忽略该方面,但仍然复制用于 xterm 键盘的转义序列。结果就是你大多请参阅 7 位 ASCII。

我使用 xterm 作为示例,因为您可能看到的大多数行为都是从 xterm 开始的(并且大多数来自 rxvt)。使用 xterm,您可能会遇到几种情况,从一个键中获得相当长的转义序列,例如,

  • 使用modifyOtherKeys模式,将转义序列分配给键盘上的(大多数)键,
  • 使用translations资源,它可以让您发送“任何”字符序列,并且
  • 使用该DECUDK功能发送应用程序定义的字符串(作为十六进制数字序列)。

其他终端(例如 OSX Terminal.app 和 iTerm2)也可以发送用户可配置的字符串。从这个角度来看,密钥发送的字节数没有明确定义的限制。

另一方面,compose 的定义更加明确:它的结果是给定编码中的一个字符(或者可能是多个字符?)。假设只有一个字符。最大值标准UTF-8编码字符的长度是4个字节。当你可以看到用户配置的密钥发送此数据,大多数情况下(由于兼容性和约定)您不会看到两者(转义序列和编码字符)混合在一起。

进一步阅读:

相关内容