4

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?

1 Answer 1

3

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
1
  • 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, 2017 at 5:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .