13

I made a custom counter with a custom command that steps the counter and sets an automatic label for it. However, when invoking this from a caption AND using the caption package, my counter steps two times. Here's a MWE:

\documentclass{book}
\usepackage{caption}

\newcounter{example}[chapter]
\renewcommand{\theexample}{\thechapter{}.\arabic{example}}
\providecommand{\example}[1]{\refstepcounter{example}\label{ex:#1}{\theexample}}

\begin{document}

\begin{figure}[h!]
\caption{\protect\example{my_example}}
\end{figure}

\end{document}

If I comment out the line \usepackage{caption}, I get the right results.

Is this a bug, or am I doing here some very basic mistake?

2 Answers 2

9

You could get a double evaluation without the caption package as well (depending on the length of the text). The caption package provides a way to ensure the text is only evaluated once:

\usepackage[singlelinecheck=false]{caption}
0
9

As already said by David the caption text will usually be evaluated once or twice, depending on the length of the caption text. (So if you make your caption text longer than one line you'll run into the same problem, even without caption package.)

To make things more consistent the caption package always evaluates the caption text twice.

Using the caption package with option singlelinecheck=false (as suggested by David) will switch off the first evaluation but it will switch off the single-line-feature of the caption package as well, giving you left-aligned (instead of centered) short captions.

If this is ok for you this is the easiest method to solve your problem. But if you would like to keep the single-line-feature we have to take a look at the internals of the caption package:

During the first evaluation (to determine the length of the caption text) \caption@prepareslc will be used, so one can get rid of side-effects of the double evaluation by extending this macro.

An example:

\documentclass{book}
\usepackage{caption}

\newcounter{example}[chapter]
\renewcommand{\theexample}{\thechapter{}.\arabic{example}}
\newcommand{\stepexample}{\refstepcounter{example}}
\DeclareRobustCommand{\example}[1]{\stepexample\label{ex:#1}{\theexample}}
\makeatletter
\g@addto@macro\caption@prepareslc{%
  \renewcommand{\stepexample}{\caption@l@stepcounter{example}}}
\makeatother

\begin{document}

\begin{figure}[h!]
\caption{\example{my_example}}
\end{figure}

\ref{ex:my_example}

\end{document}

What have I done here:

  • I have outsourced the incrementation of the example counter to \stepexample so I can re-define this one later on.
  • I have extended \caption@prepareslc so the example counter will only be incremented locally during the evaluation of the caption text length. (Not incrementing it at all seems to be a working solution as well, but this will give you an improper measurement of the caption text length since 1 will have a different length than 2 and so on.)
  • I use the internal macro \caption@l@stepcounter for local incrementation of the example counter.

But why don't we re-define \refstepcounter to \caption@l@stepcounter within \caption@prepareslc? In fact this was done by some caption package versions since this seems to be an easy global solution for all counters, but I have to drop this solution since some code (offered by other packages) was not happy with this patch of \refstepcounter at all.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .