老板建议我使用 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
。
因此您可能希望测试三个键:
/MyKey
/MyKey/.@def
/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 中是不可行的。