改行位置の調整

TeX Live 2024 に同梱されている hyphen.tex の 1 行目は、The Plain TeX hyphenation tables [NOT TO BE CHANGED IN ANY WAY!] という叫びで始まります。LaTeX が 改行 のたびに参照する英語のハイフネーション規則 4447 個を収めたファイルで、その末尾にはクヌース自身が書いた 14 語だけの例外表が付いています。そこに並ぶ presentproject には 分割点が一つもありません——読み方が二通りある語は、折るのをやめたのです。行の折り位置を調整するとは、要するにこの判断を自分の原稿でやり直すことです。このページでは \\\newline\linebreak[n]\nolinebreak[n]・任意ハイフン \-\hyphenation{...}hyphenat、そして babel の言語別ハイフネーションパターンまでを、実測値つきで扱います。

先に境界線を引いておきます。空行や \par段落を変える ことと、これから扱う 段落の内側で行の折り位置を動かす ことは別の話です。前者は字下げと段落間の空きを伴い、後者は同じ一段落の中で行末の位置だけをずらします。さらにその外側には、ページの切れ目そのものを設計する層——\widowpenalty\raggedbottom の世界——があり、こちらは「改ページの設計」が担当します。段落を何行に収めるかを頼む \looseness も、実測つきでそちらに置いてあります。このページはあくまで の層です。

\\\newline の違い——同じマクロ、違う入り口

\newline\newline = \@normalcr\relax と定義されていて、\\ はその \relax の無い版ですlatex.ltx)。違いはこの \relax ひとつだけ。\\ は続く *[長さ] を読みに行きますが、\newline\relax に阻まれて読みに行けません。実際 Alpha\newline[2ex] Beta を組むと、紙面には [2ex] がそのまま印字されます。逆に \\[2ex] は行のあとに 2ex の縦空きを入れ、\\* はその位置での改ページを禁止します。オプションを使いたいなら \\、本文で意図を明示したいなら \newline、というのが実務上の使い分けです。

両者に共通するのは、行を引き伸ばさずに終える ことです。中身は \unskip … \nobreak \hfil \break で、右端に無限に伸びるグルー \hfil を置いてから折ります。この \hfil が余白を全部吸い取るので、行は自然な長さのまま短く残ります。住所や詩のように「各行を意図した長さで終えたい」ときに向くのはこのためです。ただし副作用が一つ。段落の最後に \\ を置くと、内容の無い最終行が生まれ、Underfull \hbox (badness 10000) in paragraph at lines 6--7 が出ます。段落の末尾に \\ は要りません——これは見出しの直後も同じです。折る行が存在しない位置(段落の先頭など)で使えば、今度は ! LaTeX Error: There's no line here to end. になります。

latex
% \\ and \newline end the line short; \linebreak justifies it to the margin.
First road is steep\\
second road is gentle.

% \\ takes an optional length and a star; \newline takes neither.
Alpha\\[2ex] Beta        % 2ex of vertical space after the line
Alpha\\*    Gamma        % no page break allowed here
Alpha\newline[2ex] Delta % prints a literal [2ex] on the page

% A trailing \\ at the end of a paragraph produces
%   Underfull \hbox (badness 10000) in paragraph at lines 6--7
This paragraph does not need one.

表の中では二つの役割がはっきり分かれます。tabularp{...} 列のように 段落を作るセル では、\newline はそのセル内だけで行を折り、\\ は行(レコード)全体を終わらせます。住所を 1 セルに 2 行で入れたいなら \newline。実測でも、p{3cm} セルに Line one\newline Line two と書けば同じ行の中で二段になり、右隣のセルはそのまま残りました。array 環境でも \\ が行区切りです。逆に lc のような段落を作らない列で \newline を使うと、終える行が存在しないので先ほどのエラーになります。

\linebreak[n]\nolinebreak[n] の n は、実際いくつのペナルティか

