マクロでキャラクターをアクティブにする

マクロでキャラクターをアクティブにする

私は自分が賢いと思っていたのでこのコードインライン数式内の改行をマクロ内でローカルに許可するには:

\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

あなたかもしれないカンマをアクティブにする代わりに数式をアクティブにすることもできますが、アクティブにすると、たとえばオプションの指定で使用できなくなるため、お勧めしません。数式アクティブ文字は、TeX が数式コードを調べるときにのみ「アクティブ ドレス」を身に付けます。

完全性のために、外側のレベルにも配置し\MakeBreakableComma全て数式内のカンマは分割可能になります。 のようなものを分割したくないので、絶対にお勧めしませんf(x,y)

答え2

\def\MakeCommaBreakableの本体がスキャンされた時点では、,\def,catcode はまだ 13 に設定されていません。 のスキャン後に catcode が保存されるため、定義本体内の catcode の変更による影響を受けません。そのため、TeX は の後に制御シーケンスが欠落しているとエラーを出します/def。LaTeX の代わりに Plain TeX を使用すると、より直感的なエラー メッセージが表示されます。

! 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

関連情報