Tornando um personagem ativo em uma macro

Tornando um personagem ativo em uma macro

Eu pensei que era inteligente, então coloqueieste códigopara permitir localmente quebras dentro da matemática embutida em uma 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}

Agora, isso falha; primeiro erro:

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

O que causa esse erro?

Responder1

O truque é fazer a vírgulamatemática ativa

Desta forma, o comando \MakeCommaBreakablepode ir corretamentedentroa fórmula, portanto o efeito da ativação matemática é confinado.

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

insira a descrição da imagem aqui

Qual é o problema com o seu código?

Primeiro, mesmo que seja fixo, você ativa a vírgula no nível externo, o que não é um problema.coisa boa. Mas este não é o motivo principal: quando o TeX lê a definição de \MakeBreakableComma, o texto de substituição é tokenizado e ,possui o código de categoria 12, portanto não pode seguir \def.

Com o \lowercasetruque, o que o TeX vê é uma vírgula ativa, pois \lowercasenão altera os códigos de categoria.

Vocêpodertorne a vírgula ativa em vez de apenas matemática ativa, mas eu não recomendaria isso, porque se estiver ativa você não poderá usá-la em especificações de opções, por exemplo. Em vez disso, um personagem ativo em matemática assume a “vestimenta ativa” apenas quando o TeX está examinando códigos matemáticos.

Para completar, você também pode colocar \MakeBreakableCommano nível externo, etodosvírgulas em fórmulas matemáticas se tornariam quebráveis: definitivamente não é recomendado, porque você não quer quebrar algo como f(x,y).

Responder2

No momento em que \def\MakeCommaBreakableo corpo de ' foi escaneado, o ,in \def,ainda não tem o catcode definido como 13 e, após a varredura, o catcode seria salvo, portanto, não será afetado pela alteração do catcode dentro do corpo da definição, portanto, o TeX reclamaria da sequência de controle está faltando depois /def. Usar Plain TeX em vez de LaTeX pode gerar uma mensagem de erro mais intuitiva:

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

Presumo que você queira obter um comando quebrável, mas há algum problema apenas com \discretionary{}{}{}, que se não houver espaço extensível (cola) em uma linha, o TeX quase sempre reclamaria da caixa cheia demais. Depende da sua necessidade, você pode querer ou não aquela cola ou alterar o tamanho dela.

A maneira correta poderia ser:

\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

informação relacionada