我有一些命令,其命名参数由 pgfkeys 处理
\dog[breed=Labrador, name=Fido]
\human[name=John, car owned=Porsche]
我该如何安排
\dog[breed=Labrador, car owned=Rover]
给出错误信息Invalid key 'car owned'
,并且
\dog[name=Fido]
给出错误信息Missing required key 'breed'
?
这里有一个可以用作起点的 MWE。
\documentclass{article}
\usepackage{pgfkeys}
\makeatletter
\pgfkeys{/wickerson/.cd,
breed/.store in = {\wickerson@breed},
name/.store in = {\wickerson@name},
car owned/.store in = {\wickerson@carowned}
}
\newcommand*\dog[1][]{%
\pgfkeys{/wickerson/.cd, name=noName, breed=noBreed, #1}
Dog is a {\wickerson@breed} and is called {\wickerson@name}.\par
}
\newcommand*\human[1][]{%
\pgfkeys{/wickerson/.cd, name=noName, car owned=noCar, #1}
Human is called {\wickerson@name} and owns a {\wickerson@carowned}.\par
}
\makeatother
\begin{document}
\dog[breed=Labrador, name=Fido] % GOOD
\human[name=John, car owned=Porsche] % GOOD
\dog[breed=Labrador, car owned=Rover] % BAD (irrelevant key given)
\dog[name=Fido] % BAD (required key missing)
\end{document}
答案1
根据要求将评论转换为答案。请注意,这是我第一次使用键值系统,因此不确定这种方法是否存在任何问题,但它确实满足了这个特定示例的两个要求:
- 只能指定有效的密钥
- 未指定的键将被标记为错误
dogkeys
通过定义单独的和可以满足第一个要求humankeys
。对于第二个要求,我们可以检查字符串值是否是默认值,以了解未提供该值。
笔记:
包裹
xstring
用于字符串比较。这两个错误情况已被注释掉。否则将按预期产生错误。
代码:
\documentclass{article}
\usepackage{pgfkeys}
\usepackage{xstring}
\makeatletter
\pgfkeys{/dogkeys/.cd,
breed/.store in = {\wickerson@breed},
name/.store in = {\wickerson@name},
}
\pgfkeys{/humankeys/.cd,
name/.store in = {\wickerson@name},
car owned/.store in = {\wickerson@carowned}
}
\newcommand*\CheckKeyIsNotDefaultValue[4]{%
% #1 = package name (for error reporting)
% #2 = key name
% #3 = default key value (report error if key value matches)
% #4 = actual value of key
\IfStrEq{#4}{#3}{%
\PackageError{#1}{Key '#2' not provided.}{}%
}{}%
}
\newcommand*\dog[1][]{%
\pgfkeys{/dogkeys/.cd, name=noName, breed=noBreed, #1}
\CheckKeyIsNotDefaultValue{dogkeys}{breed}{noBreed}{\wickerson@breed}%
\CheckKeyIsNotDefaultValue{dogkeys}{name}{noName}{\wickerson@name}%
Dog is a {\wickerson@breed} and is called {\wickerson@name}.\par
}
\newcommand*\human[1][]{%
\pgfkeys{/humankeys/.cd, name=noName, car owned=noCar, #1}
\CheckKeyIsNotDefaultValue{humankeys}{name}{noName}{\wickerson@name}%
\CheckKeyIsNotDefaultValue{humankeys}{car owned}{noCar}{\wickerson@carowned}%
Human is called {\wickerson@name} and owns a {\wickerson@carowned}.\par
}
\makeatother
\begin{document}
\dog[breed=Labrador, name=Fido] % GOOD
\human[name=John, car owned=Porsche] % GOOD
%\dog[breed=Labrador, car owned=Rover] % BAD (irrelevant key given)
%\dog[breed=Fido] % BAD (required key missing)
\end{document}
答案2
为了禁止某些键(或者更确切地说,只允许某些键),我会将所有键定义为/wickerson/dog
和的子键/wickerson/human
。然后,您还可以安装/wickerson/dog/.unknown
在调用未知键时执行的键(尽管此解决方案不知道所讨论的键在另一个上下文中是否有效)。
以下示例会引发错误
! Package Wickerson Error: The key "car owned" is not known in the "dog" context..
\documentclass{article}
\usepackage{pgfkeys}
\makeatletter
\pgfkeys{/wickerson/.cd,
dog/breed/.store in = {\wickerson@breed},
dog/name/.store in = {\wickerson@name},
dog/.unknown/.code= {\PackageError{Wickerson}{The key "\pgfkeyscurrentkeyRAW" is not known in the "dog" context.}{}},
human/name/.store in = {\wickerson@name},
human/car owned/.store in = {\wickerson@carowned},
human/.unknown/.code= {\PackageError{Wickerson}{The key "\pgfkeyscurrentkeyRAW" is not known in the "human" context.}{}},
}
\newcommand*\dog[1][]{%
\pgfkeys{/wickerson/dog/.cd, name=noName, breed=noBreed, #1}
Dog is a {\wickerson@breed} and is called {\wickerson@name}.\par
}
\newcommand*\human[1][]{%
\pgfkeys{/wickerson/human/.cd, name=noName, car owned=noCar, #1}
Human is called {\wickerson@name} and owns a {\wickerson@carowned}.\par
}
\makeatother
\begin{document}
\dog[breed=Labrador, name=Fido] % GOOD
\human[name=John, car owned=Porsche] % GOOD
\dog[breed=Labrador, car owned=Rover] % BAD (irrelevant key given)
\dog[name=Fido] % BAD (required key missing)
\end{document}