pgfkey 包含具有可变数量值的 foreach 语句

pgfkey 包含具有可变数量值的 foreach 语句

我想在宏中使用 pgfkeys。一个键包含一个 foreach 语句,该语句处理可变数量的值。我对输出的正确顺序有些疑问。这里有一个简化的示例:

\documentclass[article]{memoir}
\usepackage[latin]{babel}
\usepackage{algpseudocode}
\usepackage{pgfkeys}

\pgfkeys{%
/test/.is family,
/test/.cd,
    key a/.store in = \keyA,
    key a print/.code = \texttt{\keyA},
    key b/.code = {\foreach \x in {#1}{\textbf{\x}--}}
}%

\newcommand\mymacro[1]{\pgfkeys{/test, #1, key a print}}

\begin{document}
\mymacro{key a = valueKeyA, key b = {valueKeyB1, valueKeyB2, valueKeyB3}}
\end{document}

输出的顺序为:valueKeyB1–valueKeyB2–valueKeyB3–valueKeyA

我如何才能实现首先对 valueKeyA 进行排版?如果我在示例代码中将 #1 放在键列表的末尾,则会收到错误消息。如果我在实际代码中将其放在键列表的末尾,则会缺少第一个键的值。我猜这要么与值的存储顺序和键的执行顺序有关,要么是我对 #1 的使用混淆了。

我使用 pgfkeys 的时间不长,如果有人能给我提示我会很高兴。

答案1

目前,按键按以下顺序执行:

  1. key a = valueKeyA. 这存储valueKeyA在宏中\keyA
  2. key b = {valueKeyB1, valueKeyB2, valueKeyB3}. 打印输出valueKeyB1--valueKeyB2--valueKeyB3--(忽略格式)
  3. key a print. 这将打印出\keyA扩展为 的内容valueKeyA

因此,问题在于,对于key a,处理分为两个部分:存储和打印,而对于 ,key b这一切都在一个步骤中完成。调用事物的顺序意味着 的两个步骤a被 的一个步骤分开b。有多种方法可以解决这个问题,具体取决于您想要实现的目标。

在给出一些之前,让我解释一下为什么放在#1最后不起作用。这是因为这样会把步骤 3 放在上面第一的,然后它会尝试打印出\keyA尚未设置的值。

正如我所说,如何修复此问题取决于你想在实际代码中做什么。以下是一些。

  1. key a print参数内部放到\mymacro正确的位置,因此我们有:

    \newcommand\mymacro[1]{\pgfkeys{/test, #1}}
    
    \begin{document}
    \mymacro{key a = valueKeyA, key a print, key b = {valueKeyB1, valueKeyB2, valueKeyB3}}
    
  2. 使key a步骤同时存储和打印其值,例如:

    \pgfkeys{/test/.cd, key a/.code={\def\keyA{#1}\texttt{#1}}}
    

    key a print然后从各处移除。

  3. key b步骤将其结果存储在宏中,以便稍后打印出来。例如:

    \pgfkeys{/test/.cd, key b/.code={\def\keyB{}\foreach \x in {#1}{\expandafter\gdef\expandafter\keyB\expandafter{\keyB\textbf{\x}--}}}, key b print/.code={\keyB}}
    

    key b print然后添加key a print(或合并print all keys)。

可能还有更多——即使它们没有被证明是有用的,它们也应该可以帮助您弄清楚您想要的解决方案的功能。


编辑:2013-06-20

第三个解决方案在扩展方面有点问题。\x在 的定义中, 至少需要扩展一次。如果所有内容都可以在定义时扩展,那么可以使用而不是 来\keyB实现。如果不行,那么就会出现一大堆s。\protected@xdef\gdef\expandafter

说实话,LaTeX3所以对于这种事情来说要容易得多,所以我添加了一个与 PGF foreach 非常接近的 LaTeX3 版本(细微的差别在于我在显示时而不是定义时迭代键列表)。我可能会做些稍微不同的事情,因为我不会费心将key a printkey b print作为键,而只是作为命令。但我会密切关注您的代码,以便您可以看到相似之处和不同之处。

以下均产生:

valueKeyA值键B1--值键B2--值键B3

\documentclass[article]{memoir}
%\url{http://tex.stackexchange.com/q/54533/86}
\usepackage[latin]{babel}
\usepackage{algpseudocode}
\usepackage{pgfkeys}
\usepackage{pgffor}
\usepackage{xparse,expl3}

\pgfkeys{%
/test/.is family,
/test/.cd,
    key a/.store in = \keyA,
    key a print/.code = \texttt{\keyA},
    key b/.code = {%
      \let\keyB=\relax%
      \foreach \x in {#1} {%
        \ifx\keyB\relax
        \expandafter\gdef\expandafter\keyB\expandafter{\expandafter\textbf\expandafter{\x}}%
        \else
        \expandafter\expandafter\expandafter\gdef\expandafter\expandafter\expandafter\keyB\expandafter\expandafter\expandafter{%
          \expandafter\keyB\expandafter-\expandafter-\expandafter\textbf\expandafter{\x}%
        }%
        \fi
      }%
    },
    key b print/.code={\keyB}
}%

\makeatletter
\pgfkeys{%
/xtest/.is family,
/xtest/.cd,
    key a/.store in = \keyA,
    key a print/.code = \texttt{\keyA},
    key b/.code = {%
      \let\keyB=\relax%
      \foreach \x in {#1} {%
        \ifx\keyB\relax
        \protected@xdef\keyB{\protect\textbf{\x}}%
        \else
        \protected@xdef\keyB{%
          \keyB--\protect\textbf{\x}%
        }%
        \fi
      }%
    },
    key b print/.code={\keyB}
}%
\makeatother

\ExplSyntaxOn

\tl_new:N \l__aik_keya_tl
\clist_new:N \l__aik_keyb_clist
\keys_define:nn {3test}
{
  key~ a .tl_set:N = \l__aik_keya_tl,
  key~ b .clist_set:N = \l__aik_keyb_clist,
  key~ a~ print .code:n = {
    \texttt{\tl_use:N \l__aik_keya_tl}
  },
  key~ b~ print .code:n = {
    \tl_clear:N \l_tmpa_tl
    \clist_map_inline:Nn \l__aik_keyb_clist
    {
      \tl_use:N \l_tmpa_tl \textbf{##1}
      \tl_set:Nn \l_tmpa_tl {--}
    }
  }
}

\NewDocumentCommand \mytmacro {m}
{
  \keys_set:nn {3test} {#1, key~ a~ print, key~ b~ print}
}

\ExplSyntaxOff

\newcommand\mymacro[1]{\pgfkeys{/test, #1, key a print, key b print}}
\newcommand\myxmacro[1]{\pgfkeys{/xtest, #1, key a print, key b print}}

\begin{document}
\mymacro{key a = valueKeyA, key b = {valueKeyB1, valueKeyB2, valueKeyB3}}

\myxmacro{key a = valueKeyA, key b = {valueKeyB1, valueKeyB2, valueKeyB3}}

\mytmacro{key a = valueKeyA, key b = {valueKeyB1, valueKeyB2, valueKeyB3}}

\end{document}

相关内容