
入力プロセッサは、カテゴリ コード 5 の文字が 2 つ連続して出現すると (つまり、空白行)、\par
マクロを挿入します。
が終了すると\vbox{Abc.}
、TeX は現在の段落を終了しますが、\par
マクロを挿入するわけではありません。代わりに TeX はプリミティブを挿入しているようです\par
。この場合の TeX の動作を正しく理解していますか? TeX が を挿入する他の場所ではどうですか\par
? マクロ はいつで\par
、プリミティブ はいつですか?
\catcode`@=11
\let\@@par\par
\def\par{\typeout{Macro!}\@@par}
Abc.
\vbox{Abc.\tracingall}
答え1
TeXプログラムには、TeXが内部的に段落ビルダーを実行する場所が7箇所あります。つまり、水平リスト(構築中の場合)を段落に変換する場所です。これは次のように行われます。ない入力ストリームにトークンを挿入するのでは\par
なく、手順を実行することによって終わりのグラフTeXプログラムのモジュール§1096に実装されています。
この手順は、TeXが水平モードでない場合は何も行いません。水平モードであってもリストが空の場合は、ほとんど何も行いません(TeXでは空の段落は無視されます)。そして、手順を実行します。改行それ以外の場合 (そして、そのメソッドは、parfillskip ペナルティの追加など、すべての魔法を実行します)。
7つの場所は
- 内部の垂直構造の終わり、例えば閉じ括弧や整列セル
\vbox
など\noalign
\vcenter
- 原始的なパー終了感知される(これはマクロレベルではトークンの意味として最初に利用可能である
\par
) - 出力ルーチン (OR) が終了した直後 (したがって、OR で開始された水平リストはゲラからの資料に続くのではなく、それ自体で段落を形成します)
これらのいずれの場合も、\par
トークンは挿入されません(再定義の対象となる可能性があります)。代わりに、終わりのグラフ手順が実行されます!
\par
トークンは、水平モードで、水平モードと互換性のないプリミティブ ( \vskip
、\hrule
、... など。 の完全なリストは TeX コードの §1094 にあります) に遭遇した場合にのみ挿入されます。そしてもちろん、トークン化プロセスでは、TeX が 2 つの行末文字を に置き換えるとき\par
(つまり、空行を と同等にする\par
) にも挿入されます。
答え2
によるとTeXbook について行末のルールは以下のとおりです
TeXが行末文字(カテゴリ5)を検出すると、現在の行に残っている可能性のある他の情報はすべて破棄されます。その後、TeXが状態いいえ(改行)の場合、行末文字は制御シーケンストークン
\par
(段落の終わり)に変換されます。TeXが状態ま(行の途中)の場合、行末文字はカテゴリ10(スペース)の文字32()のトークンに変換されます。TeXが状態ス(空白をスキップ)、行末文字は単に削除されます。
ここで、TeX はプリミティブ\par
ではなくトークンを挿入することに注意してください\par
。つまり、\par
あらゆる状況で定義する必要があります。Knuth は、水平モードを強制するコマンドについて説明するときに、この点を説明しています。
<の出現垂直コマンド制限された水平モードでは>は禁止されていますが、通常の水平モードではTeXがトークンを
\par
入力に挿入します。この\par
トークンを読み取って展開した後、TeXは<垂直コマンド> トークンを再度使用します。(制御シーケンスの現在の意味\par
が使用されます。TeX\par
のプリミティブを表さなくなる可能性があります\par
。)
さて、どこにも言及されていないのは、内部垂直モードの終了時に何が起こるかということです。明らかに、上記のルールでは、\par
処理すべき行末マーカーがないため、トークンの挿入は許可されていません。(ボックスの最後のマテリアルとボックスの終わり\par
の間に空白行がある場合は、挿入されます。)\vbox
\par
トレース出力を読むと、ボックスの最後にプリミティブについての言及はないが、出荷時には
....\penalty 10000
....\glue(\parfillskip) 0.0 plus 1.0fil
そしてもちろん、明らかに段落が構築されています。したがって、私の結論は、内部垂直モードの終了によって暗黙的にプリミティブが挿入され\par
、通常の段落終了のマテリアルが挿入されてから段落ビルダーが実行されるということです。
答え3
\par
TeXが の「本来の意味」を の末尾に置くのには理由があります\vbox
。次の馬鹿げた入力を考えてみましょう。
\vbox{\let\par\empty a}
TeX は を見つけると}
、それをバックアップし、「元の 」を挿入して水平モードを終了し、内部の垂直モードを閉じる を\par
再度読み取ります。}
\par
TeXが の現在の意味を に挿入して、 を再読み込みするとどうなるかをエミュレートすることができます}
。
\vbox{\let\par\empty a\vskip0pt}
\vskip
は (current) を挿入し\par
、TeX は を再読み込みするため\vskip
、結果は無限ループになります。
(見つかった1993年の議論comp.text.tex
。