1

By boss advised me to use the pgfkeys-package. So I ended up trying to work through this inscrutable nightmare which is called pgfmanual.pdf.

In order not to erroneously override keys defined by others I'd like a reliable check for finding out if a key is already defined or already has some properties like .value required or .value forbidden or .default or .code or whatever.

\pgfkeysifdefined only checks whether a key serves the purpose of storing a value - compiling the following example brings up the message !!!NOT DEFINED!!! although the key /pgfmanual/is inscrutable is defined to carry out some code:

\documentclass{article}

\usepackage{pgfkeys}

\pgfkeys{%
%  /pgfmanual/is inscrutable/.value required,
%  /pgfmanual/is inscrutable/.initial=indeed inscrutable,
%  /pgfmanual/is inscrutable={inscrutable, indeed!},
  /pgfmanual/is inscrutable/.code=Argument: #1,
}%

\pgfkeysifdefined{/pgfmanual/is inscrutable}{\message{^^J^^J!!!DEFINED!!!^^J^^J}}{\message{^^J^^J!!!NOT DEFINED!!!^^J^^J}}%

\begin{document}

\end{document}

Compiling the following example brings up the message !!!NOT DEFINED!!! although a value is required with the key /pgfmanual/is inscrutable which implies intentions of sooner or later using that key:

\documentclass{article}

\usepackage{pgfkeys}

\pgfkeys{%
  /pgfmanual/is inscrutable/.value required,
%  /pgfmanual/is inscrutable/.initial=indeed inscrutable,
%  /pgfmanual/is inscrutable={inscrutable, indeed!},
%  /pgfmanual/is inscrutable/.code=Argument: #1,
}%

\pgfkeysifdefined{/pgfmanual/is inscrutable}{\message{^^J^^J!!!DEFINED!!!^^J^^J}}{\message{^^J^^J!!!NOT DEFINED!!!^^J^^J}}%

\begin{document}

\end{document}
6
  • I didn't understand pgfkeys very well, but so that your keys can't be confused with others, you just have to define a home directory by doing for example /marsupial/.cd.
    – AndréC
    Aug 15, 2020 at 21:39
  • @AndréC Changing the default-path to /marsupial does not prevent you from probably overriding things that are already stored in that path. Aug 15, 2020 at 22:49
  • @UlrichDiez This prevents overwriting keys with the same name that have another absolute path. This is how you can define keys with the same name, they are differentiated by their path. And nothing says here that the other definitions have the same absolute path. Thus, if the path where the keys are defined is its own, the other keys of the same name (and of different absolute path) are not modified.
    – AndréC
    Aug 16, 2020 at 3:56
  • @AndréC What you say is correct, but I still don't see reliablle means in pgfkeys for preventing working with an absolute path or "directory" which already is used by some other routine. I only see means for checking the existence of specific keys (full path + name of key). Aug 16, 2020 at 10:14
  • As other comment say: why are you not picking a unique name in the tree?
    – Joseph Wright
    Aug 22, 2020 at 9:58

1 Answer 1

1

Read the manual carefully - it says that applying the handler

  • /.code (or one of its variants) yields defining a sub-key .@cmd.
  • /.default yields defining a sub-key .@def.

I.e., /MyKey/.code=Whatsoever code yields defining a sub-key /MyKey/.@cmd.

I.e., /MyKey/.default=Whatsoever default value yields defining a sub-key /MyKey/.@def.

Thus you may wish to test for three keys:

  1. /MyKey
  2. /MyKey/.@def
  3. /MyKey/.@cmd

You can do:

\documentclass{article}

\usepackage{pgfkeys}

\makeatletter

