3

I'm trying to define a subtree of my tree of pgfkeys keys such that any key, at any path under that subtree, will be assignable without having to previously define the key.

In other words, I would like any path under /mykeys/ to be assignable without a previous definition, like:

\pgfkeys{/mykeys/key=hello} % ok
\pgfkeys{/mykeys/nested/key=hello} % ok
\pgfkeys{/mykeys/any/arbitrarily/nested/key=hello} % still ok

The original idea was to install an .unknown handler to silently initialize the key with the given value and go on. However, it seems this approach only works for the first level of the tree, i.e. for the first line of the above example. I've also tried using the .unknown handler to install an .unknown handler inside the unknown key itself, but the handler seems to be not called when the key is used as part of a path.

To be clear: I don't know in advance the key paths that will be used: I need it to work for any arbitrary path inside /mykeys.

The code I tried is the following:

\documentclass{article}

\usepackage{pgfkeys}

\newcommand\unknown[1]{%
  \def\@key{\pgfkeyscurrentpath/\pgfkeyscurrentname}%
  \pgfkeyssetvalue{\@key}{#1}%
  \pgfkeys{\@key/.unknown/.code = {\unknown{#1}}}
}

\pgfkeys{
  /mykeys/.unknown/.code = {\unknown{#1}}
}

\begin{document}

\section{Hello}
\pgfkeys{/mykeys/key=hello}
Value: \pgfkeysvalueof{/mykeys/key}

\pgfkeys{/mykeys/nested/key=hello}
Value: \pgfkeysvalueof{/mykeys/nested/key}

\end{document}

As you can see, the first invocation of \pgfkeys works, and \pgfkeysvalueof returns the correct value, while the second doesn't.

How can I achieve the desired effect?

2

I am surprised because I thought that defining your keys as:

\pgfkeys{/mykeys/.is family, /mykeys, 
    .unknown/.code = {
        \pgfkeyssetvalue{\pgfkeyscurrentpath/\pgfkeyscurrentname}{#‌​1}
    }
}

would do what you want, but the unknown handler is not applying recursively. It seems that one way out is to override the generic .unknown handler:

\documentclass{article}

\usepackage{pgfkeys}

\pgfkeys{/mykeys/.is family, /mykeys}

\pgfkeys{/handlers/.unknown/.code = {
    \pgfkeyssetvalue{\pgfkeyscurrentpath/\pgfkeyscurrentname}{#1}
  },
}

\begin{document}

\section{Hello}
\pgfkeys{/mykeys/key=hello}
Value: \pgfkeysvalueof{/mykeys/key}

\pgfkeys{/mykeys/nested/key=hello}
Value: \pgfkeysvalueof{/mykeys/nested/key}

\end{document}

This produces the wanted output:

enter image description here

Of course, now every unknown key will be set this way, which may have unwanted side effects

  • Interesting! Can’t one save the old unknown handler and call it when \pgfkeyscurrentpath does not start with /mykeys? – gigabytes Nov 29 '17 at 15:06
  • @gigabytes Probably. I thought about this but it seems painful to test if \pgfkeyscurrentpath starts with /mykeys. Quite likely, pgfkeys provides a mechanism for doing this but I don't know it. I was hoping that one of the pgf experts on TeX.SX would provide a "better" solution:) – Andrew Nov 29 '17 at 15:13
  • I think one has to resort to generic string manipulation techniques. – gigabytes Nov 29 '17 at 15:14
0

I've been looking for a solution to this same problem without much luck as well.

This seems to work (not very thoroughly tested, and if someone has a better solution, I'd love to see it)

\usepackage{xstring}
\pgfkeys{/handlers/.unknown/.code=
  {%
    \IfBeginWith{\pgfkeyscurrentkey}{/myprefix}{%
      \pgfkeyssetvalue{\pgfkeyscurrentpath/\pgfkeyscurrentname}{#1}%
    }{%
      {Unknown key ‘\pgfkeyscurrentkey’.}%
    }%
  }%
}%

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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