20

LaTeX seems to be having problems handling nested optional arguments. I've included a minimal code example that generates the error:

\documentclass[12pt,oneside]{book}
\begin{document}

\newcommand{\termbad}[2][]{#2#1}
\newcommand{\termgood}[2][]{#2#1}

\newcommand{\up}[1]{#1}
\newcommand{\dd}[1][]{#1}

\termgood{\up{Tart}}{Pop}
\termbad[\up{Tart}]{Pop}    

\termgood{\dd[Tart]}{Pop}
\termbad[{\dd[Tart]}]{Pop}
%\termbad[\dd[Tart]]{Pop}


\end{document}

If you run this code, it works. If you remove the % in the second to last line, it fails with:

Runaway argument?

Tart{Pop} \par \par \end {document}

!File ended while scanning use of \dd.

After further tinkering, I have discovered the problem: LaTeX is reading the ] for the inner optional argument as the end of the outer optional argument and then passing a malformed argument in. So it is passing in \dd[Tart as the optional argument to \termbad instead of \dd[Tart].

This still feels like a bug to me. Nesting braces in arguments works, brackets should as well. The following are workarounds:

  • Enclose the inner optional argument in braces (as in the line before %).

  • Redefine your inner function to require its argument instead of using optional arguments.

  • Redefine your outer function to require its argument instead of using optional arguments.

Any one of the three works around the issue.

(Reposted here; question was originally posted to stackexchange and then closed instead of being migrated.)

2

1 Answer 1

27

When TeX reads arguments, then TeX only checks for matching curly braces (characters with catcode 1 and 2). Square brackets are not special in this sense. The first ] that is not hidden inside curly braces is taken as the end of the optional argument. Therefore an additional set of braces is the usual solution:

\foo[{\bar[...]}]{...}

It is only a bug, if this does not work, e.g. if the definition passes optional arguments to other commands:

\def\foo#1#2{\bar[#1]{#2}}

This should be

\def\foo#1#2{\bar[{#1}]{#2}}

Then #1 may contain square brackets, especially ].

3
  • 7
    Worth noting that xparse-defined functions do not suffer from this
    – Joseph Wright
    Oct 20, 2012 at 11:41
  • Thanks for the answers. I'm looking at xparse now, since I'm using some complex code to create a highly linked and formatted document. This may solve a few of the problems I've been having.
    – JKreft
    Oct 23, 2012 at 12:33
  • 4
    an answer explicitly showing how xparse is used has been posted at How do I nest a command with an optional argument? Apr 15, 2016 at 15:55

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.