将可选参数传递给同样带有可选参数的命令

将可选参数传递给同样带有可选参数的命令

在过去的几天里,我一直在努力实现以下目标,但无法找到解决方案。

我有以下最小工作示例:

\documentclass{article}

\usepackage{xkeyval}
\usepackage{amssymb, amsmath}
\usepackage{xparse}
\usepackage{etoolbox}

\makeatletter
\define@cmdkey [Notation] {nom} {A} {}
\define@cmdkey [Notation] {nom} {B} {}
\presetkeys [Notation] {nom} {A={},B={}}{}
\NewDocumentCommand{\nom}{ m O{} }{%
    \setkeys[Notation]{nom}{#2}%
        \ifdefempty{\cmdNotation@nom@A}{% Descriptor section
            \ifdefempty{\cmdNotation@nom@B}{% 
                e-\def\subscript{}
            }{%
                f-\def\subscript{\mathtt{\cmdNotation@nom@B}}%
            }%
        }{%
            \ifdefempty{\cmdNotation@nom@B}{%
                g-\def\subscript{\mathtt{\cmdNotation@nom@A}}%
            }{%
                h-\def\subscript{\mathtt{\cmdNotation@nom@A,\cmdNotation@nom@B}}%
            }%
        }%  
    \mathcal{#1}_{\subscript}
}% 
\makeatother


\makeatletter
\define@cmdkey [Notation] {test} {of} {}
\define@cmdkey [Notation] {test} {wrt} {}
\presetkeys [Notation] {test} {of={},wrt={}}{}
\NewDocumentCommand{\test}{ m O{} }{%
    \setkeys[Notation]{test}{#2}%
\nom{#1}[A=\cmdNotation@test@of, B=\cmdNotation@test@wrt]
}%          
\makeatother

\begin{document}

\begin{align}
\nom{K}[A=A, B=B]\\
\nom{K}[A=A] \\
\nom{K}[B=B] \\
\nom{K} \\
\test{K}[of=A, wrt=B] \\
\test{K}[of=A] \\
\test{K}[wrt=B] \\
\test{K}
\end{align}

\end{document}

基本上,当我在 \test 内部调用 \nom 并且 test 的可选输入为空时,它们会在 \nom 中作为非空参数接收。

在此处输入图片描述

到目前为止,我发现的唯一解决方案如下:

\makeatletter
\define@cmdkey [Notation] {test} {of} {}
\define@cmdkey [Notation] {test} {wrt} {}
\presetkeys [Notation] {test} {of={},wrt={}}{}
\NewDocumentCommand{\test}{ m O{} }{%
    \setkeys[Notation]{test}{#2}%
            \ifdefempty{\cmdNotation@test@wrt}{%
                \ifdefempty{\cmdNotation@test@of}{%  
                    \nom{#1}[] 
                }{%
                    \nom{#1}[B=\cmdNotation@test@of] 
                }%
            }{%
                \ifdefempty{\cmdNotation@test@of}{%         
                    \nom{#1}[A=\cmdNotation@test@wrt] 
                }{%
                    \nom{#1}[A=\cmdNotation@test@wrt, B=\cmdNotation@test@of] 
                }%
            }% 
}%          
\makeatother

在此处输入图片描述

但这是不可行的,因为在我的实际实现中,\nom 和 \test 有超过 10 个输入,我无法为每个输入组合创建检查。此外,我还有 10 个类似于 \test 的其他函数在内部调用 \nom。

希望您能帮助我。提前致谢!

编辑:

正如 @Gaussler 和 @egreg 所建议的,使用列表原则上是可行的。但我偶然发现有些情况传递的参数不是列表的一部分,或者需要另一种形式的评估而不是简单的逗号分隔(参见蓝色圆圈)。例如,第一种情况下的 \dot、\hat 是两个可选修饰符 \mod 和 \modd,或者 K 和 L 是文本描述符的一部分,其中两个/一个/没有输入可以存在。

在此处输入图片描述

对于每个 \test_i i = 1:n 的情况,我可以使用不同的输入组合并将它们传递给 \nom 以根据我的需要生成不同的方程式。

在此处输入图片描述

答案1

我不确定为什么要这样间接。无论如何,使用 expl3 做任何事情都更容易。请注意分组,这样在同一级别设置的键就不会互相影响。

\test命令将不是使用可选参数进行调用\nom,因为它已经设置了选项。

\documentclass{article}

\usepackage{amssymb, amsmath}
\usepackage{xparse}

\ExplSyntaxOn

\keys_define:nn { notation/nom }
 {
  A .tl_set:N = \l_wdsgn_notation_A_tl,
  B .tl_set:N = \l_wdsgn_notation_B_tl,
  A .initial:n = {},
  B .initial:n = {},
 }

\keys_define:nn { notation/test }
 {
  of .code:n = \keys_set:nn { notation/nom } { A=#1 },
  wrt .code:n = \keys_set:nn { notation/nom } { B=#1 },
 }

\NewDocumentCommand{\nom}{ m O{} }
 {
  \group_begin:
  \wdsgn_notation_nom:nn { #1 } { #2 }
  \group_end:
 }

\clist_new:N \l__wdsgn_notation_subscript_clist

\cs_new:Nn \wdsgn_notation_nom:nn
 {
  \keys_set:nn { notation/nom } { #2 }
  \tl_if_empty:NTF \l_wdsgn_notation_A_tl
   { % A is empty
    \tl_if_empty:NTF \l_wdsgn_notation_B_tl { e- } { f- }
   }
   { % A is not empty
    \tl_if_empty:NTF \l_wdsgn_notation_B_tl { g- } { h- }
   }
  \mathcal{#1}
  \clist_put_right:NV \l__wdsgn_notation_subscript_clist \l_wdsgn_notation_A_tl
  \clist_put_right:NV \l__wdsgn_notation_subscript_clist \l_wdsgn_notation_B_tl
  \clist_if_empty:NF \l__wdsgn_notation_subscript_clist
   { % here we exploit the fact that \clist_use:Nn disregards empty items
    \sb{\mathtt{\clist_use:Nn \l__wdsgn_notation_subscript_clist {,}}}
   }
 }

\NewDocumentCommand{\test}{ m O{} }
 {
  \group_begin:
  \keys_set:nn { notation/test } { #2 }
  \nom{#1}
  \group_end:
 }

\ExplSyntaxOff

\begin{document}

\begin{align}
\nom{K}[A=A, B=B]\\
\nom{K}[A=A] \\
\nom{K}[B=B] \\
\nom{K} \\
\test{K}[of=A, wrt=B] \\
\test{K}[of=A] \\
\test{K}[wrt=B] \\
\test{K}
\end{align}

\end{document}

在此处输入图片描述

笔记。感谢高斯勒指出需要修复的问题。

答案2

因为无聊,我提出了另一种解决方案。(除此之外,请允许我评论一下,你的语法对我来说似乎非常违反直觉。你确定这真的是你想要输入的方式吗?)

\documentclass{article}

\usepackage{semantex}

\NewSymbolClass\nom[
    data provide=data A,
    data provide=data B,
    parse options={
        command=\mathcal,
        inner return,
        if blank TF={\SemantexDataGetExpNot{data A}}{
            if blank TF={\SemantexDataGetExpNot{data B}}
            {
                symbol put left={e-},
            }
            {
                symbol put left={f-},
                set keys x={
                    sep lower={\SemantexExpNot\mathtt{\SemantexDataGetExpNot{data B}}},
                },
            },
        }
        {
            if blank TF={\SemantexDataGetExpNot{data B}}
            {
                symbol put left={g-},
                set keys x={
                    sep lower={\SemantexExpNot\mathtt{\SemantexDataGetExpNot{data A}}},
                },
            }
            {
                symbol put left={h-},
                set keys x={
                    sep lower={\SemantexExpNot\mathtt{\SemantexDataGetExpNot{data A}}},
                    sep lower={\SemantexExpNot\mathtt{\SemantexDataGetExpNot{data B}}},
                },
            },
        },
    },
    define keys[1]={
        {A}{ data set={data A}{#1} },
        {B}{ data set={data B}{#1} },
    },
]

\NewSymbolClass\test[
    parent=\nom,
    define keys[1]={
        {of}{ A={#1} },
        {wrt}{ B={#1} },
    },
]

\begin{document}

\begin{align}
    \nom{K}[A=A, B=B]\\
    \nom{K}[A=A] \\
    \nom{K}[B=B] \\
    \nom{K} \\
    \test{K}[of=A, wrt=B] \\
    \test{K}[of=A] \\
    \test{K}[wrt=B] \\
    \test{K}
\end{align}

\end{document}

在此处输入图片描述


我不太清楚你更新后的答案是什么意思。但semantex也可以编程来处理这种情况。请原谅我在下面使用了奇怪的命令名称,但我不太清楚你的符号到底是什么意思:

\documentclass{article}

\usepackage{semantex}

\NewVariableClass\MyVar[
    output=\MyVar,
]

% First a few variables; the "v" stands for variable:

\NewObject\MyVar\vh{h}
\NewObject\MyVar\vg{g}
\NewObject\MyVar\vf{f}
\NewObject\MyVar\ve{e}
\NewObject\MyVar\vK{K}
\NewObject\MyVar\vL{L}

% Feel free to give the following more descriptive names:

\NewObject\MyVar\guid{\mathrm{guid}} % could also use \operatorname, depending on what "guid" is

\NewObject\MyVar\scriptK{\mathcal{K}}
\NewObject\MyVar\ttA{\mathtt{A}}
\NewObject\MyVar\ttB{\mathtt{B}}
\NewObject\MyVar\ttC{\mathtt{C}}
\NewObject\MyVar\ttD{\mathtt{D}}
\NewObject\MyVar\ttE{\mathtt{E}}
\NewObject\MyVar\ttF{\mathtt{F}}
\NewObject\MyVar\ttG{\mathtt{G}}
\NewObject\MyVar\ttH{\mathtt{H}}
\NewObject\MyVar\ttX{\mathtt{X}}
\NewObject\MyVar\ttY{\mathtt{Y}}

\NewVariableClass\WeirdConstruction[
    parent=\MyVar,
    data provide=data A,
    data provide=data B,
    data provide=data C,
    data provide=data D,
    data provide=data E,
    data provide=data F,
    data provide=data G,
    data provide=data H,
    define keys={
        {mod}{ command=\hat },
        {modd}{ command=\dot },
    },
    define keys[1]={
        {A}{ data set={data A}{#1} },
        {B}{ data set={data B}{#1} },
        {C}{ data set={data C}{#1} },
        {D}{ data set={data D}{#1} },
        {E}{ data set={data E}{#1} },
        {F}{ data set={data F}{#1} },
        {G}{ data set={data G}{#1} },
        {H}{ data set={data H}{#1} },
        {description}{
            parse,
            if blank TF={\SemantexDataGetExpNot{lower}}
            {
                lower={#1},
            }
            {
                lower={_\bgroup #1},
                post lower=\egroup,
            },
        },
    },
    parse options={
        set keys x={
            sep upper left=\SemantexDataGetExpNot{data B},
            sep upper left=\SemantexDataGetExpNot{data A},
            sep lower left=\SemantexDataGetExpNot{data D},
            sep lower left=\SemantexDataGetExpNot{data C},
            sep upper=\SemantexDataGetExpNot{data E},
            sep upper=\SemantexDataGetExpNot{data F},
            sep lower=\SemantexDataGetExpNot{data G},
            sep lower=\SemantexDataGetExpNot{data H},
        },
    },
]

\NewObject\WeirdConstruction\ThetaConstruction{\Theta}
\NewObject\WeirdConstruction\aConstruction{\mathbf{a}}

\begin{document}

\[
    \ThetaConstruction[
        A=\ttA, B=\ttB,
        C=\ttC, D=\ttD,
        E=\ttE, F=\ttF,
        G=\ttG, H=\ttH,
        mod, modd,
        description=\vK,
        description=\vL,
    ]
\]

\[
    \aConstruction[
        A=\ttC,C=\ttX,
        mod, modd,
        description=\guid,
        description=3,
    ]
\]

\end{document}

在此处输入图片描述

相关内容