Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

This is my first foray into the pgfkeys package and I found the following behavior really odd. The Tikz/pgfkeys manual mentions two ways for setting key values: \pgfkeys{key=value} and \pgfkeyssetvalue{key}{value}. When I tried both, they return different values. 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 output is:

The colors are blue and red.
The colors are blue and yellow.

I was expecting all blue on the first line and all yellow on the second. What went wrong?

share|improve this question
    
Somehow, this problem has been extensively discussed in What do the pgfkeys key handlers .get and .store in do?. –  Claudio Fiandrino Feb 23 at 15:13
    
Simplified version can be \documentclass{article}\usepackage{pgfkeys}\begin{document}\pgfkeys{/my color/.initial = red}The color was \pgfkeysvalueof{/my color} but now; \pgfkeys{/my color=blue}the colors are\pgfkeysvalueof{/my color}\pgfkeys{/my color=yellow}and \pgfkeysvalueof{/my color}.\end{document} –  percusse Feb 23 at 17:29
add comment

2 Answers

up vote 18 down vote accepted

My humble opinion is that the manual is misleadingly written here. It freely mixes two different classes of pgfkeys operators:

  • The key-value interface, which is accessed solely through the syntax \pgfkeys{<key> = <value>}, but which has extensible capabilities through the use (and creation!) of handlers, namely, special key suffixes that intervene in the processing of <key>.

  • The macro interface, which consists of basically unrelated and unsophisticated commands such as \pgfkeyssetvalue. These do not interact with handlers but rather access the internal TeX representation of keys directly; thus, they are super-fast by comparison with \pgfkeys, but don't participate in the high-level aspects of its language.

The next thing you have to understand is that a <key> in pgfkeys is actually an object consisting of several mangled TeX macro names, of which the two relevant ones here are

  • \pgfkeys@<key>: the macro storing the value of <key>.

  • \pgfkeys@<key>/.@cmd: the macro storing the action of <key>.

Finally, you have to understand how \pgfkeys decides what to do when it is presented with <key> = <value>:

  1. It checks whether <key> has an action defined, and if so, executes it with <value> as its argument.

  2. If not, it checks whether <key> has a value defined, and if so, replaces it with <value>.

  3. If not, it checks whether <key> ends with the name of a known handler, and if so, executes it (with various context macros set so that the handler knows what to do with the rest of the key).

When you set up a key such as

\pgfkeys{/my color/.initial = red, /my color/.estore in = \mycolor}

what you have done is the following: set the value of /my/color to red and set the action of /my color to a macro defined, essentially, as

\pgfkeys@/my/color/.@cmd #1 -> \edef\mycolor{#1}

This is because .estore in is a handler that sets the action of the key requesting it. .initial is also a handler, but it just sets the value of the key directly, rather than its action.

When you request the operations

\pgfkeys{/my color=blue}
The colors are \mycolor{} and \pgfkeysvalueof{/my color}.

you are asking \pgfkeys to access the action of /my color, which stores blue in \mycolor and does not change the value of /my color; thus, \mycolor{} -> blue and \pgfkeysvalueof{/my color} -> red (still).

When you request the operations

\pgfkeyssetvalue{/my color}{yellow}
The colors are \mycolor{} and \pgfkeysvalueof{/my color}.

you are directly setting the value of /my color, bypassing the normal key-value processing, so that \mycolor is not redefined and \pgfkeysvalueof{/my color} -> yellow. Now, expanding \mycolor should be an error, but you luckily put this line of code after the previous block that defined it to be blue, so it remains blue. If you were to delete the first block then you'd get a TeX error about \mycolor being undefined.

Now, you may wonder how a key can have both a value and an action, if using <key> = <value> will only ever do the action if it exists. The answer, as you have seen, is that you can always access the value with \pgfkeysvalueof, and also with handlers such as .get. The equals sign, however, is a high-level operator and doesn't actually mean assignment: if you actually want to set a key value, you have to use .initial or \pgfkeyssetvalue.

My personal opinion is that the macro operators should be avoided unless you are trying to mix pgfkeys with regular TeX code, in which case, obviously, the non-pgfkeys code has to use the macro interface. If, however, you are using \pgfkeys exclusively and at a high level, then you should just go with handlers. The only time within pgfkeys to use the macro operators is if you are writing the internals of a key: then the macros are likely faster than calling \pgfkeys, and also, if you avoid the use of the meta-equals sign, you will have better-defined behavior in the event that one of your keys gets it meta-behavior redefined behind your back. (A really sneaky person could hack apart most pgfkeys code by redefining the handlers!)

share|improve this answer
2  
This is a really nice answer! –  Gonzalo Medina Feb 23 at 17:08
add comment

I would do it this way:

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

enter image description here

Above coloring is produced with:

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

The /.store stores the value of key in a macro while key value can be different at later stage. To change the value of macro later you can either use /.store again or use \pgfkeysgetvalue{/my color}{\mycolor}. To change the value of key itself use \pgfkeyssetvalue{/my color}{blue}.

share|improve this answer
1  
It seems to me that your .cd makes the use of my color in the following key-setting lines an error. –  Ryan Reich Feb 23 at 17:01
    
The third line in your first block of code contains a directory change that makes the following two lines set the key /my color/my color. –  Ryan Reich Feb 24 at 0:02
    
@RyanReich Corrected. thanks. –  Harish Kumar Feb 24 at 0:26
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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