如何在 l3keys 中定义新的按键属性

如何在 l3keys 中定义新的按键属性

相关元问题


从中interface3.pdf我们可以看到提供了几个关键属性,l3keys例如.code:n,,.tl_set:N.usage:n但我不知道如何定义一个新的关键属性。

此时我的代码是这样的:

\keys_define:nn {test}
  {
    keya .code:n = \somemacro {#1},
    keyb .code:n = \othermacro {#1},
  }

现在我想定义一个新的键属性,.mycode:n以便

\keys_define:nn {test}
  {
    keya .mycode:n = \somemacro {#1},
    keyb .mycode:n = \othermacro {#1},
  }

是相同的

\keys_define:nn {test}
  {
    keya .code:n = \MyFunction \somemacro {#1},
    keyb .code:n = \MyFunction \othermacro {#1},
  }

我该怎么做? 其中包括一个最小示例:

\documentclass{article}
\begin{document}

\newcommand\somemacro[1]{\detokenize{#1}}
\newcommand\othermacro[1]{\detokenize{#1}}
\newcommand\MyFunction[2]{\detokenize{#1,#2}}

\ExplSyntaxOn

\keys_define:nn {test}
  {
    keya .code:n = \somemacro {#1},
    keyb .code:n = \othermacro {#1},
  }
\keys_set:nn {test} {keya = a, keyb = b}

\keys_define:nn {test}
  {
    keya .code:n = \MyFunction \somemacro {#1},
    keyb .code:n = \MyFunction \othermacro {#1},
  }
\keys_set:nn {test} {keya = a, keyb = b}

\keys_define:nn {test}
  {
    keya .mycode:n = \somemacro {#1},
    keyb .mycode:n = \othermacro {#1},
  }
\keys_set:nn {test} {keya = a, keyb = b}

\ExplSyntaxOff

\end{document}

问题背景

最近我发现tcolorbox了一个有趣的IfEmptyTF键,你可以用它写

IfEmptyTF = {⟨token list⟩}{key=val1}{key=val2}

我决定tabularray应该具有类似的功能,并且可以使界面对用户来说更自然、更强大:

key = \tlIfEmptyTF{⟨token list⟩}{\prgReturn{val1}}{\prgReturn{val2}}

在哪里\tlIfEmptyTF函数来自functional包。也就是说,用户可以functional在值中使用包中的所有函数,并tabularray应将其替换为其返回值。并且此功能仅在以下情况下才应启用:functional用户加载库时才启用此功能。

为了实现这个新功能,同时保持代码更改最少,我认为在中定义一个新的关键属性是最好的解决方案l3keys

答案1

没有官方方法来添加新属性。由于属性可用于所有密钥创建,因此构成语言的一部分,因此添加新属性需要仔细考虑。(团队确实详细讨论了如何最好地为新选项处理程序添加“2e 友好”版本:最终我们确实例如 .if同一命名空间中的别名.legacy_if_set:n,但这并不是一个简单的决定。)

就其本身而言,.code:n应谨慎使用:大多数键最好创建为设置变量,然后在运行时由代码查询。如果您想用多个键做类似的事情,我希望使用内部函数

\cs_new_protected:Npn \__mypkg_key_processor:nn #1#2
  {
    % Payload
  }
\keys_define:nn { mypkg }
  {
    keya-a .code:n = \__mypkg_key_processor:nn { a } {#1} ,
    keya-b .code:n = \__mypkg_key_processor:nn { b } {#1} ,
  }

该团队目前正在考虑添加“后操作”属性。这可能会解决更容易允许“设置变量然后处理”的方法。(该问题专门出现在发布调试数据时,因此可能会添加更集中的属性。)

答案2

这显然是极其糟糕的作风(换句话说,不要这样做),但我认为这是实现你想要的目标的唯一方法。

\documentclass{article}
\begin{document}

\newcommand\somemacro[1]{\detokenize{#1}}
\newcommand\othermacro[1]{\detokenize{#1}}
\newcommand\MyFunction[2]{\detokenize{#1,#2}}

\ExplSyntaxOn

\cs_new_protected:cpn { key~prop~>~.mycode:n } #1
  { \__keys_cmd_set:nn \l_keys_path_str { \MyFunction #1 } }

\keys_define:nn {test}
  {
    keya .code:n = \somemacro {#1},
    keyb .code:n = \othermacro {#1},
  }
\keys_set:nn {test} {keya = a, keyb = b}

\keys_define:nn {test}
  {
    keya .code:n = \MyFunction \somemacro {#1},
    keyb .code:n = \MyFunction \othermacro {#1},
  }
\keys_set:nn {test} {keya = a, keyb = b}

\keys_define:nn {test}
  {
    keya .mycode:n = \somemacro {#1},
    keyb .mycode:n = \othermacro {#1},
  }
\keys_set:nn {test} {keya = a, keyb = b}

\ExplSyntaxOff

\end{document}

答案3

似乎 l3keys 目前不支持添加新的密钥处理程序。

如果您喜欢比 Joseph Wright 建议的代码更麻烦的代码:

如何使用\mymodule_mycode:nw{keya}...,扩展为的宏并对的第二个参数keya.code=\MyFunction...,进行一些e扩展?\keys_define:nn

\ExplSyntaxOn
\cs_new:Npn \mymodule_mycode:nw #1 {\__mymodule_mycode:nw {#1}{}} % prevent brace-removal by ensuring a leading {} with delimited #2
\cs_new:Npn \__mymodule_mycode:nw #1#2, {\exp_not:n {#1.code = \MyFunction } \exp_not:n \exp_after:wN {\use_none:n #2,}}

\exp_args:Nne \keys_define:nn {test}
  {
    \mymodule_mycode:nw{keya} = \somemacro {#1},
    \mymodule_mycode:nw{keyb} = \othermacro {#1},
    % wrap things that shall not be affected by e-expansion into \exp_not:n
    % ...
  }
\ExplSyntaxOff

如果不是 l3keys 而是 pgfkeys,您可以/.mycode通过将内容放入路径来实现密钥处理程序/handlers/

\documentclass{article}
\usepackage{pgfkeys}

\pgfkeys{%
  /handlers/.mycode/.style={\pgfkeyscurrentpath/.code={\MyFunction #1}},
  /MyPath/Worldkey/.mycode={World and #1!},
  /MyPath/Moonkey/.mycode={Moon and #1!}
}
\def\MyFunction{Hello, }

\begin{document}

\pgfkeys{/MyPath/Worldkey={You}}

\pgfkeys{/MyPath/Moonkey={You}}

\end{document}

在此处输入图片描述

相关内容