以下の内容はhttps://zrbabbler.hatenablog.com/entry/2025/04/26/185605より取得しました。


チョット不思議な \nobreak の話

相変わらずやってます🌸

Beast言語の話のTeX言語の話

先日、某キ~タを眺めていたらこんな記事を見つけました。

BibTeXで出力した文献リスト中の著者名が分綴(hyphenate)されるのを、文献スタイル(.bstファイル)を改修して解決した」というBeaST言語1ネタです。

これを読んでいて、TeX言語🤮的にチョット面白いネタを見つけたので、本記事ではそれを紹介します。

元ネタのBeaST言語の話の要点

元ネタの記事の要点を(BeaST言語を表に出さずに)話すと以下のようになります。

以下のようなBibTeXの文献データがあるとします。

@Article{nice,
  author = {Redd M. Snowemann},
  %……(略)……
}

これをjplainスタイルで処理すると以下のようなTeXコードに変換されました。

\bibitem{nice}
Redd~M. Snowemann.
%……(略)……

ここではSnowemannという単語には特に何も“細工”がされていないので分綴の対象になります。人名が分綴されるのは避けたいので、jplain.bstを改修を行って(ここがBeaSTネタの話)、改修後のスタイルでは以下のようなTeXコードに変換されました。

\bibitem{nice}
\nobreak Redd~M.\ \nobreak Snowemann\nobreak .
%……(略)……

その結果、希望通りにSnowemannの分綴が抑止されました。めでたしめでたし😊

なぜかTeX言語が希望通りにうごく件

……という話なのですが、TeX言語をチョット知っている人から見れば釈然としない点があると思います。「Snowemannの直前に\nobreakを書くことで分綴が抑止される」というのは理屈に合いません

\nobreak\penalty\@Mに展開される「plain TeXレベル」のマクロ2で、値10000のペナルティを配置します。TeXにおいて10000以上の値のペナルティをもつ位置は行分割点の候補から外れるので“その箇所”での行分割が抑止されるわけです。

従って、“その箇所”、つまり「Snowemannの直前3」での行分割が抑止されるという話なら理屈が通ります。しかし今の目的は「Snowemannの途中」での行分割の抑止であるはずで、Snowemannの直前の\nobreakは一見すると無関係のようにみえます。

本当にこの\nobreakに分綴を抑止する効果があるのかを実験してみましょう。

\documentclass{article}
\begin{document}
% 狭い幅(10em)で段落を組んでみる
\fbox{\parbox{10em}{% \nobreak なし
It's supercalifragilisticexpialidocious!
}}
\par\bigskip
\fbox{\parbox{10em}{% \nobreak あり
It's \nobreak supercalifragilisticexpialidocious!
}}
\end{document}

pdfLaTeXでタイプセットすると以下の結果が得られます。

出力結果

確かに\nobreakで実際に分綴が抑止できているようです4。それにしても、なぜ希望通りになったのか、わけがわからないですね😟

なぜTeX言語が希望通りにうごくのか

TeXでは段落中にある単語を分綴する機能があるわけですが、実は「分綴の対象となる単語」には結構ヤヤコシイ条件が設けられています。『TeX by Topic』の説明を見てみましょう。

TeX starts at glue items (if they are not in math mode) looking for a starting letter of a word: a character with non-zero \lccode, or a ligature starting with such a character (upper/lowercase codes are explained on page 48). …(略)…

If no suitable starting letter turns up, that is, if something is found that is not a character or ligature, TeX skips to the next glue, and starts this algorithm anew. Otherwise a trial word is collected consisting of all following characters with non-zero \lccode from the same font as the starting letter, or ligatures consisting completely of such characters.

(『TeX by Topic』19.4節 “Hyphenation”)

つまり、グルーの直後にある英字の列が「分綴の対象となる単語」になります。言い換えると、単語が分綴されるためには直前にグルーが存在する必要があるわけです。

これを踏まえて改めて先ほどの例を考えましょう。\nobreakのないM. Snowemannの場合は、単語「Snowemann」がその直前に(空白文字に由来する)グルーをもつため分綴の対象となります。それに対して、M.\ \nobreak Snowemannの場合は「Snowemann」の直前にあるのが(\nobreakに由来する)ペナルティとなるのでこの“Snowemann”は分綴の対象から外れます。「直前の\nobreak」で単語の分綴が抑止できるのは「分綴の対象となる単語」の条件のせいでした。

この理由を知ってしまうと、単語の直前に置くペナルティの値は10000でなくてもよいことが解ります。例えば、\nobreakの代わりに\allowbreakを置いたとします。

Redd~M. \allowbreak Snowemann.

\allowbreakは値が0のペナルティを配置するマクロです。値が0のペナルティは本来は“行分割を抑止する”効果はない5はずです。しかし「分綴の対象となる単語」の条件に関する限り、直前にあるペナルティの値が何であろうと「直前がグルーである」という条件に反することに変わりはありません。結局「\allowbreakも単語の分綴を抑止する」という直感に反する結果になります。

チョット余談

TeXには「段落先頭にある単語は分綴されない」という癖があることが知られています。

\documentclass{article}
\begin{document}
\fbox{\parbox{10em}{% 段落先頭に長い単語がある
Supercalifragilisticexpialidocious, isn't it?
}}
\end{document}

出力結果
この癖の理由も「分綴対象の単語の条件」を考えれば解ります。段落冒頭にある単語は(水平リスト中で)直前に何もないので「グルーの直後」の条件を満たさないのです。

まとめ

相変わらずやってます🌸


  1. 文献スタイルファイルで用いるプログラミング言語は公式には名前が付いていないのですが、一部の人🙃は文献スタイルファイルの拡張子「.bst」にちなんでこれを“BeaST言語”と呼んでいます。
  2. ただしLaTeXでは\nobreakは“LaTeX保護付”になっています。ちなみにLaTeXにおいて行分割を抑止するためのユーザレベル命令は\nolinebreakです。
  3. ちなみに、M.\ \nobreak Snowemannというコードでは“M.”と“Snowemann”の間の行分割は抑止されません。\nobreakの前に\によるグルーが存在し、これには後にある\nobreakのペナルティは波及しないからです。
  4. \nobreak付きの場合に“It’s”の直後で(行分割を少しでもマシにしようと努めて)行分割されていることにも注意しましょう。つまりこの位置での行分割は抑止されていません。
  5. \allowbreakはplain TeXにおいて「通常は行分割が不可能な位置を可能にする」ために使われます。LaTeXでは同様の機能は\linebreak[0]で実現できます。



以上の内容はhttps://zrbabbler.hatenablog.com/entry/2025/04/26/185605より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14