我想在宏中使用 pgfkeys,但发现文档有点难以上手。以下代码应该可以说明我试图解决的问题:
\documentclass{article}
\usepackage{pgfkeys}
\newcommand{\mymacro}[2][]{
Before the elements.
% if the elements key is set and the list is not empty
% extract the members and list them separated by commas...
% else print `No elements passed.'
#2
}
\begin{document}
\mymacro[elements={a, b, c}]{Foo.}
% The above should expand to:
%
% Before the elements. a, b, c. Foo.
\mymacro{Foo.}
% The above should expand to:
%
% Before the elements. No elements passed. Foo.
\end{document}
答案1
编辑:这是根据评论修改后的答案。我采纳了 Andrew Stacey 提出的许多建议。
PGF 关键功能种类繁多、功能强大,因此需要花费大量精力才能弄清楚如何使用它们来做您想做的事情!让我先分部分介绍我的解决方案,然后再完整介绍。
\newcommand{\mymacro}[2][elements/.initial = {No elements passed.}]{
Before the elements.
% if the elements key is set and the list is not empty
% extract the members and list them separated by commas...
% else print `No elements passed.'
{\pgfkeys{/mymacro/.cd, #1, print}}
#2
}
您应该这样定义\mymacro
。您必须调用\pgfkeys
可选参数,以便实际处理要使用的键。请注意,有必要在所有 PGF 键的路径树中为您的键提供一个“目录”,并且自己创建目录似乎是个好主意,我称之为/mymacro
(像 UNIX 目录)。
工作原理是,它将elements
处理给定的值,然后print
输出结果,如果未指定任何元素,则输出错误消息。我通过让默认参数\mymacro
直接设置值来处理这个问题elements
,而无需进行任何处理。
我还小心地将对的调用\pgfkeys
放在一个组中,因为的操作elements
不会初始化其值,并且后续的调用\mymacro
可能会相互干扰。
\pgfkeys{/mymacro/.cd,
print/.code = {\pgfkeysvalueof{/mymacro/elements}},
elements/.code = {%
\pgfkeys{/mymacro/.cd,
list/.list = {#1},
elements/.add={\{}{\}}
}%
},
list/.code = {\pgfkeys{/mymacro/elements/.append = (#1)}}
}
现在我们必须定义这些键的操作。在我看来,你的elements
钥匙是一个储物箱,里面的东西都会被打印出来print
。然而,它还elements = {a, b, ...}
使用.code
我为其定义的子键(“处理程序”),处理它在被调用为 时收到的值。这个东西会调用list
键的.list
处理程序(pgffor
如果您只是pgfkeys
单独加载而不是通过 加载,则需要该包tikz
),它只会循环遍历给定的任何逗号分隔列表,并应用于list/.code
每个项目。作为一个不具创意的例子,我只是在项目周围加上括号。之后,您还可以对elements/.code
结果进行后处理,例如通过前置和后置括号。
这种让键既可以作为值的存储,又可以作为作用于该值的代码的技巧非常有用。至少它允许你编写语义上有吸引力的语句,而elements = {a,b,c}
不必担心这是否真的分配,因为它既可以是代码,也可以是处理结果的后续分配。
也许可以更巧妙地设置,以便使用更少的键,但这在本例中会造成混淆。以下是完整的 LaTeX 文件:
\documentclass{article}
\usepackage{pgfkeys,pgffor}
\newcommand{\mymacro}[2][elements/.initial = {No elements passed.}]{
Before the elements.
% if the elements key is set and the list is not empty
% extract the members and list them separated by commas...
% else print `No elements passed.'
{\pgfkeys{/mymacro/.cd, #1, print}}
#2
}
\pgfkeys{/mymacro/.cd,
print/.code = {\pgfkeysvalueof{/mymacro/elements}},
elements/.code = {%
\pgfkeys{/mymacro/.cd,
list/.list = {#1},
elements/.add={\{}{\}}
}%
},
list/.code = {\pgfkeys{/mymacro/elements/.append = (#1)}}
}
\begin{document}
\mymacro[elements = {a,b,c}]{Foo}
\mymacro{Bar}
\mymacro[elements = {1,2,3}]{Baz}
\mymacro{Quh}
\end{document}
答案2
解决方案取决于你想用元素做什么,但有一个想法是
\documentclass{article}
\usepackage{pgfkeys}
\def\mymacroempty{}
\pgfkeys{/mymacro/.cd,
elements/.code = \def\myelements{#1}}
\newcommand{\mymacro}[2][]{%
\pgfkeys{/mymacro/.cd,elements={}}
\pgfqkeys{/mymacro}{#1}
\ifx\myelements\mymacroempty
No elements passed.
\else
\myelements.
\fi
#2
}
\begin{document}
\mymacro[elements={a, b, c}]{Foo.}
\mymacro{Foo.}
\end{document}