Сделать символ активным в макросе

Сделать символ активным в макросе

Я думал, что я умный, поэтому я поставилэтот кодчтобы локально разрешить разрывы внутри встроенной математики в макросе:

\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}

Теперь это не удается; первая ошибка:

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

Что является причиной этой ошибки?

решение1

Хитрость в том, чтобы сделать запятуюматематика активная

Таким образом, команда \MakeCommaBreakableможет быть выполнена правильно.внутриформула, поэтому эффект активации математики ограничен.

\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}

введите описание изображения здесь

В чем проблема вашего кода?

Во-первых, даже если это исправлено, вы делаете запятую активной на внешнем уровне, что не являетсяхорошая вещь. Но это не главная причина: когда TeX считывает определение \MakeBreakableComma, заменяющий текст токенизирован и ,имеет код категории 12, поэтому он не может следовать за \def.

Благодаря этому \lowercaseтрюку TeX видит активную запятую, поскольку \lowercaseне изменяет коды категорий.

Тымощьсделайте запятую активной вместо просто math active, но я бы не рекомендовал этого, потому что если она активна, вы не сможете использовать ее в спецификациях опций, например. Математический активный символ вместо этого принимает «активное платье» только когда TeX проверяет математические коды.

Для полноты картины вы также можете разместить \MakeBreakableCommaна внешнем уровне ивсезапятые в математических формулах станут хрупкими: определенно не рекомендуется, поскольку вы не хотите сломать что-то вроде f(x,y).

решение2

На момент \def\MakeCommaBreakableсканирования тела ,in \def,еще не имел catcode, установленного на 13, и после сканирования catcode будет сохранен, поэтому на него не повлияет изменение catcode внутри тела определения, поэтому TeX будет жаловаться на отсутствие управляющей последовательности после /def. Использование Plain TeX вместо LaTeX может выдать более интуитивное сообщение об ошибке:

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

Я предполагаю, что вы хотите получить разрываемую команду, но есть некоторые проблемы с только \discretionary{}{}{}, что если нет растягиваемого пространства (клея) в строке, TeX почти всегда будет жаловаться на переполненный ящик. В зависимости от того, что вам нужно, вы можете или не можете захотеть этот клей или изменить его размер.

Правильный путь может быть таким:

\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

Связанный контент