我正在处理该xkeyval
包裹。
有时我想手动检查某个键是否包含在键列表中。
也就是说,我想要一个如下的 if 命令:
\contains@key{<family>}{<key value pairs>}{<key>}
{<execute if <key> is contained in <key value pairs>>}
{<execute if key is not contained>}
xkeyval 中是否已经有命令来实现这一点?
答案1
下面定义了一个完全可展开的宏,用于检查键是否在列表中。它用于expkv
循环遍历键=值对列表,并pdftexcmds
使其\pdf@strcmp
在所有引擎中可用。在此过程中,键名称不会以任何方式展开。宏需要两步展开才能完成其工作。
\documentclass{article}
\usepackage{expkv}
\usepackage{pdftexcmds}
\makeatletter
\newcommand\ifkeyinlistTF[1]
{\romannumeral\expandafter\ifkeyinlistTF@\detokenize{#1}\relax}
\long\def\ifkeyinlistTF@#1\relax#2%
{%
\ekvparse{\ifkeyinlistTF@k{#1}}{\ifkeyinlistTF@v{#1}}{#2}%
\ifkeyinlistTF@false
}
\newcommand\ifkeyinlistTF@k[2]
{\if0\pdf@strcmp{#1}{\unexpanded{#2}}\ifkeyinlistTF@true\fi}
\newcommand\ifkeyinlistTF@v[3]
{\if0\pdf@strcmp{#1}{\unexpanded{#2}}\ifkeyinlistTF@true\fi}
\newcommand\ifkeyinlistTF@false[2]{\z@#2}
\long\def\ifkeyinlistTF@true\fi#1\ifkeyinlistTF@false#2#3{\fi\z@#2}
\makeatother
\begin{document}
\edef\foo
{%
\ifkeyinlistTF{key}{a,b=c,d,e=f,g,h=i}{.}{a}%
\ifkeyinlistTF{key}{a,b=c,d,e=f,g,h=i,key}{i}{.}%
\ifkeyinlistTF{key}{a,b=c,d,e=f,g,h=i,keya}{.}{q}%
\ifkeyinlistTF{key}{a,b=c,d,e=f,g,h=i,key=a}{u}{.}%
\ifkeyinlistTF{key}{a,b=c,d,e=f,g,h=i,key=}{i}{.}%
\ifkeyinlistTF{key}{a,b=c,d,e=f,g,h=i, key=}{t}{.}%
\ifkeyinlistTF{\key}{a,b=c,d,e=f,g,h=i, \key =}{a}{.}%
}
\texttt{\meaning\foo}
\end{document}
输出:
答案2
我自己想出了如何实现一个命令,该命令接受一个键、一个键值对列表,并根据键是否出现在列表中来执行两个代码块中的一些代码。
该解决方案基于软件包的低级命令构建xkeyval
,因此如果您已经使用该软件包,则非常适合。至少我使用该命令以及在 中设置键xkeyval
。
为了进行比较,我使用ifthen
可以被任何其他足够机制替代的包。
解决方案如下:
% !TEX TS-program = pdflatex
\documentclass{article}
\usepackage{xkeyval}
\usepackage{ifthen}
\begin{document}
\makeatletter
\newcommand{\if@contains@key}[4]{%
\XKV@checksanitizea{#2}\XKV@resb%
\newif\ifkey@found\key@foundfalse% set to true right after the key was found, otherwise remains false
\XKV@for@o\XKV@resb\XKV@tempa{% loop over the key-value pairs
% the following two lines extract the key from the pair and remove trailing whitespace (same solution as in \setkeys of xkeyval)
\expandafter\XKV@g@tkeyname\XKV@tempa=\@nil\XKV@tempa%
\expandafter\KV@@sp@def\expandafter\XKV@tempa\expandafter{\XKV@tempa}%
\ifthenelse{\equal{#1}{\XKV@tempa}}%
{\key@foundtrue}{}%
}%
\ifkey@found%
#3%
\else%
#4%
\fi%
}
\if@contains@key{welt}{hallo={}, welt={}}
{Hallo}
{Welt}
\makeatother
\end{document}
请注意,该解决方案直接作用于键值对列表,因此它不会检查键是否属于某个键系列。