pgf 密钥是如何定义的?

pgf 密钥是如何定义的?

以下代码说明我不了解 的最基本知识之一pgfkeys。即定义密钥需要什么。我已经阅读了手册的第 87.3 节及后续章节,但我仍然对密钥的定义时间有点困惑。

我原本以为用类似列表的方式运行样式{assignlabel}就足以定义assignlabel键了。看来不行。这是因为我还没有给/assignlabel键分配值吗?

如果我运行下面的代码,我会得到

ERROR: Package pgfkeys Error: I do not know the key
'/printdoctable/assignlabel/' and I am going to ignore it. Perhaps
you misspelled it.

但是,如果我取消注释该.estore行,此错误就会消失。我不明白为什么。该行只是将任何已分配的值存储到宏中,\assignlabel对吗?我还没有为该键分配任何值,那么为什么现在定义了它?而且似乎/.is choice处理程序也不足以定义它。这.estore行代码在这里有什么特别之处?

\documentclass[12pt]{article}
\usepackage{pgfkeys}
\usepackage{xparse}

\pgfkeys
{
  /printdoctable/.is family, /printdoctable,                                                                                                 
  default/.style =
  {
    assignlabel,
  },
  assignlabel/.is choice,
  % assignlabel/.estore in = \assignlabel,                                                                                                                                                                                     
  assignlabel/true/.estore in={\assignlabel},                                                                                 
  assignlabel/false/.estore in={\assignlabel},                                                                               
}  
\NewDocumentCommand{\PrintDocTable}{O{}}
{
  \pgfkeys{/printdoctable, default, #1}%                                                                                                              
 %\assignlabel                                                                                                                                      
}                                                                                                                                  

\begin{document}
\PrintDocTable[assignlabel=false]
\end{document}

答案1

这是为了强调我们的聊天,由于篇幅过长,无法在此进行全面回顾。

首先,问题似乎是如何定义 pgf 密钥。简短的回答是

 assignlabel/.is choice,

已经这样做了,

 default/.style =
  {
    assignlabel,
  },

没有必要。

然后就是为什么你的代码不起作用的问题。这是因为你的代码中assignlabel需要一个参数。要消除错误,只需为添加默认值即可assignlabel,例如

\documentclass[12pt]{article}
\usepackage{pgfkeys}
\usepackage{xparse}

\pgfkeys
{
  /printdoctable/.is family, /printdoctable,                                                                                                 
  default/.style =
  {
    assignlabel,
  },
  assignlabel/.is choice,
  assignlabel/true/.estore in={\assignlabel},                                                                                 
  assignlabel/false/.estore in={\assignlabel},                                                                               
  assignlabel/.default=true,                                                                                                                                                                                     
}  
\NewDocumentCommand{\PrintDocTable}{O{}}
{
  \pgfkeys{/printdoctable, default, #1}%                                                                                                              
 %\assignlabel                                                                                                                                      
}                                                                                                                                  

\begin{document}
\PrintDocTable[assignlabel=false]
\end{document}

不会导致错误(但此时也不太有用)。

然后聊天中提到,如果你只想要一个布尔值,那么使用/.is ifkey 可能更好。此 key 在 pgfmanual v3.1.4 的第 974 页中有描述

在此处输入图片描述

这里的代码示例非常好,因为它说明了键的作用。保罗的回答又加了一个例子。

不幸的是,在我看来,v3.1.4 的代码示例/.is choice并不是最理想的。

在此处输入图片描述

有两个问题:

  1. 首先,正如你在TeX 聊天butt cap在我们的聊天中,和的角色round cap互换了。
  2. 此外,前三个/.style键确实应该是/.code键。

问题已报告并且很可能会在下一版本的 pgf 中得到解决。

答案2

这是我的解决方案(如果我理解您的要求),其中我定义了一个新的 if(\ifprintdoctableassignlabel):

\documentclass[12pt]{article}
\usepackage{pgfkeys}
\usepackage{xparse}

\newif\ifprintdoctableassignlabel

\pgfkeys
{
  /printdoctable/.is family,
  /printdoctable,
  assignlabel/.is if=printdoctableassignlabel,
  default/.style={assignlabel=true},
}
\NewDocumentCommand{\PrintDocTable}{O{}}
{
  \pgfkeys{/printdoctable,default,#1}%
  \ifprintdoctableassignlabel
  assignlabel is true
  \else
  assignlabel is false
  \fi
}

\begin{document}
\PrintDocTable\par
\PrintDocTable[assignlabel=false]\par
\PrintDocTable[assignlabel=true]    
\end{document}

结果:

分配标签为真

分配标签为假

分配标签为真

以下是使用处理程序的示例.is choice

\documentclass[12pt]{article}
\usepackage{pgfkeys}
\usepackage{xparse}

\newif\ifprintdoctableassignlabel

\pgfkeys
{
  /printdoctable/.is family,
  /printdoctable,
  %
  assignlabel/.is if=printdoctableassignlabel,
  assignlabel/.default=true,
  %
  label/.is choice,
  label/a/.code={\def\printdoctablelabel{choice a}},
  label/b/.code={\def\printdoctablelabel{choice b}},
  label/c/.code={\def\printdoctablelabel{choice c}},
  %
  predefined values/.style={
    assignlabel=true,
    label=a,
  },
}
\NewDocumentCommand{\PrintDocTable}{O{}}
{%
  \pgfkeys{/printdoctable,predefined values,#1}%
  \ifprintdoctableassignlabel%
  assignlabel is true%
  \else%
  assignlabel is false%
  \fi%
  \space(label=\printdoctablelabel)%
}

\begin{document}
\PrintDocTable[label=b]

\PrintDocTable[assignlabel=false]

\PrintDocTable[assignlabel,label=c]

\end{document}

结果:

assignlabel 为真(标签=选择 b)

assignlabel 为假(标签=选择 a)

assignlabel 为真(标签=选择 c)

答案3

首先,非常感谢@Schrödinger 的猫在聊天中非常耐心地回答我的问题,并给出了有用的答案。我认为如果我能总结一下上述问题中出现的困惑,那会有所帮助。我想我现在理解得更清楚了。虽然 PGF/TikZ 手册很好(而且比大多数文档(无论是 TeX 相关还是其他方面)都要好得多),但仍有几件事需要强调。

从顶部开始,出于某种原因,我似乎认为

default/.style =
  {
    assignlabel,
  },

实际上初始化了相关键(在本例中为assignlabel)。事实证明,这是大错特错的。处理程序实际上所做的只是在键(在命名空间内)和键值对列表.style之间设置一种别名。因此,如果处理程序设置在该键上,则调用该处理程序会调用该键列表。但它实际上并没有定义任何这些键。这是一个重要的细节。defaultprintdoctable.style

然而,这两条线路

assignlabel/.is choice,

assignlabel/.estore in = \assignlabel, 

定义一个键。然而,这还不够,因为我写的方式assignlabel没有默认值。所以当我调用

\pgfkeys{/printdoctable, default, #1}%

在我的回答中,default部分出错了,因为它实际上是在调用assignlabel,。此时它没有默认值。如果没有指定值,则组成 RHS 的键值对会.style期望默认值。不过我仍然不确定错误消息的原因:

I do not know the key '/printdoctable/assignlabel/'

而不是抱怨没有分配值,这肯定会产生更好的错误消息。但由于 Tex 实际上没有变量或变量分配,所以它可能是一个 TeX 工件。

正如 @schrodinger's cat 解释的那样,解决这个问题的一种方法是assignlabel使用

assignlabel/.default=true,

另一种方法是写

default/.style =
  {
    assignlabel=false,
  },

它为键值对提供所需的值。

相关内容