\newcommand\CheckWhetherFullKeyDefined[1]{%
  \pgfkeysifdefined{#1}{\expandafter\@firstoftwo}{\expandafter\@secondoftwo}%
  {\@firstoftwo}{%
    \pgfkeysifdefined{#1/.@def}{\expandafter\@firstoftwo}{\expandafter\@secondoftwo}%
    {\@firstoftwo}{%
      \pgfkeysifdefined{#1/.@cmd}{\expandafter\@firstoftwo}{\expandafter\@secondoftwo}%
      {\@firstoftwo}{\@secondoftwo}%
    }%
  }%
}%

\makeatother

\begin{document}

\begingroup
\pgfkeys{/WeirdKey/.code=Code of WeirdKey with argument #1}%
\CheckWhetherFullKeyDefined{/WeirdKey}%
                           {\message{^^J^^J!!!/WeirdKey DEFINED!!!^^J^^J}}%
                           {\message{^^J^^J!!!/WeirdKey NOT DEFINED!!!^^J^^J}}%
\endgroup


\begingroup
\pgfkeys{/WeirdKey/.initial=Initial value of WeirdKey}%
\CheckWhetherFullKeyDefined{/WeirdKey}%
                           {\message{^^J^^J!!!/WeirdKey DEFINED!!!^^J^^J}}%
                           {\message{^^J^^J!!!/WeirdKey NOT DEFINED!!!^^J^^J}}%
\endgroup


\begingroup
\CheckWhetherFullKeyDefined{/WeirdKey}%
                           {\message{^^J^^J!!!/WeirdKey DEFINED!!!^^J^^J}}%
                           {\message{^^J^^J!!!/WeirdKey NOT DEFINED!!!^^J^^J}}%
\endgroup

\end{document}

Alternatively you can use the .try-handler for .cd-ing to the key in question only if it exists.

I use the .cd-handler because the manual says that \pgfkeys in any case will reset the default-path to what it was before executing \pgfkeys.

(I hope \pgfkeys will never be changed to using the .cd-handler for resetting - if it does, then resetting to a default-path which does not exist as a key as well might be a problem.)

\documentclass{article}

\usepackage{pgfkeys}

\makeatletter
\newcommand\CheckWhetherFullKeyDefined[1]{%
  \begingroup
  \pgfkeys{%
     % Apply handlers not in the exception-list only to existing keys:
     /handler config=only existing,
     % Remove the /.cd-handler from the exception-list:
     /utils/exec={\expandafter\let\csname pgfk@excpt@.cd\endcsname=\UndEFiNeD},
     % Try the /.cd-handler - the /.try-handler  will set \ifpgfkeyssuccess:
     #1/.cd/.try,
  }%
  \expandafter\endgroup\ifpgfkeyssuccess\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
}%
\makeatother

\begin{document}

\begingroup
\pgfkeys{/WeirdKey/.code=Code of WeirdKey with argument #1}%
\CheckWhetherFullKeyDefined{/WeirdKey}
                           {\message{^^J^^J!!!/WeirdKey DEFINED!!!^^J^^J}}%
                           {\message{^^J^^J!!!/WeirdKey NOT DEFINED!!!^^J^^J}}%
\endgroup


\begingroup
\pgfkeys{/WeirdKey/.initial=Initial value of WeirdKey}%
\CheckWhetherFullKeyDefined{/WeirdKey}
                           {\message{^^J^^J!!!/WeirdKey DEFINED!!!^^J^^J}}%
                           {\message{^^J^^J!!!/WeirdKey NOT DEFINED!!!^^J^^J}}%
\endgroup


\begingroup
\CheckWhetherFullKeyDefined{/WeirdKey}
                           {\message{^^J^^J!!!/WeirdKey DEFINED!!!^^J^^J}}%
                           {\message{^^J^^J!!!/WeirdKey NOT DEFINED!!!^^J^^J}}%
\endgroup

\end{document}

Be aware that you can check for an enitre key (path and name of key) only, but not for the "existence" of some "directory"/"folder" of the path of a key:

Management of keys internally is done by defining macros whose names contain the entire key.

Thus the "directory" /MyStuff can "exist" due to the key /MyStuff/SubDirectory/SubSubDirectory/MyKey being defined, implying that underlying macros are defined whose names contain the phrase pgfk@/MyStuff/SubDirectory/SubSubDirectory/MyKey, e.g., \pgfk@/MyStuff/SubDirectory/SubSubDirectory/MyKey and probably \pgfk@/MyStuff/SubDirectory/SubSubDirectory/MyKey/.@def or \pgfk@/MyStuff/SubDirectory/SubSubDirectory/MyKey/.@cmd.

For checking whether the "directory" /MyStuff exists, you'd need to know if some macro is defined whose name is pgfk@/MyStuff or whose name's first letters form the phrase pgfk@/MyStuff/ while there might be an arbitrary sequence of letters in that macro-name trailing that phrase. Afaik such a test is not feasible in TeX.

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.