I am using pgfkeys
to hold formatting parameters. The tree is set up with a set of default values, as well as customizations for various formats. Those formats each have a basic definition, which in turn can have multiple subformats. I maintain all of these simultaneously because I need to be able to switch between different formats and subformats within a single document. And because I store many parameters in the tree, I don't want to have to fully define the complete list of parameters for every subformat. Instead, I take advantage of the .search also
handler so that I request the parameter for a specific subformat and \pgfkeys
will (assuming .search also
has been setup properly) give the most specific customization that exists, falling back to the default setting if nothing else is specified.
For example, for the subformat 1 for format test one
, I define the key
\pgfkeys(/stdt/.cd,
test one/1/.search also={/stdt/test one,/stdt/default})
which has the result that if the key does not exist in that subformat, we first check the parent format, and then the default format for the key.
Then I use the following macro to retrieve the right parameter for the default context while still letting override things if I need to:
\NewDocumentCommand{\stdtParameter} { O{\ActiveFormat} O{\theTestSection} m }
{\pgfkeys{/stdt/#1/#2/.cd,#3}}
This works fine in ordinary contexts, but it's fragile and cannot be used when I need to expand first, for example if I want to use the parameter as an argument of ifnumcomp
from etoolbox
.
I'm able to use \edef
if I invoke \pgfkeysvalueof
, but not \pgfkeys
itself. For example, this works:
\edef\temp{\pgfkeysvalueof{/stdt/\ActiveFormat/num columns}}%
\ifnumgreater{\temp}{1}{Do something}{Do something else}%
But I've been unable to do the same with \pgfkeys
. All my experiments with \edef
and variants have led to abject failure. The problem with using \pgfkeysvalueof
, though, is that it sidesteps the .search also
handler mechanism, and an undefined key will return \relax
, which means that I would need to reimplement all the logic of .search also
in my own macro, and I'm loath to do that if it's unnecessary.
How can I properly expand \pgfkeys
so that I can write something like this?
\ifnumgreater{\stdtParameter{num columns}}{1}{Do something}{Do something else}
MWE to show the effects of different kinds of calls
\documentclass{article}
\usepackage{etoolbox,xparse}
\usepackage{pgfkeys}
\newcommand{\ActiveFormat}{default}
\newcounter{TestSection}
% We need to use cd before getting the parameter because giving the full path
% will stop \pgfkeys from checking search-also trees.
\NewDocumentCommand{\stdtParameter} { O{\ActiveFormat} O{\theTestSection} m }
{\pgfkeys{/stdt/#1/#2/.cd,#3}}
\pgfkeys{/stdt/.cd,
format/.store in=\ActiveFormat,
default/0/.search also={/stdt/default},
default/1/.search also={/stdt/default},
default/name/.initial=Default,
default/my size/.initial=0.5in,
default/my label/.initial=Generic Section,
default/num columns/.initial={1},
test one/.search also={/stdt/default},
test one/name/.initial=Test One,
test one/num columns/.initial={2},
test one/my size/.initial=0.625in,
test one/0/.search also={/stdt/test one,/stdt/default},
test one/1/.search also={/stdt/test one,/stdt/default},
test one/1/my label/.initial=Some Content,
test two/.search also={/stdt/default},
test two/name/.initial=Test Two,
test two/0/.search also={/stdt/test two,/stdt/default},
test two/1/.search also={/stdt/test two,/stdt/default},
test two/my label/.initial=A Different Section
}
\begin{document}
Original format (should be default): \ActiveFormat
Testing \textsf{\textbackslash stdtParameter}
With no optional arguments, the default \textsf{my size} should be \pgfkeys{/stdt/default/my size}.
I got a value of \stdtParameter{my size}.
With one optional argument, \textsf{test one/my size} should be \pgfkeys{/stdt/test one/my size}.
I got a value of \stdtParameter[test one]{my size}.
Now ask for an explicit format which does not define a value for \textsf{my size}. I should get the default value above.
I got a value of \stdtParameter[test two]{my size}
With both optional arguments (format and section), the value of \textsf{test one/1/my label} should be `\pgfkeys{/stdt/test one/1/my label}'.
I got a value of `\stdtParameter[test one][1]{my label}'.
Now check for the fallback label when it's undefined. I asked for \textsf{test two/1/my label}. I should see
`\pgfkeys{/stdt/test two/1/.cd,my label}'.
I got a value of \stdtParameter[test two][1]{my label}.
By default we have \stdtParameter{num columns} columns.
% Switch active formats
\pgfkeys{/stdt/format=test one}
Switched active format to \ActiveFormat, but we're still in section \theTestSection.
The label is `\stdtParameter{my label}'.
\stepcounter{TestSection}
After incrementing the section counter, the label is now `\stdtParameter{my label}' and we
have \stdtParameter{num columns} columns.
% set columns for active format/subformat
\stdtParameter{num columns=3}
Now we have \stdtParameter{num columns} columns.
% The following won't work. We need to fully expand pdfkeys and pass that to \ifnumgreater
% \ifnumgreater{\stdParameter{num columns}}{1}{Multi-column action}{One-column action}
Checking full paths: Default = \pgfkeys{/stdt/default/num columns}.
Test one = \pgfkeys{/stdt/test one/num columns}
Test one, section one = \pgfkeys{/stdt/test one/1/.cd,num columns}
Test two, section one = \pgfkeys{/stdt/test two/1/.cd,num columns}
\end{document}
/stdt/.is family
instead. In the old documentation this was used to create a new "folder"..is family
methods, and the basic problem remains: I still can't get\pgfkeys
to expand with\edef
./.is family
to create a new folder (so to speak) and/.initial=...
to create a new entry. Even/.default
would fail without/.initial
.