LaTeXのlistで段落見出しをやろうとしてはいけない
LaTeXの
\item
は\@item
を使って定義されているが、\@item
では、箇条書きの「見出し」の出し方がトリッキーな方法で実現されており、そのためlist
環境で作る箇条書き環境で見出しを段落として整形する(いわゆる「段落見出し」)ことには限界がある、という話。
LaTeXの箇条書きでは各項目を \item
で表現するのだけど、ユーザーレベルではその見出しの内容や装飾を \makelabel
を使って制御できるようになっている。\@item
の定義では、下記のように、\makelabel
で整えられた見出しの材料がいったん \box\@labels
というボックスに格納されることになっている。このボックスは、やはり \@item
の中で用意されている \everypar
によって段落の先頭に追加されることで、最終的に組版されるという仕掛け。
\def\@item[#1]{%
\if@noparitem
\@donoparitem
\else
\if@inlabel
\indent \par
\fi
\ifhmode
\unskip\unskip \par
\fi
\if@newlist
\if@nobreak
\@nbitem
\else
\addpenalty\@beginparpenalty
\addvspace\@topsep
\addvspace{-\parskip}%
\fi
\else
\addpenalty\@itempenalty
\addvspace\itemsep
\fi
\global\@inlabeltrue
\fi
\everypar{%
\@minipagefalse
\global\@newlistfalse
\if@inlabel
\global\@inlabelfalse
{\setbox\z@\lastbox
\ifvoid\z@
\kern-\itemindent
\fi}%
\box\@labels
\penalty\z@
\fi
\if@nobreak
\@nobreakfalse
\clubpenalty \@M
\else
\clubpenalty \@clubpenalty
\everypar{}%
\fi}%
\if@noitemarg
\@noitemargfalse
\if@nmbrlist
\refstepcounter\@listctr
\fi
\fi
\sbox\@tempboxa{\makelabel{#1}}%
\global\setbox\@labels\hbox{%
\unhbox\@labels
\hskip \itemindent
\hskip -\labelwidth
\hskip -\labelsep
\ifdim \wd\@tempboxa >\labelwidth
\box\@tempboxa
\else
\hbox to\labelwidth {\unhbox\@tempboxa}%
\fi
\hskip \labelsep}%
\ignorespaces}
TeXは \item
に遭遇すると、まず @inlabel
フラグをオンにする(厳密にいえば \@noparitem
フラグが立っているときは @inlabel
が立つことはないが、ltlists.ltx
で \@noparitem
が立つように設定されているのは trivlist
くらいっぽい?)。
@inlabel
フラグがオンの場合には、\lastbox
を捨てて(つまりインデントを帳消しにして)垂直方向のグルーを挿入したあと、\box\@labels
を配置する。そのあとではじめて、\item
に続いて原稿中で示されているトークンの存在によって水平モードに入る。
このような挙動のため、\item
の「見出し」では水平モードに入っておらず、厳密には段落が始まっていない。したがって、\makelabel
でいわゆる「段落見出し」を作って独自の list
を定義した場合、\item[...]
の直後(i.e. 水平リストを開始する要素を挟まない)に itemize
環境を入れると、内側の itemize
環境の \item
の見出しが適切に「改行」されずに版面を超えて前の行に残ってしまうという事態になる。
そもそも「段落見出しが必要な場合に list
環境を使うのはどうなのか」という話でもあるんだけれど、HTMLの <DL>
のような「見出し付き箇条書き」はドキュメントの要素として一般によく使われており、その見出しの表現として「段落見出し」を使いたいのも自然に思える。こうした見出し付き箇条書きをLaTeXで表現するときにいちばん直感的なのは description
らしく、実際、Pandocでもそのように実装されている。description
は標準的には list
で定義されているので、「list
で段落見出しの箇条書き環境を定義したい」というのは、それほど無茶な要望ではないと思われる。
ワークアラウンド
\item[...]
で水平リストを明示的に開始すればいい。Pandocならこんな感じ。
item 1
: `\leavevmode\vspace{-\baselineskip}`{=latex}
* subitem 1
* subitem 2
item 2
: ...