15

For some reason, the following minimal example doesn't compile:

\documentclass{article}

\makeatletter
\newcommand{\testMe}{%
    test
    \@ifstar{1}{2}%
}
\makeatother

\begin{document}
\testMe
\testMe*
\begin{figure}
  bla bla bla
  \caption{\testMe*}
\end{figure}
\end{document}

However, if you uncomment the \@ifstar line, or don't use \testMe in the caption then it works. Why?

  • Commands defined in that way are fragile, so you need \protect\testMe in the moving arguments, for instance the caption text. – egreg Jun 12 '13 at 8:12
  • I see. Is there no way of checking the presence of a star such that I don't need to use \protect before every such use? – gablin Jun 12 '13 at 8:17
  • Yes, there are at least two ways. – egreg Jun 12 '13 at 8:21
15

Commands defined in that way are fragile, so you need \protect\testMe in the moving arguments, for instance the caption text.

Let's see why. The argument to \caption needs to be massaged a few times, in particular it gets written to the .aux file for possible inclusion in the list of figures (or tables).

When TeX does a \write operation, it expands commands “all the way”, unless instructed not to do so (which is the purpose of \protect). During this expansion in \write operations, \@ifstar or \@ifnextchar (which \@ifstar is defined upon) break because they need to assign a value to a scratch macro to work and this is not possible during expansion.

Thus you have three possibilities:

  1. use \protect\testMe when in a moving argument

  2. use \DeclareRobustCommand for defining \testMe (same syntax as \newcommand)

  3. use xparse.

The last possibility needs a comment. If you do

\usepackage{xparse}
\NewDocumentCommand{\testMe}{s}
 {test \IfBooleanTF{#1}{1}{2}}

you get basically the same as your \testMe, but automatically protected when found in moving arguments.

| improve this answer | |

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.