リストを入れ子にすると、LaTeX は階層に応じて行頭のラベルを切り替えます。ところが itemize の項目のなかに置いた enumerate は、版面では第 2 階層に見えるのに「(a)」ではなく「1.」から始まります。LaTeX が数えているのは紙の上の深さではなく、同じ種類のリストが何重に囲んでいるか だからです。この一点を知らないまま入れ子を書くと、出力を見て首をかしげることになります。このページでは、ラベルがどう選ばれるか、Too deeply nested という壁が四段目に立っている理由、リスト全体で共有される別の上限、そして深くするほど確実に失われていく行の幅を扱います。
ラベルを決めるのは版面の深さではなく、同じ種類の入れ子の数
LaTeX は深さを 二本のカウンタで別々に 数えています。latex.ltx の中で itemize は \@itemdepth を、enumerate は \@enumdepth を進め、それぞれの値から \labelitem + ローマ数字、\labelenum + ローマ数字という命令名を組み立てて呼びます。二本は互いに無関係なので、itemize の中の enumerate は \@enumdepth としては 1 段目——だから \labelenumi が使われ、番号は「1.」から始まります。よく「入れ子の深さで一律にラベルが決まる」と説明されますが、それは誤りです。実際に組んでみると一目で分かります。
\begin{enumerate}
\item Make the dough
\begin{itemize}
\item Flour
\item Water
\begin{enumerate}
\item Add half
\item Add the rest
\end{enumerate}
\end{itemize}
\item Let it rest
\end{enumerate}この三段の入れ子が実際にどう出るかというと、外側の enumerate は「1.」「2.」、その中の itemize は第 2 階層のダッシュ – ではなく 第 1 階層の黒丸 •、いちばん内側の enumerate は第 3 階層のローマ数字 i. ではなく 第 2 階層の (a) です。itemize にとってはこれが最初の itemize であり、内側の enumerate にとっては外側の enumerate が一つあるだけ、という数え方をしているからです。種類を交互に重ねれば、それぞれの種類のラベルを順に使い切っていくことになります。
| 深さ | 環境 | その種類での段数 | 出るラベル |
|---|---|---|---|
1 | itemize | 1 | • (\labelitemi) |
2 | enumerate | 1 | 1. (\labelenumi) |
3 | itemize | 2 | – (\labelitemii) |
4 | enumerate | 2 | (a) (\labelenumii) |
5 | itemize | 3 | * (\labelitemiii) |
6 | enumerate | 3 | i. (\labelenumiii) |
四段目の壁——! LaTeX Error: Too deeply nested.
同じ種類のリストを五重にすると、コンパイルは ! LaTeX Error: Too deeply nested. で止まります。メッセージは 深さの数字を教えてくれません——Too deeply nested の一言だけなので、どの \begin が五段目なのかは自分で数えることになります。エラーの位置として報告される行番号が、五段目を開いた \begin{itemize} の行です。理由は組版上の禁止ではなく、単なる名前不足で、latex.ltx の判定は \ifnum \@itemdepth >\thr@@(3 より大きいか)というだけ。四段目までしかラベル命令が定義されておらず、五段目に渡す名前が無いから止まる、それだけのことです。だから enumitem を読み込んだだけではこの壁は消えません。設定を何も足さずに五段目を開けば、同じエラーが同じように出ます。
% raising the ceiling really does take all four lines
\usepackage{enumitem}
\setlistdepth{9}
\renewlist{itemize}{itemize}{9}
\setlist[itemize]{label=$\cdot$}
\setlist[itemize,1]{label=$\bullet$}壁を本当に取り払うには、enumitem の \setlistdepth だけでは足りません。\setlistdepth{9} はリスト全体の上限を上げるだけで、itemize そのものは四段目で止まったままです。\renewlist{itemize}{itemize}{9} を書いて環境を九段対応で作り直し、そのうえで \setlist[itemize]{label=…} で新しい段のラベルを与えて、ようやく五段目以降が組めるようになります。ラベルを与えずに五段目を開くと、今度は ! Package enumitem Error: Undefined label. に変わるだけです。数字を並べた深い階層を扱いたいだけなら、easylist のように最初から任意の深さを前提に設計されたパッケージのほうが素直です。ただし、その前に一度立ち止まってください——五段の入れ子を読み下せる読者はほとんどいません。深すぎる入れ子は、たいてい節見出しに直すべき構造の兆候です。
もう一つの上限——リスト環境が共有する 6 段の予算
種類ごとの 4 段の上に、すべてのリストで共有される 6 段の上限 がもう一枚あります。itemize も enumerate も内部では同じ list 環境の上に作られており、その list が \ifnum \@listdepth >5 という判定を持っているからです。itemize と enumerate を交互に重ねれば 6 段までは通りますが、7 段目でやはり Too deeply nested になります。厄介なのは、この予算を使うのがリストだけではないことです。article.cls を見ると quote・quotation・verse・description、そして thebibliography までが \list の上に作られています。深い箇条書きのなかで引用ブロックを二重にすると、それだけで残りの予算を食い尽くしてエラーになる——原因が「引用」に見えないので、この形の事故はいちばん見つけにくい部類です。
インデントは足し算で効く——四段目で行幅の四分の一が消える
入れ子の本当のコストは、ラベルではなく 行の幅 に現れます。list 環境は開くたびに \leftmargin を左の総和に足し込むので、インデントは階層ごとに積み上がります。10pt の article(1 段組)だと \leftmargini が 25.0pt、\leftmarginii が 22.0pt、\leftmarginiii が 18.7pt、\leftmarginiv が 17.0pt。四段目に到達したときの左マージンの合計は 82.7pt で、本文の幅 345pt に対して およそ四分の一 が失われ、残る行幅は 262.3pt になります。値が階層ごとに少しずつ小さく設定されているのは、この積み上がりを緩めるための配慮ですが、それでも四段でこれだけ削られます。
| 長さ | 値 | そこまでの累計 | 残る行幅(textwidth 345pt) |
|---|---|---|---|
\leftmargini | 25.0pt(2.5em) | 25.0pt | 320.0pt |
\leftmarginii | 22.0pt(2.2em) | 47.0pt | 298.0pt |
\leftmarginiii | 18.7pt(1.87em) | 65.7pt | 279.3pt |
\leftmarginiv | 17.0pt(1.7em) | 82.7pt | 262.3pt |
数字にすると、深い入れ子が読みにくい理由が具体的になります。262pt の幅というのは 2 段組の 1 段分に近く、そこへ長い文を流し込めば行分割の余地が減って、単語間の空きが不自然に開いたり、Overfull \hbox の警告が増えたりします。加えて 2 段組ではそもそも \leftmargini が 2em に縮められており、版面が狭いほど入れ子の余裕は無くなります。左マージンを詰めたいときは、enumitem の leftmargin= を階層ごとに指定するのが実用的です。ただし、そこまで手を入れる前に構造を見直したほうが早いことのほうが多い——第 3 階層より深い項目は、たいてい親の項目に散文として畳み込めます。
入れ子をどこで止めるか
LaTeX は 4 段まで許しますが、それは「4 段まで読める」という意味ではありません。深い入れ子が伝えているのは階層構造そのものであって、読者はその構造を 行頭記号の形と左端の位置だけ から復元しなければなりません。第 3 階層のアスタリスクと第 4 階層の中点は形が似ていて、しかも両者のインデント差はわずか 17pt です。つまり第 4 階層まで来ると、読者が構造を見分ける手がかりはほとんど残っていない。以下は、入れ子を書き終えたあとの見直しに使えるチェックリストです。
- 2 階層で足りているか確かめる。 3 階層以上は、たいてい親の項目に散文として畳み込めます。
- 深い階層が本当に必要なら、リストではなく節見出しにする。
\subsectionと\subsubsectionには目次と相互参照が付いてきます。 - 種類を混ぜたら出力を必ず目で見る。 ラベルは同じ種類の入れ子の数で決まるので、想定と違う記号が出ることがあります。
quoteやverseを深い入れ子の中で使わない。 同じ 6 段の予算を消費し、原因の分かりにくいエラーを招きます。Too deeply nestedが出たら深さを数え直す。 メッセージは段数を教えないので、報告された行から\beginをさかのぼります。