pgfkeys - 如何检查密钥是否已定义?

pgfkeys - 如何检查密钥是否已定义?

老板建议我使用 pgfkeys 包。所以我最终尝试解决这个名为 pgfmanual.pdf 的难以捉摸的噩梦。

为了不错误地覆盖其他人定义的键,我希望进行可靠的检查,以查明某个键是否已定义或已具有某些属性,如.value required.value forbidden.default.code等等。

\pgfkeysifdefined仅检查键是否用于存储值 -!!!NOT DEFINED!!!尽管键/pgfmanual/is inscrutable被定义为执行某些代码,但编译以下示例仍会显示消息:

\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}

编译以下示例会显示以下消息,!!!NOT DEFINED!!!尽管密钥需要一个值,/pgfmanual/is inscrutable但这意味着迟早会使用该密钥的意图:

\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}

答案1

仔细阅读手册 - 它说应用处理程序

  • /.code(或其变体之一)产生定义子键.@cmd
  • /.default产生定义子键的结果.@def

即,/MyKey/.code=Whatsoever code产生定义子键的结果/MyKey/.@cmd

即,/MyKey/.default=Whatsoever default value产生定义子键的结果/MyKey/.@def

因此您可能希望测试三个键:

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

你可以做:

\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}

或者,只有当相关键存在时,您才可以使用.try-handler 来对其进行处理。.cd

我使用.cd-handler 是因为手册说\pgfkeys在任何情况下都会将默认路径重置为执行之前的状态\pgfkeys

(我希望\pgfkeys永远不会改为使用.cd-handler 进行重置 - 如果是这样,那么重置为不存在作为键的默认路径可能会有问题。)

\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@[email protected]\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}

请注意,您只能检查整个密钥(密钥的路径和名称),而不能检查密钥路径的某些“目录”/“文件夹”是否存在:

内部密钥的管理是通过定义名称包含整个密钥的宏来完成的。

因此“目录”/MyStuff可以由于键/MyStuff/SubDirectory/SubSubDirectory/MyKey被定义而“存在”,暗示定义了名称包含短语的底层宏pgfk@/MyStuff/SubDirectory/SubSubDirectory/MyKey,例如,\pgfk@/MyStuff/SubDirectory/SubSubDirectory/MyKey和可能\pgfk@/MyStuff/SubDirectory/SubSubDirectory/MyKey/.@def\pgfk@/MyStuff/SubDirectory/SubSubDirectory/MyKey/.@cmd

要检查“目录”是否/MyStuff存在,您需要知道是否定义了某个宏,其名称为pgfk@/MyStuff或名称的首字母构成该短语pgfk@/MyStuff/,而该宏名称中可能存在任意字母序列,紧随该短语之后。据我所知,这种测试在 TeX 中是不可行的。

相关内容