I have left Harvard as of July 1, 2008 to take a position at NYU. This website has been cached and left static. Feel free to browse my new website, aka "What the heck is a Clinical Associate Professor?"

03.20.08

Number pages within chapters in LaTeX

Posted in LaTeX at 9:17 am by leingang

In latex, the \numberwithin command allows one to bind one counter with another. A common example is the section counter and the chapter counter. When a new chapter is created, the chapter counter increments, and the section counter is reset. In this scheme, if the last section of chapter 1 is labeled “1.5″, the first section of chapter 2 is labeled “2.1″.

In the process of preparing a large handout, put together in stages and repeatedly distributed, a student asked if I could number the pages of a document within the chapters. So each page would be labeled chapter-page, and the first page of each chapter would be page 1.

Sounded simple enough: just use

\renewcommand{\thepage}{\arabic{chapter}-\arabic{page}}

(this changes the way pages are labeled) and

\numberwithin{page}{chapter}

to change the numbering. But this doesn’t quite do it, because \numberwithin resets the counter to zero, and so the first page of chapter 4 gets labeled as “4-0″. I need to start a new chapter, then reset the page counter to one, not zero.

There is probably a package which does this, but five minutes of googling didn’t produce it. So I started to roll my own. One can write a \Chapter command that calls \chapter then resets the page counter. The disadvantage here is that (1) you have to search-and-replace existing code, and (2) \chapter is a pretty complicated command with a starred version and an optional argument. The \chapter macro calls lower-level macros and actually returns a seven-argument macro with four arguments filled in. So rather than call the \chapter macro, I want to make adjustments, then return \chapter so that it can parse as normal. That’s when I tried:

\let\oldchapter=\chapter
\def\chapter{\resetcounter{page}{0}\oldchapter}

This adds the page reset to the beginning of the chapter, without changing the way it’s used. The trouble is that \chapter clears the page before starting the new chapter, and that page needs a label. So this made sure the first page of Chapter 4 was labeled 4-1, but now the last page of Chapter 3 got labeled 3-0!

What I needed was to return \chapter, but make sure LaTeX executed the \resetcounter command right afterwards. The solution is \expandafter, which defers token expansion by one position. From The TeXBook:

TeX first reads the token that comes immediately after \expandafter, without expanding it; let’s call this token t. Then TeX reads the token that comes after t (and possibly more tokens, if that token has an argument), replacing it by its expansion. Finally TeX puts t back in front of that expansion.

And here’s the implementation:


\let\oldchapter=\chapter
\def\resetpage{\setcounter{page}{1}}
\def\chapter{\expandafter\resetpage\oldchapter}

The parsing works like this: upon reading the new \chapter macro, TeX encounters \expandafter, reads \resetpage but holds onto it. It then expands \chapter, which under the hood returns that seven-argument monster macro. At that point \resetpage is called.

Update 2008-04-08: Peter tells me the package I’m looking for is chappg.  Should have googled more!

Blogged with the Flock Browser

Tags: , ,

2 Comments

  1. bready said,

    April 7, 2008 at 5:12 pm

    If \resetpage is still called BEFORE \oldchapter, then you should still have the same problem, according to your quote from the TeXBook. You would be setting the last page of chapter 3 to 1 and the first page of chapter four to 2. It seems like what you would want to do is call:

    \def\chapter{\oldchapter\resetpage}

    What am I missing?

  2. leingang said,

    April 8, 2008 at 8:19 am

    Like I said, this is my first use of \expandafter, so I’m not quite sure I can explain it well. The problem with \def\chapter{\oldchapter\resetpage is that \chapter expects some arguments, and we the macro writer can’t anticipate how many arguments are going to be present. \oldchapter\resetpage is going to try to create a chapter named \resetpage, which will probably be disastrous. :-)

    Another common use of \expandafter is to use variable variable names, so that


    \def\save#1#2{
    \expandafter\def\expandafter\csname#1\endcsname{#2}}

    has the effect of what you probably mean when you want to write \def\#1{#2}: that is, save #2 in a macro named #1. Although the TeXBook does say that the held token is put in front of the token string and then evaluated in the same order, I think the fact that the second token is evaluated and expanded first is almost the same thing as having the second token come first. There was another use of \expandafter as a solution to a question on comp.tex.macosx the other day.