你可以通过安装专门的 case table大小写转换表 来自定义大小写转换行为。大小写转换表规定了大写字母与小写字母之间的映射关系,它既影响作用于 Lisp 对象的大小写转换函数(见上一节),也影响作用于缓冲区文本的相关函数(see Case Changes)。每个缓冲区都拥有一个大小写转换表,同时还存在一个标准大小写转换表,用于初始化新建缓冲区的大小写转换表。
大小写转换表是一个字符表(char-table,see 字符表),其子类型为 case-table。该字符表将每个字符映射到对应的小写字符。它额外包含三个槽位,用于存放相关映射表:
大写表:将每个字符映射为对应的大写字符。
规范化表:将一组大小写相关的字符全部映射为该组中的某个特定成员。
等价表:将一组大小写相关的字符中的每个字符,映射为该组中的下一个字符。
在简单场景下,你只需要指定到小写的映射即可,另外三张相关表会由该表自动计算生成。
对于某些语言,大写与小写字母并非一一对应。可能存在两个不同的小写字母对应同一个大写字母。这类情况下,你必须同时指定小写与大写的映射。
部分字符拥有预定义的特殊大小写转换规则,默认情况下会覆盖当前的大小写转换表。这些字符拥有由 Unicode 标准定义的非-nil 字符属性:special-uppercase、special-lowercase 或 special-titlecase(see Character Properties)。典型例子是 U+00DF 拉丁小写字母尖 S ß,默认情况下会被转为大写字符串 "SS",而非 U+1E9E 拉丁大写字母尖 S。若要强制这些字符遵循大小写转换表的转换规则,可将对应 Unicode 属性设为 nil:
(upcase "ß") => "SS" (put-char-code-property ?ß 'special-uppercase nil) (upcase "ß") => "ẞ"
大小写转换表中的 canonicalize 额外槽位,将每个字符映射到一个规范等价字符;任何两个通过大小写转换关联的字符,都拥有相同的规范等价字符。例如,‘a’ 与 ‘A’ 因大小写转换相关,它们应当拥有相同的规范等价字符(可以统一为 ‘a’,也可以统一为 ‘A’)。
equivalences 额外槽位是一张映射表,它对每个等价类(拥有相同规范等价字符的字符集合)进行循环置换。(对于普通 ASCII,它会将 ‘a’ 映射到 ‘A’,‘A’ 映射到 ‘a’,其他等价字符组同理。)
构建大小写转换表时,你可以为 canonicalize 传入 nil,Emacs 会根据小写与大写映射自动填充该槽位。你也可以为 equivalences 传入 nil,Emacs 会根据 canonicalize 自动填充该槽位。在实际使用中的大小写转换表里,这两个组成部分都不为 nil。不要在未指定 canonicalize 的情况下尝试手动指定 equivalences。
以下是用于操作大小写转换表的函数:
若 object 是合法的大小写转换表,该谓词函数返回非-nil。
将 table 设置为标准大小写转换表,后续新建的缓冲区都会使用它。
返回当前的标准大小写转换表。
返回当前缓冲区的大小写转换表。
将当前缓冲区的大小写转换表设为 table。
with-case-table 宏会保存当前大小写转换表,将 table 设为当前表,执行 body 中的表达式,最后恢复原大小写转换表。返回值为 body 中最后一个表达式的值。即使通过 throw 或错误发生异常退出(see 非局部退出),也会恢复原大小写转换表。
部分语言环境会修改 ASCII 字符的大小写转换规则;例如在土耳其语环境中,ASCII 大写字母 I 会被转为土耳其语无点 i (‘ı’)。这会干扰需要标准 ASCII 大小写转换的代码,比如基于 ASCII 的网络协议实现。这种情况下,可以使用 with-case-table 宏并搭配变量 ascii-case-table,它保存了未被修改的 ASCII 字符集大小写转换表。
ASCII 字符集专用的大小写转换表。任何语言环境设置都不应修改它。
下面三个函数是用于定义非-ASCII 字符集包的便利子例程。它们会修改指定的大小写转换表 case-table,同时也会修改标准语法表。See Syntax Tables。通常你会用这些函数来修改标准大小写转换表。
该函数指定一对对应的字母,一个大写字母和一个小写字母。
将字符 l 和 r 设为一对匹配的、大小写无关的分隔符。
将字符 char 设为大小写不变字符,并指定其语法为 syntax。
显示当前缓冲区的大小写转换表内容的描述信息。