将键值对列表转发到 expl3 中的其他命令

将键值对列表转发到 expl3 中的其他命令

我想将键值对列表传递给另一个命令/环境。在此 MWE 中为tcolorbox,但它应该可以正常工作(例如将参数传递给\LoadClass[params]{article})。

\documentclass{article}
\usepackage{xparse,graphicx}

\RequirePackage{tcolorbox}
\tcbuselibrary{xparse}
\DeclareTColorBox{mytcb}{O{}}{#1}

\ExplSyntaxOn
\keys_define:nn { mybodule/bfigure }
{
    caption .tl_set:N = \l_mybodule_caption_tl,
    tcb     .clist_set:N = \l_mybodule_tcb_clist,
}

\NewDocumentEnvironment{bfigure}{O{}}
{
    \keys_set:nn { mybodule/bfigure } { #1 }  
    \begin{mytcb}[\l_mybodule_tcb_clist]
}
{\end{mytcb}}
\ExplSyntaxOff

\begin{document}
    \begin{bfigure}[tcb={left=-3pt}]
        \includegraphics[width=1cm]{example-grid-100x100pt}
    \end{bfigure}
\end{document}

我不太清楚如何实现这一点。有人能帮忙吗?

答案1

一般的想法是,您需要\l_mybodule_tcb_clist在将其作为逗号分隔的键值列表传递给某些命令/环境之前进行扩展。

首先,只需要扩展一步就可以获取l3clist变量的内容。

然后在简单情况下,如果我们有\cmdA[options]\cmdA{options},那么

\expandafter\cmdA\expandafter[\l_options_clist]
% or
\expandafter\cmdA\expandafter{\l_options_clist}

完成工作。\LoadClass[params]{article}属于这种类型。

在更复杂的情况下,如果之前还有其他参数options,例如\cmdB{arg1}[options],那么您可以通过提供一个新宏将其作为第一个参数处理:

\def\temp{\cmdB{arg1}}%
\expandafter\temp\expandafter[\l_options_clist]

对于可扩展的解决方案,可以使用宏扩展来交换参数的顺序,扩展第一个参数,然后恢复顺序。 (sub) 包中的 latex3 函数使用的机制l3expan与此类似。

% follow xparse' arg-spec names, 
% m stands for mandatory, o stands for optional
\def\expandsecond@mo#1#2[#3]{%
  \expandafter\expandafter\expandafter#1%
  \expandafter\exchangetwo@mm@to@om\expandafter{#3}{#2}%
}
\def\exchangetwo@mm@to@om#1#2{{#2}[#1]}

% store key-value pairs in macro
\def\options{key1,key2,key3}

% suppose \cmdB has syntax \cmdB{}[]
% this will expand to \cmdB{arg1}[key1,key2,key3]
\expandsecond@mo\cmdB{arg1}[\options]

\begin{envname}[options]就属于这种类型。

特别在您的示例中,由于环境mytcb是在由环境创建的组内使用的bfigure\tcbset{options}\begin{mytcb}因此相当于\begin{mytcb}[options],因此有@UlrikeFischer 的建议评论

\ExplSyntaxOn
\NewDocumentEnvironment{bfigure}{O{}}
{
    \keys_set:nn { mybodule/bfigure } { #1 }
    \exp_args:No\tcbset{\l_mybodule_tcb_clist}
    \begin{mytcb}
}
{\end{mytcb}}
\ExplSyntaxOff

答案2

不幸的是,LaTeX 的所有不同键值系统都是互不兼容的,这需要将键值树序列化为逗号分隔的列表并传递它们。到目前为止,似乎还没有一个所有人都应该遵守的主流键值系统。

由于您正在与 进行交互tcolorbox,因此我只能建议使用pgfkeys。与此相反l3keys,它与包的其余部分自然集成,您可以轻松访问/tcb子树并传递您的选项。

\documentclass{article}
\usepackage{xparse,graphicx}

\RequirePackage{tcolorbox}
\tcbuselibrary{xparse}
\DeclareTColorBox{mytcb}{O{}}{#1}

\pgfqkeys{/mybodule/bfigure}{%
    caption/.initial={},
    tcb/.style={/tcb/.cd,#1},
}

\NewDocumentEnvironment{bfigure}{O{}}{%
    \pgfqkeys{/mybodule/bfigure}{#1}%
    \begin{mytcb}%
}{%
    Caption: \pgfkeysvalueof{/mybodule/bfigure/caption}%
    \end{mytcb}%
}

\begin{document}
    \begin{bfigure}[caption={foobar},tcb={left=-3pt}]
        \includegraphics[width=1cm]{example-grid-100x100pt}
    \end{bfigure}
\end{document}

答案3

您显然正在使用它mytcb作为辅助环境,因此让它接受强制参数而不是可选参数应该没有问题。

\documentclass{article}
\usepackage{xparse,graphicx}

\usepackage{tcolorbox}
\tcbuselibrary{xparse}
\DeclareTColorBox{mytcb}{m}{#1}

\ExplSyntaxOn
\keys_define:nn { mybodule/bfigure }
{
    caption .tl_set:N = \l_mybodule_caption_tl,
    tcb     .clist_set:N = \l_mybodule_tcb_clist,
}

\NewDocumentEnvironment{bfigure}{O{}}
{
    \keys_set:nn { mybodule/bfigure } { #1 }  
    \exp_args:NnV \begin{mytcb} \l_mybodule_tcb_clist
}
{\end{mytcb}}
\ExplSyntaxOff

\begin{document}

\begin{bfigure}[tcb={left=-3pt}]
\includegraphics[width=1cm]{example-grid-100x100pt}
\end{bfigure}

\begin{bfigure}[tcb={left=20pt,right=4cm}]
\includegraphics[width=1cm]{example-grid-100x100pt}
something that will show the effect of the \texttt{right}
option, for lack of knowledge what other keys you plan to use 
\end{bfigure}

\end{document}

在此处输入图片描述

相关内容