3

The following code illustrates that I don't understand one of the most basic things about pgfkeys. Namely, what it takes for a key to be defined. I've read through section 87.3 and following sections of the manual, but it still left me a bit fuzzy about when a key has been defined.

I originally thought that running a style with a list like {assignlabel} was sufficient to define the assignlabel key. It seems not. Is this because I have not assigned the /assignlabel key a value?

If I run the code below, I get

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

However, if I uncomment the .estore line, this error goes away. I don't understand why. That line just stores any assigned value to the macro, \assignlabel, right? I still have not assigned any value to the key, so why is it now defined? And it seems the /.is choice handler doesn't suffice to define it either. What does the .estore line do that is special here?

\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}
3

This is an attempt to highlight a few key features of our chat, which is too long to be fully reviewed here.

First and foremost, the question seems to be how one can define a pgf key. The short answer is that

 assignlabel/.is choice,

does that already,

 default/.style =
  {
    assignlabel,
  },

is not needed for that.

Then there is the question why your code does not work. This is because in your code assignlabel needs an argument. To make the error go away, it is sufficient to add a default to assignlabel, e.g.

\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}

does not cause an error (but is at this point also not too useful either).

Then it was mentioned in the chat that if you only want a Boolean, you may be better off with the /.is if key. This key is described in the pgfmanual v3.1.4 on p. 974

enter image description here

The code example here is very good in that it illustrates what the key does. Paul's answer adds another example.

Unfortunately, the v3.1.4 code example of /.is choice is IMHO less than optimal.

enter image description here

There are two issues:

  1. First, as you pointed out in the TeX chat and our chat, the roles of butt cap and round cap are swapped.
  2. Moreover, the first three /.style keys should really be /.code keys.

This issue has been reported and will most likely be resolved in the next version of pgf.

9
  • Perhaps my question wasn't clear. My ultimate goal is to define a boolean key, but let's set that aside for the moment. This question is simply to ask why the code stops complaining about assignlabel being undefined once the assignlabel/.estore in = \assignlabel, has been added. The .is choice code isn't really relevant, and if it makes the question less confusing, I could delete it. I'm more interested in understanding what's going on here than achieving a specific goal. Unexpected results always particularly concern me, because that's a clear sign I don't understand something. Dec 19 '19 at 3:31
  • @FaheemMitha Your code also works if you remove , default from \pgfkeys{/printdoctable, default, #1}% , i.e. use \pgfkeys{/printdoctable, #1}% instead. At the moment the way you use default does not make too much sense.
    – user194703
    Dec 19 '19 at 3:40
  • Thanks for pointing that out. Actually, I'm unclear whether the code default/.style = { assignlabel, } actually serves any purpose if assignlabel isn't given a value. I earlier thought it initializes the key assignlabel, but apprently not. Dec 19 '19 at 3:46
  • @FaheemMitha asssignlabel gets "initialized" by assignlabel/.is choice,.
    – user194703
    Dec 19 '19 at 3:48
  • So, does default/.style = { assignlabel, } do anything at all? Dec 19 '19 at 3:50
3

Here is my solution (if I understand your request) where I define a new 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}

The result:

assignlabel is true

assignlabel is false

assignlabel is true

Here is an example using an .is choice handler:

\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}

The result:

assignlabel is true (label=choice b)

assignlabel is false (label=choice a)

assignlabel is true (label=choice c)

8
  • Hi @Paul. Thank you for the answer. You seem to have interpreted my question as "how do I implement a boolean using pgfkeys", when actually it was "why am I seeing this behavior?". But have an upvote anyway. Dec 20 '19 at 13:08
  • @FaheemMitha Thanks. Just a remark about your question and other answers: the use of the .estore in handler is not relevant. Here, using the simpler .store in handler is enough and does not change all the explanations. Dec 20 '19 at 13:38
  • Hi Paul. Yes, I guess estore is not required. I've just got into the habit of using it. Dec 20 '19 at 19:18
  • @FaheemMitha It is exactly as if you always use \edef instead of \def.... Dec 21 '19 at 1:48
  • Are .estore and other e-things best avoided then? Dec 21 '19 at 6:25
3

First, thanks very much to @Schrödinger's cat for very patiently answering my questions in chat, and for a helpful answer. I thought it would help if I could summarize the confusions that went into my question above. I think I understand things better now. While the PGF/TikZ manual is fine (and much better than most documentation out there, TeX-related or otherwise), there are a few things which could be emphasized.

Taking it from the top, for some reason, I seem to have thought that something like

default/.style =
  {
    assignlabel,
  },

actually initialized the key in question (in this case, assignlabel). As it turns out, this is horribly wrong. What the .style handler actually does is simply set up a sort of alias between the key default (inside the printdoctable namespace), and a list of key-value pairs. So if the .style handler is set on that key, then calling that calls that list of keys. But it doesn't actually define any of those keys. That's an important detail.

However, both the lines

assignlabel/.is choice,

and

assignlabel/.estore in = \assignlabel, 

define a key. However, that is not enough, because the way I wrote it,assignlabel does not have a default value. So when I called

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

in my answer, the default part errored out, because it was effectively calling assignlabel,. Which doesn't have a default value at this point. And the key-value pairs that comprise the RHS of the .style expect a default if a value is not specified. Though I'm still not sure why the error message is:

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

instead of complaining that a value hasn't been assigned, which would certainly make for a better error message. But since Tex doesn't actually have variables or variable assignments, maybe it's a TeX artifact.

As @schrodinger's cat explained, one way around this is to assign assignlabel a default value with

assignlabel/.default=true,

An alternative is to write

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

which provides the required value to the key-value pair.

1
  • Looks good to me. +1 to you and Paul.
    – user194703
    Dec 19 '19 at 21:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.