mdframed環境の問題

mdframed環境の問題

- 本田 知亮 の投稿
返信数: 0
長文です

先日見つけてて不思議に思ったものの放置してたんですが
mdframed環境の内部の最初の段落だけ
字下げがなくなるという問題があります
(たぶん結構知られているとは思います).

\documentclass{jarticle}
\usepackage{mdframed}
\begin{document}
\begin{mdframed}
字下げが消えた!
\par
ここにはあるぞ
\end{mdframed}
\end{document}

動作的に\@afterheadingとかの\setbox\z@\lastboxあたりが
\everyparあたりに入ってるんだろうとはあたりをつけてはいたところ
TeXConf2015で,この現象を知っていたmunepiさんから
示唆していただいたことを踏まえてmdframedを追いかけてみました.

幸いなことに先頭段落の字下げについてはTeXLive2015のrevision212と
githubにあるrevision215というのでは差はありません.

やっぱり\everyparに\setbox\z@\lastboxが入り込んでいるのですが,
欧文の場合,見出し直後は字下げしないことが多いので
実は意図的なものかもしれません.
また,mdframed環境の先頭にlist系環境がくる場合のことを
想定しているようにも思えます.

さて・・細かくみると,mdframed環境の内部を作る
\mdf@lrboxの中で\@afterheadingがコメントアウトされて
その前に\@afterindentfalseが入っています.
この\@afterindentfalseには実質上意味がないのですが,
そのあと\mdf@trivlistというmdframed版の\@trivlistに処理がわたって,
そこで\itemが発行されて\@inlabeltrueになります.

つまりmdframedの最初は\itemの直後とほぼ同じ扱いになって,
これによって,段落先頭の字下げが
\setbox\z@\lastboxで削除されます.

ですので\@inlabelfalseにすればいいのですが,
単純にそうすると今度はmdframedがlist系環境で始まると
エラーになってしまいます.
ですので,\everyparの中の先頭に\@inlabelfalseを挿入してみます.

\documentclass{jarticle}
\usepackage{mdframed}
\begin{document}

\makeatletter
\patchcmd{\mdf@trivlist}{\mdf@temp\relax}{\mdf@temp\relax\expandafter\everypar\expandafter{\expandafter\@inlabelfalse\the\everypar}}
\makeatother

\begin{mdframed}
字下げが消えた!
\par
ここにはあるぞ
\end{mdframed}
\end{document}

こうするとなんとか,
先頭にlist系環境があってもたぶん影響なく,
最初の字下げへの処置ができます.

ですが,
実はそもそも,先頭の字下げの処置をするしないにかかわらず
mdframed環境の先頭に
list系環境があって,そのあとに
普通の文がくるとlistとそのあとの地の文の間隔がなくなってしまいます.

\documentclass{jarticle}
\usepackage{mdframed}

\iffalse
\makeatletter
\patchcmd{\mdf@trivlist}{\mdf@temp\relax}{\mdf@temp\relax\expandafter\everypar\expandafter{\expandafter\global\expandafter\@inlabelfalse\the\everypar}}
\makeatother
\fi

\begin{document}
\begin{mdframed}
\begin{itemize}
\item aaaaaaa
\item aaaaaaaa
\end{itemize}
上の空きがないし字下げまでされてる!
\par
\begin{itemize}
\item aaaaaa
\item aaaaaaaa
\end{itemize}
空きがある!
\end{mdframed}
\end{document}

おまけに今度は先頭のlistの直後で字下げされます.
なぜかmdframed環境の先頭にlist系環境があると
\@noparlisttrueの状態でそのlistの終了処理の中の\endtrivlistまで進んで
ここでlist系環境の後ろに空きをいれたり,字下げの有無をしたりする
\@endparenvの処理が飛ばされます.

なぜ\@noparlisttrueの状態になるのか追い切れてませんが
\@endparenvを常に処理させるとなんとかなるようです.

\documentclass{jarticle}
\usepackage{mdframed}

\makeatletter
\def\mdf@@endtrivlist{%
\if@inlabel
\leavevmode
\global \@inlabelfalse
\fi
\if@newlist
\@noitemerr
\global \@newlistfalse
\fi
\ifhmode\unskip \par
\else
\@inmatherr{\end{\@currenvir}}%
\fi
\if@noparlist \else
\ifdim\lastskip >\z@
\@tempskipa\lastskip \vskip -\lastskip
\advance\@tempskipa\parskip \advance\@tempskipa -\@outerparskip
\vskip\@tempskipa
\fi\fi%%%%%%%
\@endparenv%%
}
\patchcmd{\mdf@trivlist}{\mdf@temp\relax}{\mdf@temp\relax\expandafter\everypar\expandafter{\expandafter\global\expandafter\@inlabelfalse\the\everypar}%
\let\endtrivlist\mdf@@endtrivlist}
\makeatother

\begin{document}
ああああああ
\begin{mdframed}
ああああああああ
\begin{itemize}
\item aaaaaaa
\item aaaaaaaa
\end{itemize}
\end{mdframed}
\end{document}

あんまりきれいな修正ではないですがなんとか動くようです.
もっとも想定し損ねているものがありそうでが.

それとTeXConf2015で話題に出ましたけど,
もうひとつ\prevdepthに関すること
(mdframedの終了時にが-1000ptになること)
もあるのですが,
これはrevision213と215で違うようで,
どうも215の状態が作者の意図なのかもしれない気がするのと
問題の理解と再現ができていないので,後回しにします.

#tcolorboxの発表が大変素晴らしかったので
#そっちの理解もしたかったり・・・