在不知道输入的确切形式的情况下如何使用 pgfkeys 的 /.style args 处理程序?

在不知道输入的确切形式的情况下如何使用 pgfkeys 的 /.style args 处理程序?

我希望能够创建一个命令(使用pgfkeys),该命令可以接受有限形式的输入,并且某些部分将来自一组有限的值。更具体地说,任何输入都会有一些部分A(来自已知列表),并且对于某些值A,附加信息#1#2等(不是来自已知列表)也可以使用一组有限的形式来指定,但不必如此。

举个虚构的例子,假设我的命令是\meal,并且A将成为列表的一个元素

chicken, beef, tofu

Achicken或时beef,以下形式的附加信息可以这样指定:

chicken with #1
chicken on a bed of #1
beef with #1
beef with #1 or #2

我希望最大可能的多功能性一旦确定了正确的形式,并且理解了输入,会发生什么。例如,假设我想要

\meal{chicken}                                ->   Chicken
\meal{chicken with #1}                 ->   CHICKEN (with #1? uggh)
\meal{chicken on a bed of #1}    ->   #1, underneath chicken
\meal{beef}                                      ->   Beef
\meal{beef with #1}                       ->   Beef and a side of #1
\meal{beef with #1 or #2}           ->   Beef with your choice of #1 or #2 as a side
\meal{tofu}                                      ->   Tofu

我意识到这已经是一个相当艰巨的任务了(哈哈),但为了简单起见,假设我们永远不需要写

\meal{chicken on a bed of beef with chicken}

或其他会让计算机感到困惑的东西。

现在,我正在做一些初步测试(在尝试制作一个可以完成我想要的所有事情的东西之前),然后遇到了一个问题。我写的代码,在适应这个虚构的例子之后,将是

\documentclass{article}
\usepackage{pgfkeys}
\pgfkeys{%
    mealname/.initial = ,%
    overform/.style args = {#1 over #2}{mealname = #1 over #2},%
    andform/.style args  = {#1 and #2}{mealname = #1 and #2}%
    noform/.style        = {mealname = #1}%
}
\newcommand{\meal}[1]{%
\pgfkeys{%
    overform/.try  = #1,%
    andform/.retry = #1,%
    noform/.retry  = #1,%
    mealname/.get  = \mealname}%
\mealname%
}

\begin{document}

\meal{A over B}

\end{document}

运行正常;但是,当我A over B用替换时A and B,出现错误

File ended while scanning use of \pgfkeys@code

我假设发生的事情是,它pgfkeys试图over在输入中找到该单词的出现A and B,但陷入了无限循环,或者因为找不到而以某种方式中断。我曾希望在over任何地方都找不到后,会抛出一个错误并告知/.try停止,但事实似乎并非如此。

现在,我意识到我所要求的可能有点愚蠢,因为那pgfkeys是针对“键值参数”的,因为一个更容易编码(但使用起来稍微不太直观)的解决方案是让每种不同的形式(chicken,,chicken with等等)成为它自己的键,并接受如下输入:

\meal{chicken}
\meal{chicken with = #1}
...

或者,让 的每个值A成为一个家族,形式为子键;例如,调用键chicken会将/.cd我们带入/chicken/家族,其中有键/chicken/with/chicken/on a bed of,这样就可以写

\meal{chicken}
\meal{chicken, with = #1}
...

也许我只是过于挑剔,想要避免使用等号;但在最大程度上,我希望我的文档代码能够模拟自然的英语表达(除了只是想弄清楚如何应对挑战/出于好奇)。

因此,我的问题是:有什么方法可以实现我想要的命令吗pgfkeys? 还有其他包或方法可以做到这一点吗? 假设我的方法至少在某种程度上是正确的:有什么方法可以使用/.style args键处理程序(也许与/.try处理程序一起使用?)来确定输入的形式,并对该形式执行正确的操作,而不会陷入无限循环,试图测试输入是否是给定的形式?

答案1

您可以执行以下操作。

不过,这并没有检查太多。所以你可以说

\meal{Tofu with something}

而不会引发错误。

代码

\documentclass{article}
\usepackage{pgf,pgfkeys}
\makeatletter
\newcommand*{\kitchenset}{\pgfqkeys{/kitchen}}
\newcommand*{\kitchenalso}{\pgfqkeysalso{/kitchen}}
\newcommand*{\qrr@pgfutil@in@}[2]{%
    \pgfutil@in@{#1}{#2}%
    \ifpgfutil@in@
        \expandafter\pgfutil@firstoftwo
    \else
        \expandafter\pgfutil@secondoftwo
    \fi
}
\kitchenset{
    mealname/.initial=Nothing,
    mealwith/.initial=nothing,
    mealwithor/.initial=nothing,
    mealbed/.initial=a plate,
    @meal/.code={%
        \qrr@pgfutil@in@
            { with }{#1}
            {\kitchenalso{@meal with={#1}}}
            {%
                \qrr@pgfutil@in@
                    { on a bed of }{#1}
                    {\kitchenalso{@meal bed={#1}}}
                    {\kitchenalso{mealname={#1}}}%
            }%
    },
    @meal with/.code args={#1 with #2}{%
        \kitchenalso{mealname={#1}}
        \qrr@pgfutil@in@
            { or }{#2}
            {\kitchenalso{@meal with or={#2}}}
            {\kitchenalso{mealwith={#2}}}%
    },
    @meal with or/.style args={#1 or #2}{%
        mealwith={#1},
        mealwithor={#2},
    },
    @meal bed/.style args={#1 on a bed of #2}{%
        mealname={#1},
        mealbed={#2},
    }
}
\makeatother

\newcommand*{\kitchenvalues}{%
    Meal: \pgfkeysvalueof{/kitchen/mealname} with \pgfkeysvalueof{/kitchen/mealwith} (or \pgfkeysvalueof{/kitchen/mealwithor}) on a bed of \pgfkeysvalueof{/kitchen/mealbed}.}

\newcommand*{\meal}[1]{%
    \begingroup
        \kitchenset{@meal={#1}}%
        \kitchenvalues
    \endgroup}
\begin{document}
\meal{xxx}

\meal{Beef}

\meal{Beef with Salad}

\meal{Beef with Salad or French Fries}
\end{document}

输出

在此处输入图片描述

相关内容