3

I thought I am smart, so I put this code to locally allow breaks inside inline math into a macro:

\documentclass{article}
\def\MakeCommaBreakable{%
    \def\OldComma{,}
    \catcode`\,=13
    \def,{%
        \ifmmode%
        \OldComma\discretionary{}{}{}%
        \else%
        \OldComma%
        \fi%
    }%
}
\begin{document}
    \MakeCommaBreakable
    $xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx$
\end{document}

Now, this fails; first error:

! Missing control sequence inserted.
<inserted text> 
                \inaccessible 
l.14    \MakeCommaBreakable

What causes this error?

2 Answers 2

3

The trick is to make the comma math active

This way, the command \MakeCommaBreakable can properly go inside the formula, so the effect of math activation is confined.

\documentclass{article}
\usepackage{amsmath}

\newcommand{\MakeCommaBreakable}{%
  \mathchardef\normalcomma=\mathcode`,
  \begingroup\lccode`~=`,\lowercase{\endgroup\let~}\BreakableComma
  \mathcode`,="8000
}
\newcommand{\BreakableComma}{%
  \normalcomma\mspace{0mu plus 6mu}\penalty0
}

\begin{document}

$\MakeCommaBreakable xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
  xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx$

\end{document}

enter image description here

What's the problem with your code?

First, even if it's fixed, you're making the comma active at the outer level, which isn't a good thing. But this is not the main reason: when TeX reads the definition of \MakeBreakableComma, the replacement text is tokenized and , has category code 12, so it cannot follow \def.

With the \lowercase trick, what TeX sees is an active comma, because \lowercase doesn't change category codes.

You might make the comma active instead of just math active, but I wouldn't recommend it, because if it's active you cannot use it in option specifications, for instance. A math active character instead takes on the “active dress” only when TeX is examining math codes.

For completeness, you might also place \MakeBreakableComma at the outer level, and all commas in math formulas would become breakable: definitely not recommended, because you don't want to break something like f(x,y).

7

At the time of \def\MakeCommaBreakable's body been scanned, the , in \def, does not yet have catcode set to 13, and after the scanning the catcode would be saved thus won't be affected by catcode change inside the definition body, thus TeX would complain control sequence is missing after /def. Using Plain TeX instead of LaTeX can give a more intuitive error message:

! Missing control sequence inserted.
<inserted text> 
                \inaccessible 
<to be read again> 
                   ,
\MakeCommaBreakable ... {,} \catcode `\,=13 \def ,
                                                  {\ifmmode \OldComma \discr...
l.12 \MakeCommaBreakable

I assume you want to get a breakable command, but there are some issue with only \discretionary{}{}{}, that if there are no stretchable space (glue) in a line, TeX would almost always complain the overfull box. Depends on you need you may or may not want that glue or change the size of it.

The correct way could be:

\bgroup
% make sure it is defined before catcode change to prevent infinite expand
\gdef\OldComma{,}
\catcode`\,=13
\gdef\MakeCommaBreakable{%
    \catcode`\,=13
    \def,{%
        \ifmmode
% You don't need to place % after control token, because
% TeX already ignores them.
% Also, consider use math glue to give some adjustable spacing, otherwise
% TeX would almost always report overfull box for a long line like this
        \OldComma\>\allowbreak
        \else
        \OldComma
        \fi
    }%
}
\egroup
\MakeCommaBreakable
    $xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx$
\bye

You must log in to answer this question.

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