我想在宏中使用 pgfkeys。一个键包含一个 foreach 语句,该语句处理可变数量的值。我对输出的正确顺序有些疑问。这里有一个简化的示例:
\documentclass[article]{memoir}
\usepackage[latin]{babel}
\usepackage{algpseudocode}
\usepackage{pgfkeys}
\pgfkeys{%
/test/.is family,
/test/.cd,
key a/.store in = \keyA,
key a print/.code = \texttt{\keyA},
key b/.code = {\foreach \x in {#1}{\textbf{\x}--}}
}%
\newcommand\mymacro[1]{\pgfkeys{/test, #1, key a print}}
\begin{document}
\mymacro{key a = valueKeyA, key b = {valueKeyB1, valueKeyB2, valueKeyB3}}
\end{document}
输出的顺序为:valueKeyB1–valueKeyB2–valueKeyB3–valueKeyA
我如何才能实现首先对 valueKeyA 进行排版?如果我在示例代码中将 #1 放在键列表的末尾,则会收到错误消息。如果我在实际代码中将其放在键列表的末尾,则会缺少第一个键的值。我猜这要么与值的存储顺序和键的执行顺序有关,要么是我对 #1 的使用混淆了。
我使用 pgfkeys 的时间不长,如果有人能给我提示我会很高兴。
答案1
目前,按键按以下顺序执行:
key a = valueKeyA
. 这存储valueKeyA
在宏中\keyA
。key b = {valueKeyB1, valueKeyB2, valueKeyB3}
. 打印输出valueKeyB1--valueKeyB2--valueKeyB3--
(忽略格式)key a print
. 这将打印出\keyA
扩展为 的内容valueKeyA
。
因此,问题在于,对于key a
,处理分为两个部分:存储和打印,而对于 ,key b
这一切都在一个步骤中完成。调用事物的顺序意味着 的两个步骤a
被 的一个步骤分开b
。有多种方法可以解决这个问题,具体取决于您想要实现的目标。
在给出一些之前,让我解释一下为什么放在#1
最后不起作用。这是因为这样会把步骤 3 放在上面第一的,然后它会尝试打印出\keyA
尚未设置的值。
正如我所说,如何修复此问题取决于你想在实际代码中做什么。以下是一些。
将
key a print
参数内部放到\mymacro
正确的位置,因此我们有:\newcommand\mymacro[1]{\pgfkeys{/test, #1}} \begin{document} \mymacro{key a = valueKeyA, key a print, key b = {valueKeyB1, valueKeyB2, valueKeyB3}}
使
key a
步骤同时存储和打印其值,例如:\pgfkeys{/test/.cd, key a/.code={\def\keyA{#1}\texttt{#1}}}
key a print
然后从各处移除。让
key b
步骤将其结果存储在宏中,以便稍后打印出来。例如:\pgfkeys{/test/.cd, key b/.code={\def\keyB{}\foreach \x in {#1}{\expandafter\gdef\expandafter\keyB\expandafter{\keyB\textbf{\x}--}}}, key b print/.code={\keyB}}
key b print
然后添加key a print
(或合并print all keys
)。
可能还有更多——即使它们没有被证明是有用的,它们也应该可以帮助您弄清楚您想要的解决方案的功能。
(编辑:2013-06-20)
第三个解决方案在扩展方面有点问题。\x
在 的定义中, 至少需要扩展一次。如果所有内容都可以在定义时扩展,那么可以使用而不是 来\keyB
实现。如果不行,那么就会出现一大堆s。\protected@xdef
\gdef
\expandafter
说实话,LaTeX3所以对于这种事情来说要容易得多,所以我添加了一个与 PGF foreach 非常接近的 LaTeX3 版本(细微的差别在于我在显示时而不是定义时迭代键列表)。我可能会做些稍微不同的事情,因为我不会费心将key a print
和key b print
作为键,而只是作为命令。但我会密切关注您的代码,以便您可以看到相似之处和不同之处。
以下均产生:
valueKeyA
值键B1--值键B2--值键B3
\documentclass[article]{memoir}
%\url{http://tex.stackexchange.com/q/54533/86}
\usepackage[latin]{babel}
\usepackage{algpseudocode}
\usepackage{pgfkeys}
\usepackage{pgffor}
\usepackage{xparse,expl3}
\pgfkeys{%
/test/.is family,
/test/.cd,
key a/.store in = \keyA,
key a print/.code = \texttt{\keyA},
key b/.code = {%
\let\keyB=\relax%
\foreach \x in {#1} {%
\ifx\keyB\relax
\expandafter\gdef\expandafter\keyB\expandafter{\expandafter\textbf\expandafter{\x}}%
\else
\expandafter\expandafter\expandafter\gdef\expandafter\expandafter\expandafter\keyB\expandafter\expandafter\expandafter{%
\expandafter\keyB\expandafter-\expandafter-\expandafter\textbf\expandafter{\x}%
}%
\fi
}%
},
key b print/.code={\keyB}
}%
\makeatletter
\pgfkeys{%
/xtest/.is family,
/xtest/.cd,
key a/.store in = \keyA,
key a print/.code = \texttt{\keyA},
key b/.code = {%
\let\keyB=\relax%
\foreach \x in {#1} {%
\ifx\keyB\relax
\protected@xdef\keyB{\protect\textbf{\x}}%
\else
\protected@xdef\keyB{%
\keyB--\protect\textbf{\x}%
}%
\fi
}%
},
key b print/.code={\keyB}
}%
\makeatother
\ExplSyntaxOn
\tl_new:N \l__aik_keya_tl
\clist_new:N \l__aik_keyb_clist
\keys_define:nn {3test}
{
key~ a .tl_set:N = \l__aik_keya_tl,
key~ b .clist_set:N = \l__aik_keyb_clist,
key~ a~ print .code:n = {
\texttt{\tl_use:N \l__aik_keya_tl}
},
key~ b~ print .code:n = {
\tl_clear:N \l_tmpa_tl
\clist_map_inline:Nn \l__aik_keyb_clist
{
\tl_use:N \l_tmpa_tl \textbf{##1}
\tl_set:Nn \l_tmpa_tl {--}
}
}
}
\NewDocumentCommand \mytmacro {m}
{
\keys_set:nn {3test} {#1, key~ a~ print, key~ b~ print}
}
\ExplSyntaxOff
\newcommand\mymacro[1]{\pgfkeys{/test, #1, key a print, key b print}}
\newcommand\myxmacro[1]{\pgfkeys{/xtest, #1, key a print, key b print}}
\begin{document}
\mymacro{key a = valueKeyA, key b = {valueKeyB1, valueKeyB2, valueKeyB3}}
\myxmacro{key a = valueKeyA, key b = {valueKeyB1, valueKeyB2, valueKeyB3}}
\mytmacro{key a = valueKeyA, key b = {valueKeyB1, valueKeyB2, valueKeyB3}}
\end{document}