![是否可以定义接受不同参数类型的命令?](https://linux22.com/image/467316/%E6%98%AF%E5%90%A6%E5%8F%AF%E4%BB%A5%E5%AE%9A%E4%B9%89%E6%8E%A5%E5%8F%97%E4%B8%8D%E5%90%8C%E5%8F%82%E6%95%B0%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%91%BD%E4%BB%A4%EF%BC%9F.png)
这实际上是一个更普遍的问题,但由于几乎普遍要求使用 MWE,因此请考虑 David Carlisle 的代码
\documentclass{article}
\usepackage{fontspec}
\usepackage{nopageno}
\newfontfamily\mathematica[NFSSFamily=mathematica]{STIX Two Math}%
\DeclareSymbolFont{wm}{TU}{mathematica}{m}{n}
\DeclareSymbolFont{wmb}{TU}{mathematica}{b}{n}
\ExplSyntaxOn
\Umathcode"03B1 = 0 \symwm "003B1
\Umathcode"03B2 = 0 \symwm "003B2
\NewDocumentCommand{\mapcommands}{mm}
{
\seq_set_from_clist:Nn\l_cmds{#1}
\seq_set_from_clist:Nn\l_chars{#2}
\seq_map_pairwise_function:NNN\l_cmds\l_chars\mapcommandfunction
}
\NewDocumentCommand{\mapcommandfunction}{mm}{\cs_set:Npx #1 {\codepoint_generate:nn{#2}{11}}}
\mapcommands{\alphatwo,\beta}{"03B1,"03B2}
\ExplSyntaxOff
\show\alphatwo
\begin{document}
$$\alphatwo\beta$$
\end{document}
他在回答我之前的一个问题时说道:https://tex.stackexchange.com/a/691806/224317。要使此代码完成我希望它执行的所有操作,需要调用一个配套函数,将\mapcodes
标准代码(例如"03B1
希腊字母)映射到特定字体中的插槽位置。唯一的本质区别是它需要包含第三个参数,其中包含字体系列和大概需要在第一个参数中接受不同的类型说明符。egreg 在此处提供了一个可用的版本:https://tex.stackexchange.com/a/691747/224317。现在,我们来谈谈问题的棘手部分和要点。
我希望这两个函数都能接受单个参数以及逗号分隔的列表(如果适用)。只要列表以“内联”形式提供,我认为它们就可以正常工作。我知道
\mapcommands{\alphatwo,\beta}{"03B1,"03B2}
\mapcommands{\gamma}{"03B3}
例如,这不会造成任何问题。我假设第二种用法被视为长度为 1 的列表。但我还希望能够使用以下形式的命令创建和命名列表
\DeclareCommandList{GreekCommands}{\alpha,\beta,\gamma,\delta}
\DeclareCodeList{GreekCodes}{"03B1,"03B2,"03B3,"03B4}
类似于\defineblock
egreg 的答案,然后按如下方式传递它们:
\mapcommands{GreekCommands}{GreekCodes}
我已经尝试过了,但作为新手expl3
对底层 TeX 扩展机制的理解还不够深入,因此我还没有成功。我猜想要么 (a) 有一种方法可以采用广义参数,然后确定其性质,针对每种情况做一些适用的事情,要么 (b) 有一种方法可以做一些与函数重载等同的事情。它出现expl3
可能会提供类似的东西,但软件包中也有变体,但我不确定。因此l3expan
,虽然我想解决这个特定问题,但我也想了解这两种调用机制的一般区别、如何处理它们、故障排除技巧等。
答案1
以下将这两个宏及其对它们的支持添加到您的 MWE。
通过引入两个可选星号来添加支持,如果给出任一星号,则下一个强制参数将被视为命名列表输入,而不是逗号分隔的列表。
我们也可以不要求星星,而是检查是否存在这样的列表,如果您需要帮助,只需发表评论。
\documentclass{article}
\usepackage{fontspec}
\usepackage{nopageno}
\newfontfamily\mathematica[NFSSFamily=mathematica]{STIX Two Math}%
\DeclareSymbolFont{wm}{TU}{mathematica}{m}{n}
\DeclareSymbolFont{wmb}{TU}{mathematica}{b}{n}
\ExplSyntaxOn
\Umathcode"03B1 = 0 \symwm "003B1
\Umathcode"03B2 = 0 \symwm "003B2
\Umathcode"03B3 = 0 \symwm "003B3
\Umathcode"03B4 = 0 \symwm "003B4
\msg_new:nnn { mike-pugh } { unknown-cmd-list }
{ The~ named~ cmd~ list~ `#1'~ is~ unknown.~ Make~ sure~ you~ defined~ it. }
\msg_new:nnn { mike-pugh } { unknown-char-list }
{ The~ named~ char~ list~ `#1'~ is~ unknown.~ Make~ sure~ you~ defined~ it. }
\seq_new:N \l__mikepugh_cmds_seq
\seq_new:N \l__mikepugh_chars_seq
\NewDocumentCommand \mapcommands { s m s m }
{
\IfBooleanTF {#1}
{
\seq_if_exist:cTF { l__mikepugh_cmds_ \tl_to_str:n {#2} _seq }
{
\seq_set_eq:Nc \l__mikepugh_cmds_seq
{ l__mikepugh_cmds_ \tl_to_str:n {#2} _seq }
}
{ \msg_error:nnn { mike-pugh } { unknown-cmd-list } {#2} }
}
{ \seq_set_from_clist:Nn \l__mikepugh_cmds_seq {#2} }
\IfBooleanTF {#3}
{
\seq_if_exist:cTF { l__mikepugh_chars_ \tl_to_str:n {#4} _seq }
{
\seq_set_eq:Nc \l__mikepugh_chars_seq
{ l__mikepugh_chars_ \tl_to_str:n {#4} _seq }
}
{ \msg_error:nnn { mike-pugh } { unknown-char-list } {#2} }
}
{ \seq_set_from_clist:Nn \l__mikepugh_chars_seq {#4} }
\seq_map_pairwise_function:NNN
\l__mikepugh_cmds_seq \l__mikepugh_chars_seq \mapcommandfunction
}
\NewDocumentCommand \DeclareCommandList { m m }
{
\seq_clear_new:c { l__mikepugh_cmds_ \tl_to_str:n {#1} _seq }
\seq_set_from_clist:cn { l__mikepugh_cmds_ \tl_to_str:n {#1} _seq } {#2}
}
\NewDocumentCommand \DeclareCodeList { m m }
{
\seq_clear_new:c { l__mikepugh_chars_ \tl_to_str:n {#1} _seq }
\seq_set_from_clist:cn { l__mikepugh_chars_ \tl_to_str:n {#1} _seq } {#2}
}
\NewDocumentCommand \mapcommandfunction { m m }
{ \cs_set:Npx #1 { \codepoint_generate:nn {#2} {11} } }
\mapcommands{\alphatwo,\beta}{"03B1,"03B2}
\DeclareCommandList{GreekCommands}{\alpha,\gamma,\delta}
\DeclareCodeList{GreekCodes}{"03B1,"03B3,"03B4}
\mapcommands*{GreekCommands}*{GreekCodes}
\ExplSyntaxOff
\show\alphatwo
\show\delta
\begin{document}
\[\alphatwo\beta\delta\]
\end{document}