n は 0〜4 の五段階で、それぞれ 0・51・151・301・10000 というペナルティに翻訳されます。 latex.ltx\@getpen0 / \@lowpenalty / \@medpenalty / \@highpenalty / \@M を返し、標準クラスではその三つが article.cls の 118〜120 行目で 51151301 と定義されているからです。\linebreak[n] はこの値を で置き(つまり「折ると得をする」)、\nolinebreak[n] で置きます(「折ると損をする」)。引数を省略するとどちらも 4、すなわち ∓10000——TeX にとっての無限大です。数字が見えると使い分けが決まります。[1] の 51 は本文の badness に簡単に負ける「ささやき」、[3] の 301 でようやく主張らしくなり、[4] だけが命令です。

引数linebreak が置く値nolinebreak が置く値実際の強さ
[0]00ただの合法な折り点。得も損もしない
[1]-5151本文の badness に負ける「ささやき」
[2]-151151\widowpenalty の既定と同じ重み
[3]-301301ここでようやく主張になる
[4]-1000010000既定値。無限大=命令

\linebreak\\ は、折るという結果は同じでも仕上がりが正反対です。\linebreak はペナルティを置くだけなので、その行は 通常どおり両端揃えされ、右マージンまで引き伸ばされます——語間が間延びしがちなのはそのためです。\\ は先ほどの \hfil で余りを吸うので短いまま。「短く折りたいなら \\、マージンまで揃えたいなら \linebreak と覚えれば迷いません。細かい話をすると、\@no@lnbk は直前のグルーを \unskip で外し、ペナルティを置いてから同じ幅のグルーを戻します。つまり word\linebreak word と書いても空白は二重になりません。

ここで折らせない——~(タイ)と \mbox の代償

空白ひとつを守りたいだけならチルダ ~ が第一選択です。 幅は通常の単語間空白と同じで、違いは「そこで行が折れない」ことだけ。Fig.~3Dr.~SmithChapter~12equation~\ref{eq:1} のように、数字や記号と切り離してはいけない語に使います。重要なのは、~前後の語のハイフネーションを妨げない ことです。中身は \nobreak\ に近く、その位置に無限のペナルティ(\nobreak = \penalty10000)を置くだけなので、語そのものは自由に折れます。段階的に強さを指定したいなら \nolinebreak[n]、無条件に禁じたいなら低水準の \nobreak があります。

一方 \mbox{...} は別物です。中身を一つの箱にしてしまうので、行を折ることもハイフンを入れることもできなくなりますT-34 を割らせたくない、といった短い語句には向きますが、代償があります。実測:幅 4.2cm の minipagedichlorodiphenyltrichloroethane をそのまま置くと収まりますが、\mbox{...} で囲むと Overfull \hbox (18.8814pt too wide) が出て、語が右マージンを 18.88pt 突き抜けます。長い URL や化合物名を \mbox で固めるのは、直したい病気より重い薬です。次章に出てくる \hyphenation{...} の分割点なし登録や hyphenat\nohyphens{...} なら、箱にせずにハイフンだけを止められます。

ハイフネーションを追加する \-——「ここでも折れる」ではなく「ここでしか折れない」

\- を語のどこかに一つでも入れると、LaTeX はその語を、あなたが印を付けた位置でしか折らなくなります。 パターンが見つけていた候補は全部消えます。\showhyphens で並べると一目瞭然です。supercalifragilistic は素のままなら su-per-cal-ifrag-ilis-tic と 5 か所で折れますが、super\-califragilistic と書いた瞬間 super-califragilistic の 1 か所だけになります。hyphenationhy-phen-ation から hyphen\-ationhyphen-ation へ減ります。つまり \- は候補の 追加 ではなく 置換 です。望ましい分割点は自分ですべて書き出さなければなりません。なお \- は折りを強制しません——「折るなら、この候補のどれか」を示すだけです。

latex
% Ask TeX where it would break, and read the answer in the .log:
%   [] \T1/cmr/m/n/10 su-per-cal-ifrag-ilis-tic
\showhyphens{supercalifragilistic}
%   [] \T1/cmr/m/n/10 super-califragilistic   <- one \- killed the other four
\showhyphens{super\-califragilistic}

% So spell out every break point you actually want:
super\-cali\-fragi\-listic

long-standing の後半が折れないのはなぜか——hyphenat\hyp

