17

I would like to keep track of all the \AddRef commands in a document and then process them one at a time, for instance print them in the document on one line per value. It seems that this should be doable as the functionality is not that different than list of figures that, but I can' seem to get this to work. I did not even attempt the \foreach command required at the end of the file so if someone knows how to do that that would be appreciated.

\documentclass[12pt]{article}
\begin{document}

\newtoks{\Ref}
\newcommand{\AddRef}[1]{%
    \let\OldRef=\the\Ref\relax
    \let\Ref=\the\OldRef{#1}\relax
}

\AddRef{Ref 1}
\AddRef{Ref 2}
\AddRef{Ref 3}

The list of Ref are:
\the\Ref

\end{document}

At the end, I would like to process the list, say to print a line at a time:

Ref 1

Ref 2

Ref 3


The original question above required the case where this list of strings is a global macro so that it is complete at the end of the document. Another application requires that this list of strings be local to a scope so a local version would also be useful.

Peter Grill
  • 223,288

3 Answers3

13

The \let\OldRef=\the\Ref doesn't work because \OldRef is then simply a copy of \the. Also note that \Ref here stands for \toks<number> and coping it using \let would only let both macros point to the same token register.

You can accumulate code using the \g@addto@macro macro:

\def\Ref{}
\makeatletter
\newcommand{\AddRef}[1]{%
    \g@addto@macro\Ref{{#1}}%
}
\makeatother

This redefines a macro, which is less efficient than using a token register, but this should be OK in your case.

Instead of using a for loop I would simply add the required macros as part of the definition of \Ref, so that you simply have to use the macro. The ToC and List of Figures is generated by writing such code into an external file instead.

Martin Scharrer
  • 262,582
  • Both of these work. But in which circumstances is one better than the other? I am not too concerned about speed. – Peter Grill Mar 29 '11 at 04:26
  • And the reason I wanted to use a for loop at the end, is that I have not yet figured out exactly how I am going to do the processing that is needed, so had planned on temporarily outputing a \todo statement for now and coming back later to fix it. That way I did not need to change the collection of these, just the processing of the \Ref(s). I could of course collect the \todo as part of the list as it is created, and then later change this, but that solution somehow seems wrong. – Peter Grill Mar 29 '11 at 05:02
9
\documentclass[12pt]{article}
\newcommand\AddRefList{}
\newcommand\AddRef[1]{\edef\AddRefList{\AddRefList#1\endgraf}}
\begin{document}

\AddRef{Ref 1}
\AddRef{Ref 2}
\AddRef{Ref 3}

The list of Ref are:

\AddRefList

\end{document}
9

If you want a local version of \g@addto@macro without using up a new token register you could use something like

\long\def\@addto@macro#1#2{%
\begingroup
\toks@\expandafter{#1#2}%
\expandafter\endgroup\expandafter
\edef\expandafter#1\expandafter{\the\toks@}%
}

this uses the scratch register \toks@ without affecting its existing contents, it is basically \g@addto@macro but using \edef rather than \xdef and with a few extra \expandafter to compensate.

David Carlisle
  • 757,742
  • On the other hand, this particular application seems to require global definitions, since \AddRef might be used inside an environment. – egreg Oct 05 '12 at 21:44
  • 1
    @egreg I was asked by the OP in chat for a local version of g@addto@macro and I always do what I'm told:-) – David Carlisle Oct 05 '12 at 22:02