检查 xkeyval 中是否设置了键

检查 xkeyval 中是否设置了键

我正在处理该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}

请注意,该解决方案直接作用于键值对列表,因此它不会检查键是否属于某个键系列。

相关内容