同じ規則が、あなたが自分でタイプした普通のハイフンにも適用されるからです。 \showhyphens で確かめると、longstandinglong-stand-ing と 3 つに割れますが、long-standing と書いた途端に long-standing——つまり そのハイフンの位置だけ になり、stand-ing が消えます。well-knownX-raystate-of-the-art のような複合語がすべてこれに当たります。行末に長い複合語が来ると急に組版が苦しくなるのは、この規則のせいです。解決策は hyphenat パッケージの \hyplong\hyp standing と書くと、実測でふたたび long-stand-ing に戻ります。見た目は同じハイフンのまま、パターンによる候補が生き返るわけです。

hyphenat にはもう一つ、\mbox の代わりになる道具があります。\nohyphens{...} は中身の \language を「パターンを持たない言語」に切り替えるだけの、たった 1 行の定義です。実測でも \nohyphens{supercalifragilistic} の候補は 0 になりました。箱を作らないので、語の前後では今までどおり行が折れます——\mbox のように 18pt もはみ出す事故は起きません。同じ発想で、\bshyp\fshyp\dothyp\colonhyp は URL やパスの \/.: を「折ってよい記号」に変え、パッケージオプション [none]\hyphenpenalty=10000\exhyphenpenalty=10000 の 2 行だけで文書全体のハイフネーションを止めます。

latex
\usepackage{hyphenat}

% A plain "-" kills the rest of the word:  long-standing
% \hyp prints the same hyphen and keeps the patterns: long-stand-ing
long\hyp standing, well\hyp known, state\hyp of\hyp the\hyp art

% No hyphens in this word, but the line may still break around it.
% Unlike \mbox this cannot overflow the margin.
\nohyphens{supercalifragilistic}

% Breakable punctuation for URLs and paths:
https:\fshyp\fshyp example\dothyp com\fshyp very\fshyp long\fshyp path

\hyphenation{...} が効かないとき——アクセント・活用形・大文字

同じ語が何度も出るなら、本文を汚さずプリアンブルで例外を登録できます。書式はクヌース自身が hyphen.tex の末尾でやっているのと同じ——分割点をハイフンで示した語を \hyphenation{...} に並べるだけです。この仕組みには 表からは見えない使い道 があります。ハイフンを一つも書かずに語を登録すると、その語は二度と折られません。 実測でも \hyphenation{fortran} のあと \showhyphens{fortran} の候補は 0 になりました。冒頭で触れた presentproject がクヌースの例外表に分割点なしで載っているのは、まさにこれです。\mbox と違って箱を作らないので、行からはみ出す心配もありません。

効かない理由も三つ実測しました。第一に アクセント。OT1(既定のフォントエンコーディング)で \hyphenation{r\'e-sum\'e} と書くと ! Improper \hyphenation will be flushed. で止まります。OT1 のアクセント付き文字は \accent で合成された「文字でないもの」だからです。\usepackage[T1]{fontenc} を入れれば単一のグリフになり、同じ行が何事もなく通ります。第二に 完全一致\hyphenation{hyphena-tion} を登録すると hyphenationhyphena-tion になりますが、複数形の hyphenations は例外表に当たらず hy-phen-ations とパターンに戻ります。活用形は一つずつ登録が必要です。第三に、大文字小文字は区別しません。TeX は \lccode で小文字化してから照合するので、For-tran の 1 件で FORTRANFortranfortran の 3 通りすべてが FOR-TRANFor-tranfor-tran になりました。

latex
\usepackage[T1]{fontenc}   % without this, an accent in \hyphenation errors:
                           % ! Improper \hyphenation will be flushed.

\hyphenation{% one entry per inflected form; case does not matter
  hyphena-tion  hyphena-tions
  r\'e-sum\'e
  fortran                 % no hyphens = never break this word
}

babel の言語別ハイフネーションパターン——Wissenschaft が二通りに折れる

分割パターンは言語ごとに別物で、\language を切り替えると同じ語が違う場所で折れます。 実測がすべてを語ります。\usepackage[english,ngerman]{babel} を読み込むと \language は 36(ngerman)になり、\showhyphens{Wissenschaft Wahrscheinlichkeit}Wis-sen-schaft Wahr-schein-lich-keit と正しく折れます。ところが \selectlanguage{english}\language は 0)に切り替えた直後、同じ語が Wis-senschaft Wahrschein-lichkeit になります——ドイツ語として間違った分割です。逆も同じで、ドイツ語のパターンで英語を組むと typesettingty-pe-set-ting になります。babel を入れずに書いたドイツ語論文が妙に不格好なのは、たいていこれが原因です。

