嵌套 keyval 正确解析

嵌套 keyval 正确解析

我有两组 keyval 参数和两个函数,我希望它们的行为像下面的玩具 MWE 一样。

\documentclass{article}

\usepackage{xkeyval}
\usepackage{xparse}

\makeatletter
\define@key{A}{a1}{\def\a@aOne{#1}}
\define@key{A}{a2}{\def\a@aTwo{#1}}

\DeclareDocumentCommand{\A}{ m }{%
    \begingroup
        \setkeys{A}{a1={}, a2={}, #1}
        \fbox{$a_1$ = \a@aOne, $a_2$ = \a@aTwo}
    \endgroup
}

\define@key{B}{left}{\def\b@left{#1}}
\define@key{B}{right}{\def\b@right{#1}}

\DeclareDocumentCommand{\B}{ m }{%
    \begingroup
        \setkeys{B}{left={}, right={}, #1}
        \A{\b@left} \A{\b@right}
    \endgroup
}

\makeatother


\begin{document}

    \A{a1=1, a2=2}

    \B{left={a1=1, a2=2}, right={a1=1, a2=2}}

\end{document}

但是我收到错误! Package xkeyval Error: 'a1=1, a2=2' undefined in families 'A' at line with using commandB`。

看完之后这个问题我理解为什么会发生这种情况,但无法将给出的建议应用于我的情况。在这种情况下如何进行正确的解析?

谢谢。

答案1

对于这种情况,解决方案就是使用 扩展\b@...\expandafter,以便将其扩展值传递给\A。因此,将您的\B定义更改为以下内容:

\DeclareDocumentCommand{\B}{ m }{%
    \begingroup
        \setkeys{B}{left={}, right={}, #1}%
        \expandafter\A\expandafter{\b@left}%
        \expandafter\A\expandafter{\b@right}%
    \endgroup
}

完整更新的示例(%在行尾添加了一些额外的 s 以防止输出中出现多余的空格):

\documentclass{article}

\usepackage{xkeyval}
\usepackage{xparse}

\makeatletter
\define@key{A}{a1}{\def\a@aOne{#1}}
\define@key{A}{a2}{\def\a@aTwo{#1}}

\DeclareDocumentCommand{\A}{ m }{%
    \begingroup
        \setkeys{A}{a1={}, a2={}, #1}%
        \fbox{$a_1$ = \a@aOne, $a_2$ = \a@aTwo}%
    \endgroup
}

\define@key{B}{left}{\def\b@left{#1}}
\define@key{B}{right}{\def\b@right{#1}}

\DeclareDocumentCommand{\B}{ m }{%
    \begingroup
        \setkeys{B}{left={}, right={}, #1}%
        \expandafter\A\expandafter{\b@left}%
        \expandafter\A\expandafter{\b@right}%
    \endgroup
}

\makeatother

\begin{document}

    \A{a1=1, a2=2}

    \B{left={a1=1, a2=2}, right={a1=3, a2=4}}

\end{document}

输出

在此处输入图片描述

答案2

我会直接选择l3keys

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\evalA}{m}
 {
  \robur_eval_a:n { #1 }
 }
\NewDocumentCommand{\evalB}{m}
 {
  \robur_eval_b:n { #1 }
 }

\keys_define:nn { robur/A }
 {
  a1 .tl_set:N = \l__robur_A_aone_tl,
  a2 .tl_set:N = \l__robur_A_atwo_tl,
 }
\keys_define:nn { robur/B }
 {
  left .tl_set:N = \l__robur_B_left_tl,
  right .tl_set:N = \l__robur_B_right_tl,
 }

\cs_new_protected:Nn \robur_eval_a:n
 {
  \group_begin:
  \keys_set:nn { robur/A } { a1=, a2=, #1 }
  \fbox{$a\sb{1}=\l__robur_A_aone_tl$,~$a\sb{2}=\l__robur_A_atwo_tl$}
  \group_end:
 }
\cs_generate_variant:Nn \robur_eval_a:n { V }

\cs_new_protected:Nn \robur_eval_b:n
 {
  \group_begin:
  \keys_set:nn { robur/B } { left=, right=, #1 }
  \robur_eval_a:V \l__robur_B_left_tl
  \robur_eval_a:V \l__robur_B_right_tl
  \group_end:
}
\ExplSyntaxOff

\begin{document}

\evalA{a1=1, a2=2}

\evalB{left={a1=1, a2=2}, right={a1=3, a2=4}}

\end{document}

在此处输入图片描述

\expandafter,由于V变体:\robur_eval_a:V <tl variable>

\robur_eval_a:n { <contents of the tl variable> }

相关内容