[Tex/LaTex] Save current value of counter in a command

countersexpansionmacros

I would like to define kind of an own index, that collects certain information and one counter value – in the following small example the \addstuff-command that may get the value of a counter as its first argument and a description as its second. The first entry might also be text itself or even empty.

I want to collect all these value-text entries and create an output at the end. In the following example the description always reflects, what i want the counter value to be in that entry.

\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}

So my question is, how can i evaluate the first parameter to obtain the actual value of the counter at the moment, \addstuff is called? Because in this code, both lines that i save in my collection end up having the value 3 instead of 1 or 2 respectively.

Best Answer

A problem with complete expansion in LaTeX is that some commands are "dangerous"; so a two pass approach is needed. In your \addstuff command you want that the first argument is expanded to the maximum possible and the second argument is taken "as is".

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

It would be more complicated if the argument to expand wasn't the first. A different approach might be

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

where it's clearer what gets expanded and what doesn't.

If there's more control on what is allowed in the first argument, that is, nothing that could need "protection", one can do it in one step:

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

But with this definition, something as seemingly innocent as \addstuff{\bfseries special}{stuff} would fail miserably.

Related Question