与 TikZ 尝试使用未知键作为键的值的方式类似color
,我想将未知键解释为我自己的一个键的值decoration
(不要与 TikZ 中同名的键混淆),使用 编写expl3
。
我天真地尝试使用
\usepackage{expl3}
\usepackage{xparse}
\ExplSyntaxOn
\keys_define:nn { mymodule } {
decoration .tl_set:N = \l_mymodule_decoration_tl ,
unknown .code:n = {
\tl_set:NV \l_mymodule_decoration_tl \l_keys_key_tl }
}
\NewDocumentCommand \mymathmacro { O{} m } {
\mymodule_mathmacro:nn {#1} {#2}
}
\cs_new:Npn \mymodule_mathmacro:nn #1#2 {
\keys_set:nn { mymodule } {#1}
#2 \tl_use:N \l_mymodule_decoration_tl
}
\ExplSyntaxOff
这种方法效果很好,只是我有时会给出未知的键^2
,例如$\mymathmacro[^2]{x}$
,希望修饰符为上标2
。但实际上,我得到的修饰符是一个^
字符,后面跟着2
。
假设问题是 catcode 分配,我现在正在使用
\usepackage{expl3}
\usepackage{xparse}
\ExplSyntaxOn
\cs_generate_variant:Nn \tl_set_rescan:Nnn { NnV }
\keys_define:nn { mymodule } {
decoration .tl_set:N = \l_mymodule_decoration_tl ,
unknown .code:n = {
\tl_set_rescan:NnV \l_mymodule_decoration_tl
{ \char_set_catcode_math_subscript:N _
\char_set_catcode_math_superscript:N ^ }
\l_keys_key_tl
}
}
...
\ExplSyntaxOff
到目前为止,这种方法效果很好,但我的问题是:我怎么知道我没有错过重要的 catcode 分配?我真正想要的是扫描未知密钥,就像将其直接作为密钥的值赋值一样decoration
。
另外,我听说应该避免使用 和 堂兄弟。除了使用 之外,\tl_rescan:nn
有没有更好的方法来编写 代码?unknown
\tl_set_rescan:NnV
答案1
我认为你误用了键值系统。存储\l_keys_key_tl
在键名,不是值,因此它被规范化为字符串;引用文档(第十九部分第四节末尾),
该信息存储在
\l_keys_key_tl
,并将由 处理\tl_to_str:n
。
因此,这种行为是预料之中的,我认为你这样说不会有什么好处
$\mymathmacro[^2]{x}$
代替
$\mymathmacro[decoration=^2]{x}$
对于前一种语法,只需使用标准可选参数,而不是键值系统。命令应该将键值列表作为参数或将要使用的标记列表。同时存在这两种可能性会造成混淆。
如果你确实坚持使用键名作为值,你可以这样做
\keys_define:nn { mymodule } {
decoration .tl_set:N = \l_mymodule_decoration_tl ,
unknown .code:n =
{
\tl_set_rescan:NnV \l_mymodule_decoration_tl {} \l_keys_key_tl
},
}
没有必要在 的第二个参数中指定任何类别代码更改\tl_set_rescan:NnV
,因为当调用该函数时,标记将在正常类别代码制度下重新扫描,因此^
是上标(类别 7),_
是下标(类别 8)。