# How to write a pgfkeys handler so that it can be used as a style?

I would like to enrich pgfkeys by the functionality of mandatory and recommended keys. If a mandatory key is not given, an error is shown. If a recommended key is not given, a warning is shown.

My idea is to have two handlers which can be used after the options have been processed:

\newcommand{\mycommand}[1][]{%
\pgfqkeys{/path}{#1,
key a/recommended,
key b/mandatory,
}%
% ...
}


This is as far as I am:

\documentclass{article}
\usepackage{pgfkeys}
\newcommand{\PackageName}{pgfkeys extended}

\makeatletter
\pgfqkeys{/handlers}{%
% ------- if given -------
if given/.code 2 args={%
\typeout{! path: \pgfkeyscurrentpath}%
\pgfkeys{\pgfkeyscurrentpath/.get=\tmp@value}%
\expandafter \ifx \expandafter \pgfkeysnovalue \tmp@value
#2%
\else
#1%
\fi
},
% ------- recommended -------
recommended/.style={%
if given=
\relax
\PackageWarning{\PackageName}{Recommended key \pgfkeyscurrentkeyRAW' not given.}%
},
}
\makeatother

\pgfqkeys{/test}{%
hello/.initial,
hello/.value required,
}

\begin{document}
content\ldots

%\pgfqkeys{/test}{hello=true}
%\pgfkeysvalueof{/test/hello}
\pgfkeys{/test/hello/if given=10}
\pgfkeys{/test/hello/recommended}

\end{document}


The if given handler works fine on it's own. But when it is called by the recommended handler \pgfkeyscurrentpath is empty.

I could change the recommended handler to a custom code instead of a style, save the \pgfkeyscurrentpath in a command before calling if given and then inside of if given check whether this command has been defined. If it is I use it, if it's not I use \pgfkeyscurrentpath. And in the end I mustn't forget to reset that command. But that seems overly complicated. Isn't there an easier solution?

And if I can't use my own handler here in a style, do I need to be careful that some of TikZ's keys can not be used in a style either?

First, it's a tikz standard to make all handler names start with a period. If you don't do this, you might get confused between normal keys and handlers, though of course you are free to do whatever you want.

If you call a handler like /path/to/key/.handler then the value stored in \pgfkeyscurrentpath is /path/to/key. If you just say .handler=something then the path you've given is empty and \pgfkeyscurrentpath will be set empty. One solution to this is to say \pgfkeyscurrentpath/.handler, so you can say:

\makeatletter
\pgfqkeys{/handlers}{%
.if given/.code 2 args={%
\typeout{! path: \pgfkeyscurrentpath}%
\pgfkeys{\pgfkeyscurrentpath/.get=\tmp@value}%
\expandafter \ifx \expandafter \pgfkeysnovalue \tmp@value
#2%
\else
#1%
\fi
},
.recommended/.style={%
\pgfkeyscurrentpath/.if given= %%%% This is the only line that changed
\relax
\PackageWarning{\PackageName}{Recommended key \pgfkeyscurrentkeyRAW' not given.}%
},
}
\makeatother


If I were you though, I would probably define a command \ifkeyisgiven or something and then call that in .recommended. I think this is clearer:

\makeatletter
\def\ifkeyisgiven#1#2{
\typeout{! path: \pgfkeyscurrentpath}%
\pgfkeys{\pgfkeyscurrentpath/.get=\tmp@value}%
\expandafter \ifx \expandafter \pgfkeysnovalue \tmp@value
#2%
\else
#1%
\fi
}

\pgfqkeys{/handlers}{%
recommended/.code={%
\ifkeyisgiven{}{
\Packagewarning{\PackageName}{Recommended key \pgfkeyscurrentkeyRAW' not given.}%
}
},
}
\makeatother
`
• thanks a lot, also for pointing out the naming convention. Somehow I thought to remember the leading dot was reserved for the default handlers defined by pgfkeys, but I was wrong: "It is recommended (but not necessary) that the name of a handler starts with a dot (but not with .@), so that they are easy to detect for the reader." (pgf manual for version 3.0.0, section 82.3.5 Keys That Are Handled, page 890). – jakun Oct 20 '17 at 5:57