ここから直接の帰結が出ます。\hyphenation{...} の例外表も \language ごとに別々に持たれている ので、宣言した時点で有効だった言語にしか効きません。実測:\usepackage[english,ngerman]{babel} のあとプリアンブルで \hyphenation{Wiss-en-schaft} と書くと、ngerman の本文では Wiss-en-schaft と指定どおりに折れますが、\selectlanguage{english} の直後には例外がまるごと見えなくなり、英語パターンの Wis-senschaft に戻ります。多言語文書では、例外の登録は目的の言語を選択したあとに書く のが鉄則です。なお和文にはこの意味でのハイフネーションが無いので、\-\hyphenation も欧文部分のための道具です。

latex
\usepackage[T1]{fontenc}
\usepackage[english,ngerman]{babel}

% Exceptions belong to the language that is current when they are declared.
% Select the language first, then declare.
\selectlanguage{ngerman}
\hyphenation{Wiss-en-schaft}
\selectlanguage{english}
\hyphenation{hyphena-tion hyphena-tions}

% Check the result rather than guessing:
%   ngerman -> Wis-sen-schaft   english -> Wis-senschaft
\showhyphens{Wissenschaft}
命令役割行を引き伸ばす?
\\ , \newline行を強制的に折る(段落は変えない)。\\ だけが [長さ]* を取るいいえ。\hfil が余りを吸い、短いまま残る
\linebreak[n]ペナルティ −(0/51/151/301/10000) を置く。既定は n=4はい。右マージンまで両端揃えされる
\nolinebreak[n]ペナルティ +(0/51/151/301/10000) を置く。n=4 で完全禁止
~改行されない空白。ハイフネーションは妨げない
\mbox{...}中身を 1 つの箱に。折りもハイフンも不可。はみ出しの原因になる
\-任意ハイフン。その語は印を付けた位置でしか折れなくなる
\hyphyphenat。ハイフンを印字しつつ、語全体の候補を残す
\nohyphens{...}hyphenat。ハイフンだけを止める。箱にしないのではみ出さない
\hyphenation{...}プリアンブルの例外表。完全一致・大文字小文字不問・\language ごと
\showhyphens{...}その語をいまどこで折れるかを .log に書き出す診断用

改行警告を直す順番——力技は最後に

出た場所に \\ を打ち込んで消すのが、いちばんやってはいけない直し方です。 TeX の行分割は段落全体を見て最適化されるので、一行を固定すると残りの配分が変わり、別の行が壊れます。順番は、原稿の言い換え → ハイフネーション候補を足す → ~\nolinebreak で局所的に禁じる → 最後に段落全体の許容度、です。最後の段——\tolerance\emergencystretch\sloppy(既定に戻すのは \fussy)、そして Overfull \hbox の読み方——は「Overfull \hbox の直し方」が担当します(\sloppy が実は 4 行の代入にすぎないことも、そちらで実測されています)。microtype で字幅をわずかに伸縮させる手も、そこに含まれます。

  • 長い語・URL・化合物名を先に洗い出す。 \showhyphens{...} に通し、そもそも折り点があるかを確かめる。
  • 専門語には \hyphenation{...} を。 活用形ごとに登録し、多言語なら \selectlanguage のあとに書く。
  • \- は最後の一語だけに。 一つ入れた瞬間、その語の他の候補は全部消えることを忘れない。
  • 人名・番号・単位は ~ で結ぶ。 \mbox は「絶対に割ってはいけない短い語句」に限る。
  • 多言語文書では babel を必ず入れる。 言語を切り替えないままだと、片方の言語が常に間違った位置で折れる。