在命令中保存计数器的当前值

在命令中保存计数器的当前值

我想定义一种自己的索引,它收集某些信息和一个计数器值 - 在下面的小示例中,命令\addstuff可能会将计数器的值作为其第一个参数,将描述作为其第二个参数。第一个条目也可能是文本本身,甚至是空的。

我想收集所有这些值文本条目并在最后创建一个输出。在下面的示例中,描述始终反映出我希望计数器值在该条目中是什么。

\documentclass[a4paper]{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\newcommand{\collect}{}

\newcounter{mycounter}\setcounter{mycounter}{1}

\makeatletter
\newcommand{\addstuff}[2]{\g@addto@macro\collect{#1 & #2\\}}
\makeatother
\newcommand{\generateOutput}{%
    Output of collection\par%
    \begin{tabular}{rl}\collect\end{tabular}%
}

\begin{document}
    \addstuff{normal}{Entry}
    \addstuff{\themycounter}{save the 1 it should have here}
    \refstepcounter{mycounter} %incement -> 2

    \addstuff{\arabic{mycounter}}{<-save the 2 of the counter}
    \refstepcounter{mycounter} %incement -> 3

    % Print all saved data
    \generateOutput
\end{document}

所以我的问题是,如何评估第一个参数以获取当前计数器的实际值\addstuff?因为在此代码中,我保存在集合中的两行最终分别具有值3而不是12

答案1

LaTeX 中完全扩展的一个问题是,有些命令是“危险的”;因此需要采用两遍方法。在命令中,\addstuff您希望第一个参数被扩展到最大可能,而第二个参数则“按原样”采用。

\makeatletter
\newcommand{\addstuff}[2]{%
  \protected@edef\@tempa{#1}%
  \expandafter\g@addto@macro\expandafter\collect\expandafter{%
    \@tempa & #2 \\}}
\makeatother

如果扩张的论点不是第一个,情况会更加复杂。另一种方法可能是

\makeatletter
\newcommand{\addstuff}[2]{%
  \protected@edef\@tempa{#1 & \unexpanded{#2} \noexpand\\}
  \expandafter\g@addto@macro\expandafter\collect\expandafter{\@tempa}}
\makeatother

其中哪些可以扩展,哪些不可以扩展,这一点更加清晰。

如果对第一个参数中允许的内容有更多的控制,即没有任何内容需要“保护”,则可以一步完成:

\makeatletter
\newcommand{\addstuff}[2]{%
  \begingroup\edef\x{\endgroup
    \noexpand\g@addto@macro\noexpand\collect
      {#1 & \unexpanded{#2} \noexpand\\}}\x}
\makeatother

但如果按照这个定义,看似无辜的事情\addstuff{\bfseries special}{stuff}就会惨遭失败。

答案2

使用令牌寄存器,使生活更加轻松。

\documentclass[a4paper]{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\newtoks\tabtoks
\newcommand\addstuff[2]{%
  \begingroup\edef\x{\endgroup
    \noexpand\tabtoks{\the\tabtoks
      #1 & \noexpand#2 \noexpand\\}}\x}
\newcommand*\resettabtoks{\tabtoks{}}

\newcounter{mycounter}
\setcounter{mycounter}{1}

\newcommand\generateOutput{%
  Output of collection\par%
  \begin{tabular}{ll}\the\tabtoks\end{tabular}}

\begin{document}
\resettabtoks
\addstuff{normal}{Entry}
\addstuff{\themycounter}{save the 1 it should have here}
\refstepcounter{mycounter} %incement -> 2

\addstuff{\themycounter}{<-save the 2 of the counter}
\refstepcounter{mycounter} %incement -> 3

\addstuff{\noexpand\bfseries foo}{a test}
\addstuff{\themycounter}{is three}

\generateOutput
\end{document}

相关内容