在字符串的大多数使用场景中,我们将字符串理解为包含文本字符—即与缓冲区或文件中 相同类型的字符。但 Lisp 程序偶尔会使用在概念上包含键盘字符的字符串;例如,这些字符串 可能是按键序列或键盘宏定义。然而,出于历史兼容性考量,将键盘字符存储到字符串中是一个 复杂的问题,且并非总能实现。
我们建议新程序避免处理此类复杂性:不要将键盘事件存储在包含控制字符等内容的字符串中,
而是按照 key-valid-p 所识别的标准 Emacs 格式存储。
若你通过 read-key-sequence-vector(或 read-key-sequence)读取按键序列,
或通过 this-command-keys-vector(或 this-command-keys)访问按键序列,
可使用 key-description 将其转换为推荐格式。
这些复杂性源于键盘输入字符可能包含的修饰位。除 Meta 修饰符外,其余所有修饰位均无法 包含在字符串中,且仅在特殊情况下允许使用 Meta 修饰符。
最早的 GNU Emacs 版本将元字符表示为 128 至 255 范围内的编码。彼时,基础字符编码范围为
0 至 127,因此所有键盘字符编码均可存入字符串。许多 Lisp 程序在字符串常量中使用 ‘\M-’
表示元字符,尤其是在 define-key 及类似函数的参数中,且按键序列和事件序列始终
以字符串形式表示。
当我们增加对 127 以上更大基础字符编码及额外修饰位的支持时,不得不修改元字符的表示方式。 如今,用于表示字符中 Meta 修饰符的标志位为: 2**27 而此类数值无法包含在字符串中。
为支持在字符串常量中使用 ‘\M-’ 的程序,对于在字符串中包含特定元字符制定了 特殊规则。以下是将字符串解析为输入字符序列的规则:
read-key-sequence 等构造键盘输入字符字符串的函数会遵循上述规则:当事件无法存入
字符串时,会构造向量(vector)而非字符串。
当你在字符串中使用 ‘\M-’ 读取语法时,会生成 128 至 255 范围内的编码—与修改对应 键盘事件以存入字符串时得到的编码相同。因此,无论元事件以何种方式进入字符串,其在字符串中的 表现都是一致的。
不过,大多数程序最好遵循本节开头的建议,避开这些问题。