这是我第一次接触 pgfkeys 包,我发现以下行为真的很奇怪。Tikz/pgfkeys 手册提到了两种设置键值的方法:\pgfkeys{key=value}
和\pgfkeyssetvalue{key}{value}
。当我尝试这两种方法时,它们返回不同的值。MWE:
\documentclass{article}
\usepackage{tikz}
\pgfkeys{/my color/.initial = red, /my color/.estore in = \mycolor}
\begin{document}
\pgfkeys{/my color=blue}
The colors are \mycolor{} and \pgfkeysvalueof{/my color}.
\pgfkeyssetvalue{/my color}{yellow}
The colors are \mycolor{} and \pgfkeysvalueof{/my color}.
\end{document}
输出为:
The colors are blue and red.
The colors are blue and yellow.
我原本以为第一行全是蓝色,第二行全是黄色。哪里出错了?
答案1
我个人认为手册写得有点误导。它随意混合了两种不同类型的pgfkeys
操作符:
这核心价值接口,仅通过语法访问
\pgfkeys{<key> = <value>}
,但通过使用(和创建!)具有可扩展的功能处理程序,即干预处理的特殊键后缀<key>
。这宏界面,由基本不相关且不复杂的命令组成,例如
\pgfkeyssetvalue
。这些命令不是与处理程序交互,而是直接访问键的内部 TeX 表示形式;因此,与相比,它们速度超快\pgfkeys
,但不参与其语言的高级方面。
接下来你需要理解的是,<key>
inpgfkeys
实际上是一个由几个混乱的 TeX 宏名组成的对象,其中两个相关的是
\pgfkeys@<key>
:存储宏价值的<key>
。\pgfkeys@<key>/.@cmd
:存储宏行动的<key>
。
最后,你必须理解\pgfkeys
当出现以下情况时如何决定做什么<key> = <value>
:
它检查是否
<key>
定义了动作,如果是,则以其<value>
参数执行该动作。如果没有,它会检查是否
<key>
已定义值,如果是,则用 替换它<value>
。如果不是,它会检查是否
<key>
以已知处理程序的名称结尾,如果是,则执行它(设置各种上下文宏,以便处理程序知道如何处理其余的密钥)。
当你设置一个密钥时,例如
\pgfkeys{/my color/.initial = red, /my color/.estore in = \mycolor}
您所做的如下:设置价值并/my/color
设置red
行动本质上定义为/my color
宏
\pgfkeys@/my/color/.@cmd #1 -> \edef\mycolor{#1}
这是因为.estore in
是一个设置请求它的键的操作的处理程序。 .initial
也是一个处理程序,但它只是直接设置键的值,而不是其操作。
当您请求操作时
\pgfkeys{/my color=blue}
The colors are \mycolor{} and \pgfkeysvalueof{/my color}.
你请求\pgfkeys
访问行动,/my color
存储blue
在\mycolor
和没有改变的值/my color
;因此,\mycolor{} -> blue
和\pgfkeysvalueof{/my color} -> red
(仍然)。
当您请求操作时
\pgfkeyssetvalue{/my color}{yellow}
The colors are \mycolor{} and \pgfkeysvalueof{/my color}.
你直接设置的值/my color
,绕过正常的键值处理,\mycolor
因此没有重新定义和\pgfkeysvalueof{/my color} -> yellow
。现在,扩展\mycolor
应该是一个错误,但幸运的是,你把这行代码放在了将其定义为 的前一个块之后blue
,所以它仍然是blue
。如果你删除第一个块,那么你会得到一个关于未定义的 TeX 错误\mycolor
。
<key> = <value>
现在,您可能想知道,如果使用只会在存在时执行操作,那么键如何可以同时具有值和操作。正如您所看到的,答案是,您始终可以使用 访问值\pgfkeysvalueof
,也可以使用 等处理程序访问值.get
。但是,等号是一个高级运算符,实际上并不意味着赋值:如果您确实想设置键值,则必须使用.initial
或\pgfkeyssetvalue
。
我的个人想法是应该避免使用宏运算符,除非你试图pgfkeys
与常规 TeX 代码混合,在这种情况下,显然非pgfkeys
代码必须使用宏接口。但是,如果你\pgfkeys
专门使用并且处于高级别,那么你应该只使用处理程序。pgfkeys
使用宏运算符的唯一时间是如果你正在编写键的内部:那么宏可能比调用更快,而且,如果你避免使用元等号,你将有更好定义的行为,以防你的一个键在你背后重新定义其元行为。(一个真正鬼鬼祟祟的人可以通过重新定义处理程序来\pgfkeys
破解大多数代码!)pgfkeys
答案2
我会这样做:
\documentclass{article}
\usepackage{tikz}
\pgfkeys{/.cd,
my color/.store in = \mycolor,
my color=red,}
\begin{document}
\pgfkeyssetvalue{/my color}{blue}
The colors are \mycolor{} and \pgfkeysvalueof{/my color}.
\pgfkeyssetvalue{/my color}{yellow}\pgfkeysgetvalue{/my color}{\mycolor}
The colors are \mycolor{} and \pgfkeysvalueof{/my color}.
\pgfkeys{my color=yellow} \pgfkeysgetvalue{/my color}{\mycolor}
\mycolor.
\end{document}
上述着色是通过以下方式产生的:
\pgfkeyssetvalue{/my color}{blue}
The colors are \textcolor{\mycolor}{\mycolor} and \textcolor{\pgfkeysvalueof{/my color}}{\pgfkeysvalueof{/my color}}.
\pgfkeyssetvalue{/my color}{yellow}\pgfkeysgetvalue{/my color}{\mycolor}
The colors are \textcolor{\mycolor}{\mycolor} and \textcolor{\pgfkeysvalueof{/my color}}{\pgfkeysvalueof{/my color}}.
\pgfkeys{my color=yellow} \pgfkeysgetvalue{/my color}{\mycolor}
\textcolor{\mycolor}{\mycolor}.
将键的值存储/.store
在宏中,而键值在后期可能会有所不同。要稍后更改宏的值,您可以/.store
再次使用或使用\pgfkeysgetvalue{/my color}{\mycolor}
。要更改键本身的值,请使用\pgfkeyssetvalue{/my color}{blue}
。