我正在尝试使用 xparse 库和 xkeyval 为可选键值对制作一个宏。下面是我正在尝试做的一个简单示例
系统管理员
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{cmd}
\RequirePackage{xparse}
\RequirePackage{xkeyval}
\define@key{keyvalTest}{width}{\def\kt@width{#1}}
\define@key{keyvalTest}{caption}{\def\kt@caption{#1}}
\NewDocumentCommand{\keyvalTest}{ o m }{
\begingroup
% Set the default values, and override any extra if any optional arguments are present, else just set the default values
\IfValueTF{#1}
{\setkeys{keyvalTest}{width={50mm}, caption=\NoValue, #1}}
{\setkeys{keyvalTest}{width={50mm}, caption=\NoValue}}
\noindent
Path: #2 \\
Width: \kt@width \\
% Should print the caption if specified as an optional arg, else print "No Caption"
\IfValueTF{\kt@caption}
{Caption: \kt@caption}
{No Caption}
\endgroup
}
主文本
\documentclass{article}
\usepackage{cmd}
\begin{document}
\keyvalTest{diagrams/pathToDiagram.pdf} \\
\keyvalTest[caption={hello}, width=3cm]{diagrams/pathToDiagram.pdf}
\end{document}
这个例子给了我这样的:
并出现错误,指出\NoValue{}
未定义。我只看到它在几个地方使用(例如这里),但我从未见过它在实际代码中使用。我猜它可能已被弃用,或者仅对 expl3 有效?
我经历过xparse 的文档找不到任何可以充当 NoValue 的宏。我也尝试过阅读它的源代码,但如果可能的话,我想避免使用 expl3。
我想知道我应该从哪里开始。我应该使用空白,并使用某种isblank
或isempty
函数,还是有更好的方法来解决这个问题?我认为在缺少命名可选参数时执行 if else 逻辑会很常见,但我似乎在任何地方都找不到任何示例。
答案1
\IfValueTF
正在检查您是否具有特殊字符序列,-NoValue-
并在参数中设置了不太可能的类别代码。更好的方法是简单地检查是否\kt@caption
已设置。您可以使用内部 LaTeX 命令\@ifundefined
来管理此问题,方法是将您的定义重写为\keyvalTest
:
\NewDocumentCommand{\keyvalTest}{o m}{
\IfValueTF{#1}
{\setkeys{keyvaltest}{width=50mm,#1}}
{\setkeys{keyvaltest}{width=50mm}}
\noindent
Path: #2 \\
Width: \kt@width \\
% Should print the caption if specified as an optional arg, else print "No Caption"
\@ifundefined{kt@caption}
{No Caption}
{Caption: \kt@caption}
}
或者,您可以使用 e-TeX 命令\ifdefined
,该命令使用 TeX 的低级 if 机制,并避免 2018 年之前的 LaTeX 出现问题。将\@ifundefined
序列替换为:
\ifdefined\kt@caption
Caption: \kt@caption
\else
No Caption
\fi
答案2
我不会xkeyval
与混合使用expl3
,它具有自己的键值接口,并且在许多方面优于xkeyval
。
文件cmd.sty
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{cmd}
%\RequirePackage{xparse} % not needed for LaTeX 2020-10-01 or later
\ExplSyntaxOn
\keys_define:nn { hsevenxfour/cmd }
{
width .dim_set:N = \l__hsevenxfour_cmd_width_dim,
width .initial:n = 50mm,
caption .tl_set:N = \l__hsevenxfour_cmd_caption_tl,
}
\NewDocumentCommand{\keyvalTest}{ O{} m }
{
\group_begin:
\keys_set:nn { hsevenxfour/cmd } { #1 }
\noindent
Path:~#2 \\
Width:~\dim_eval:n { \l__hsevenxfour_cmd_width_dim } \\
% Should print the caption if specified as an optional arg, else print "No Caption"
\tl_if_empty:NTF \l__hsevenxfour_cmd_caption_tl
{
No~caption
}
{
Caption:~\tl_use:N \l__hsevenxfour_cmd_caption_tl
}
\group_end:
}
\ExplSyntaxOff
文件test.tex
\documentclass{article}
\usepackage{cmd}
\begin{document}
\noindent
\keyvalTest{diagrams/pathToDiagram.pdf}
\noindent
\keyvalTest[caption={hello}, width=3cm]{diagrams/pathToDiagram.pdf}
\end{document}