xeCJK: 如何实现一个控制中西自动间距的特例
xeCJK「在中西之间自动添加 \CJKecglue 的功能」在命令前后 ... <前> \cmd{...} <后> ... 可能判断错误。例如 #392。
大致有两类错误
- 希望自动添加空格,没有添加。能通过手动添加空格或
\space解决。 - 不希望自动添加空格,添加了。手动添加
\mbox{}能解决一些。
一般化的需求是,想(自动)设置某个命令前后的 xeCJK 字符类别(见 texdoc xecjk, pp. 25)。例如,设置 <前字符类别 CJK> \ref{...} <后字符类别 Default>。
在 https://github.com/CTeX-org/ctex-kit/issues/392#issuecomment-441869646 @Liam0205 提到
这个问题以前讨论过。
结论大致是:技术上实现一个 case 不难。但是有很多的 edge case,所以很难保证完备性。因此,暂时不去实现;同时在
xeCJK层面,中文与西文之间建议手工加上空格。
在 https://github.com/CTeX-org/forum/issues/23#issuecomment-482929983 我做了一些瞎试。
从 xeCJK 项目的角度,推荐的做法是什么?
xeCJK 会在字符与边界之间插入一些很小的 \kern 用于判断状态,这是从 CJK 包继承下来的技术。
只有边界是诸如 \relax 等不可展开的 primitive 时,以上机制才会起作用。如果边界是 hbox、glue、whatsit 等 TeX 项目时,这个机制就会失效。
我们可以在边界前后手动保存和恢复 xeCJK 用于判断的 \kern 来部分解决问题。可以参考 GEB.cls 中的 \@@_save_node: 和 \@@_restore_node:
https://github.com/qinglee/GEB/blob/de8719725d4326bccfbd91ab251443aa4dc065a5/GEB.cls#L1568-L1598
用法与 LaTeX 内核的 \@bsphack 和 \@esphack 类似。
字\save \mbox{\restore 1\save}\restore 字