获取 pgfkey 值的正确方法是什么?

获取 pgfkey 值的正确方法是什么?

这是我第一次接触 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>

  1. 它检查是否<key>定义了动作,如果是,则以其<value>参数执行该动作。

  2. 如果没有,它会检查是否<key>已定义值,如果是,则用 替换它<value>

  3. 如果不是,它会检查是否<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}

相关内容