5

In short: I am trying to append counter values to a token list, but when I print the token list at the end I get the final values of those counters. What I want is the value of the counters at the moment that I added them to the list. I realise that I somehow need to change the way things are (not) being expanded, but I don't really understand any of the answers to related questions on this.

Background: I am trying to solve my own question, which I posted earlier today, on counting the number of pages in each chapter/section in my document. I am quite close, but this is the remaining issue I have.

Minimal example: Here is a simplified version of the tex file I'm using. I want the final output to be 1,4; 2,7; 2,8 but instead I get 2,8; 2,8; 2,8.

\documentclass{article}

% Create the \mytoks token list, and give a way to add to it.
\newtoks\mytoks
\mytoks={}
\newcommand{\appendtomytoks}[1]{%
    \mytoks=\expandafter{\the\mytoks#1}%
}

% Create the counter I'll be using.
\newcounter{mycounter}

% Now the command for storing the counter in the token list.
% (Really it's more complicated than this.)
\newcommand{\toplevelcmd}{%
    \setcounter{mycounter}{\thepage}%
    \addtocounter{mycounter}{3}%
    \appendtomytoks{\the\value{section}, \the\value{mycounter}\par}%
}

\begin{document}

\section{First section}

% S1 P1, so should add 1,4 to token list
\toplevelcmd 

\newpage{}

.

\newpage{}

.

\newpage{}

\section{Second sectionx}

% S2 P4, so should add 2,7 to token list
\toplevelcmd 

\newpage{}

% S2 P5, so should add 2,8 to token list
\toplevelcmd 

\the\mytoks

\end{document}

Here is part of the preamble of the actual document I'm working on. \appendtopagecounttable is just renamed \appendtomytoks, but as you can see the commands are a bit more complicated. Arguments #1 and #3 to the commands below should just be counter values, but #2 could be something a bit more complicated (but probably not, I think).

\newcommand{\addchapterpagecount}[3]{%
    \appendtopagecounttable{\medskip\par\noindent\textbf{\makebox[\parindent][l]{#1}#2\hfill #3}}
}
\newcommand{\addsectionpagecount}[3]{%
    \appendtopagecounttable{\noindent\hspace{\parindent}\makebox[0.8cm][l]{#1}#2\dotfill #3}
}
  • The plain TeX solution is to use \csname to create numbered macros. – John Kormylo Sep 12 '14 at 19:41
  • @JohnKormylo Thanks for the idea, but I couldn't get it to work. Combined with \def it gave the problem that was the subject of the question, and with \edef it worked in simple cases but not with the more complex parameters I described at the end of my question (I forget what the exact error was). So in the end it was no different to David's solution (except that I would've needed to figure out how to iterate over them!). – Jim Oldfield Sep 21 '14 at 11:16
5

If you only want to put counter values in there, you can replace

    \mytoks=\expandafter{\the\mytoks#1}%

by

    \edef\tmp{\mytoks{\the\mytoks#1}}\tmp

as they are safe (and expand) in an \edef)

  • I guess my minimal example was a bit too minimal! I'm adding more complicated stuff than that; I've added an update to my question. I tried your solution anyway, and even tried using something like your solution at a higher level (using \edef on #1 and #3 in my \addsectionpagecount command) but couldn't get them to work. – Jim Oldfield Sep 12 '14 at 15:51
  • @J why put all that stuff in a list? normal thing if you want a list of things that take two numbers is define \@elt to be \relax so it is safe with the above then you build up a list like \@elt{1}{2}\@elt{5}{6} with the numbers at the point you saved them, then you can define \@elt to be a two argument command with \makebox etc when you use the list – David Carlisle Sep 12 '14 at 16:05
  • Why put it all in the list? Because the alternative would be massively more complicated! At the point of adding to the list I am effectively in a loop iteration (where I am in the document) and in a branch (section or chapter?) and you're suggesting I save that state along with the information I have to hand (page count and heading), then later on loop over it all and reassemble it. Considering how much trouble I'm having just joining two strings, I sudder to imagine all the roadblocks I'd have to work around if I did it like that. – Jim Oldfield Sep 21 '14 at 11:10
  • Nevertheless I accepted this as the answer. No one has suggested a better way, so I just did this and put up with having minimal formatting in the final table, avoiding any commands that seemed to break compilation. Thanks for the idea. – Jim Oldfield Sep 21 '14 at 11:12
3

The following illustrates how to use \csname to store the first and last page of each chapter and section.

\documentclass{book}
\usepackage{lipsum}

\newcounter{pages}

\newcommand{\firstpage}[1]% #1 = chapter number or some unique identifier
{\expandafter\edef\csname firstpage.#1\endcsname{\thepage}}

\newcommand{\lastpage}[1]% #1 = chapter number or some unique identifier
{\expandafter\edef\csname lastpage.#1\endcsname{\thepage}}

\newcommand{\pages}[1]% #1 = chapter number or some unique identifier
{\setcounter{pages}{\csname lastpage.#1\endcsname}%
\stepcounter{pages}%
\addtocounter{pages}{-\csname firstpage.#1\endcsname}%
\thepages}% output number of pages

\begin{document}
\chapter{One}
\firstpage{\thechapter}

\section{A}
\firstpage{\thesection}
\lipsum[1-6]
\lastpage{\thesection}

\section{B}
\firstpage{\thesection}
\lipsum[7-15]
\lastpage{\thesection}
\lastpage{\thechapter}

\newpage\noindent%
\pages{1} pages in Chapter 1\newline
\pages{1.1} pages in Section 1.1\newline
\pages{1.2} pages  in Section 1.2
\end{document}

pages

Yes, they don't add up, but sections don't start new pages.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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