I think I finally have a reasonable understanding of pgfkeys
, but initializing a key with or without the .initial
handler is giving me trouble. I do understand the distinction between .default
and .initial
in that the former specifies a value when none is given for a key and the latter specifies a value otherwise (that is my understanding, anyway). The MWE contains four example cases.
The first one seems to work correctly, except that trying to initialize paintwhat
and paintshade
with .initial
gives an error about an undefined control sequence. The second example seems to work correctly, but again trying to initialize units
with .initial
while .default
seems to work perfectly. In the third example, I understand that .initial
doesn't work with subkeys and I think that's why I can't use it in this example. How, then, can I initialize sunits
? Finally, in the fourth example, when I initialize zunits
LAST inside \pgfkeys{...}
the initial use of \picktheunits
works as expected, but the final use does not.
Ultimately, my question is: what causes these difficulties in initializing a key? Is is something trivial I'm overlooking, or is it something subtle?
(In case anyone is wondering, this example with units is my prototypical test case for testing keys and values.)
Here is the MWE:
% !TEX TS-program = lualatexmk
% !TEX encoding = UTF-8 Unicode
\documentclass{article}
\usepackage{pgfkeys}
\begin{document}
A command about painting things.\par
%\newcommand*{\paintit}{} % this appears to be optional
%\newcommand*{paintshadw}{} % this appears to be optional
\pgfkeys{%
/paintthe/.is family, /paintthe,
paintwhat/.store in=\paintit,
paintwhat/.default=building, % used when just paintwhat is given
paintwhat = barn, % initial value of paintwhat; can be overwritten
paintshade/.store in=\paintshade,
paintshade/.default=light, % used when just paintshade is given
paintshade = light, % initial value of paintshade; can be overwritten
}%
% version with shade
\newcommand*{\paintthecolor}[2][]{%
\begingroup % make key values local to this instance
\pgfkeys{/paintthe,#1}
Paint the \paintit\ \paintshade\ #2.
\endgroup
}%
\paintthecolor{green}\par
\paintthecolor[paintwhat]{green}\par
\paintthecolor[paintwhat=house,paintshade=dark]{red}\par
\paintthecolor[paintwhat=car,paintshade=medium]{blue}\par
\paintthecolor{gray}\par
% These commands will already be defined, albeit not as they are here.
\newcommand*{\perpusederivedunits}{You'll get derived units.}
\newcommand*{\perpusebaseunits}{You'll get base units.}
\newcommand*{\perpusealternateunits}{You'll get alternate units.}
A command about selecting default units. Seems to work correctly.\par
\pgfkeys{%
/chooseunits/.is family, /chooseunits,
units/.store in=\chosenunits,
units/.default=alternate,
units=derived, % .initial doesn't work here
}%
\newcommand*{\choosetheunits}[1][]{%
\begingroup
\pgfkeys{/chooseunits,#1}
\csname perpuse\chosenunits units\endcsname % this builds the command that selects the units
\endgroup
}%
\choosetheunits\par % works correctly
\choosetheunits[units=base]\par
\choosetheunits[units]\par
\choosetheunits[units=derived]\par
\choosetheunits[units=alternate]\par
\choosetheunits[units=derived]\par
\choosetheunits[units]\par
\choosetheunits\par % works correctly
A different approach using \texttt{.is choice} handler. Can't initialize.\par
\pgfkeys{%
/selectunits/.is family, /selectunits,% /.cd,
sunits/.is choice,
sunits/.initial={\perpusederivedunits}, % .initial doesn't work with .is choice
sunits/.default=alternate,
sunits/base/.code={\perpusebaseunits},
sunits/derived/.code={\perpusederivedunits},
sunits/alternate/.code={\perpusealternateunits},
}%
\newcommand*{\settheunits}[1][]{%
\begingroup
\pgfkeys{/selectunits,#1}
\endgroup
}%
\settheunits\par % doesn't work since .initial doesn't apply to .is choice
\settheunits[sunits=base]\par
\settheunits[sunits]\par
\settheunits[sunits=derived]\par
\settheunits[sunits=alternate]\par
\settheunits[sunits=derived]\par
\settheunits[sunits]\par
\settheunits\par % doesn't work since .initial doesn't apply to .is choice
Another approach to the unit problem. Partially works.\par
\pgfkeys{%
/pickunits/.is family, /pickunits,
%zunits=derived, % throws unknown key error when placed here
zunits/.default=alternate,
zunits/.code={\csname perpuse#1units\endcsname},
zunits=derived, % works partially when placed here
}%
\newcommand*{\picktheunits}[1][]{%
\begingroup
\pgfkeys{/pickunits,#1}
\endgroup
}%
\picktheunits\par % works correctly
\picktheunits[zunits=base]\par
\picktheunits[zunits]\par
\picktheunits[zunits=derived]\par
\picktheunits[zunits=alternate]\par
\picktheunits[zunits=derived]\par
\picktheunits[zunits]\par
\picktheunits\par % does not work
\end{document}
.initial
handler stores the value inside the key itself, so after\pgfkeys{/foo/.initial=bar}
you can use\pgfkeys{/foo=baz}
to change it's value (as long as no.code
is associated with it), and retrieve its value either with.get
or\pgfkeysvalueof{/foo}
. As.store
is (more or less) the same as.code={\def<macro>{#1}}
, the same remarks as mentioned in the documentation for the.initial
handler (currently page 989) applies.