Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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.

share|improve this question
    
You need to evaluate the first argument at the time you add it to the macro, not add the code directly. Have a look at \eappto from the etoolbox package. I will post an answer in a while if no one else posted one. –  Martin Scharrer Jan 4 '12 at 9:23
    
@Martin: Maybe you can extend your answer by the approaches with edef or with newtoks. –  Marco Daniel Jan 4 '12 at 9:48
    
@MarcoDaniel: I was planning to give other people a chance to post their answers. That wasn't meant as a "I'm currently writing my answer" note. –  Martin Scharrer Jan 4 '12 at 9:55
    
@Martin Though there are answers using edef and newtoks i would also be interested in a version using the etoolbox, just because I tried your ideas and didn't have any success in using \eappto. –  Ronny Jan 5 '12 at 7:30

2 Answers 2

up vote 8 down vote accepted

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.

share|improve this answer
    
I like the second solution, can you explain why that works if i use \themycounter or \arabic{mycounter} but not if i use \value{mycounter} as first parameter? –  Ronny Jan 4 '12 at 10:46
1  
\themycounter or \arabic{mycounter} are representations of the counter's value; think to \value{mycounter} as the abstract number. –  egreg Jan 4 '12 at 10:52

use a token register, makes live easier.

\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}
share|improve this answer
    
Shouldn't it be \unexpanded{#2} instead of \noexpand#2? Without \unexpanded one has to do it in two steps. –  egreg Jan 4 '12 at 10:48
    
So i gave both attempts a try. Your attempt has one disadvantage, the other one (from egreg) does not have: If you define a new environment and call \addstuff from inside the first block, i.e. the code executed before the environment, your solution does somehow calls \adstuff (even running through it - i checked with some ouptut inside that command) without adding something to the token register. I used \newenvironmentx from xargs to define the environment. –  Ronny Jan 4 '12 at 14:08

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.