二重かっこの高さを中身に合わせるtexマクロを解読する

 [\![3]\!]のような二重角かっこは、\[\!\[3\]\!\]と入力すれば出すことができます。 nath.styを導入すると、\double[とか\lBrackなどと書けるようです。

しかし、このままでは中身に高さのあるもの(分数など)を入れた場合に見栄えが良くありません。 中身に応じた高さにしてくれる\leftマクロは\double[lBrackには適用できないようです。

\!で間隔を詰める方法の場合、高さが二倍くらいの分数であれば、\!\!を使って\left\[\!\!\left[ \frac{1}{2} \right]\!\!\right]のようにすれば見栄えはよくなります。 つまり、中身の高さに応じて詰める間隔を変えないといけないということです。 どうにかして自動で変わってくれないでしょうか。

これを可能にしたマクロがBracket: LaTeXにありました。 それは、以下のようなものです。

\makeatletter
\def\Left#1#2\Right{\begingroup%
   \def\ts@r{\nulldelimiterspace=0pt \mathsurround=0pt}%
   \let\@hat=#1%
   \def\sht@im{#2}%
   \def\@t{{\mathchoice{\def\@fen{\displaystyle}\k@fel}%
          {\def\@fen{\textstyle}\k@fel}%
          {\def\@fen{\scriptstyle}\k@fel}%
          {\def\@fen{\scriptscriptstyle}\k@fel}}}%
   \def\g@rin{\ts@r\left\@hat\vphantom{\sht@im}\right.}%
   \def\k@fel{\setbox0=\hbox{$\@fen\g@rin$}\hbox{%
      $\@fen \kern.3875\wd0 \copy0 \kern-.3875\wd0%
      \llap{\copy0}\kern.3875\wd0$}}%
      \def\pt@h{\mathopen\@t}\pt@h\sht@im%
      \Right}%
\def\Right#1{\let\@hat=#1%
   \def\st@m{\mathclose\@t}%
   \st@m\endgroup}
\makeatother

このマクロを解読していきます。 私はtex言語は全くの素人なので間違った解釈があるかもしれない点に注意してください。

制御綴り

\の後に「通常の文字」がいくつか並んだものを制御綴りというそうです。 もっぱらマクロ名や変数名に使われている印象です。

\makeatletter, \makeatother

@を「通常の文字」扱いに変更する命令と、「その他の文字」扱いに戻す命令のようです。 このマクロの中で現れる制御綴りはすべて@を含んでいます。 ユーザーランドでは@は「その他の文字」であるので、うっかり@を含む制御綴りを定義することはありません。 よって@を含む制御綴りは、一種の予約語としてシステムが使うことができます。

末尾の%

末尾の改行は半角スペースに変わってしまいます(和文だとこれを取り除いてくれる機能がplatexにあるようです)。 行末に%を置くことで、半角スペースの挿入を抑止できます。 しかし、インデントのために半角スペースを入れているので意味がない気がします。 他の効果もあるようですが、よくわかりません。

\Left#1#2\Right

パターンマッチという引数の取り方で、\Leftの次のトークン(開きかっこ)を#1に入れ、\Rightが見つかるまでの残りのすべてのトークン(かっこの中身)を#2に入れるようです。

\begingroup, \endgroup

{}の代替であり、グルーピングに使うようです。 変数の代入などは、この範囲でしか影響を及ぼさないという効果があるようです。 C言語でいうところのスコープのようなものでしょうか。

なぜ代替する必要があるのかはよくわかりませんでした。

\ts@r

いきなり読めない意味不明なマクロ名ですが、{\nulldelimiterspace=0pt \mathsurround=0pt}に置換されるだけです。 \mathsurroundは、数式モードに出入りするときの空白に関するパラメータのようです。数式モードでないところで書いたときでも内部的には数式モードで描画される(後述)ので、その調整用っぽいです。 \nulldelimiterspaceはよくわかりませんでした。

\@hat

これは開きかっこを保持する変数のようです。後では閉じかっこを保持することになります。

\sht@im

かっこの中身を保持する変数のようです。

\@t

今の環境(数式モードの中か?など)によって表示するものを切り替える機能を持つ\mathchoiceを使っているようです。

\g@rin

\left\@hat\vphantom{\sht@im}\right.によって正しい高さの開きかっこだけを描画しています。 \vphantomは中身を描画せず中身を描画した時の高さになるようなものです。 \right.は閉じかっこを描画しないで\leftを閉じるものです。

k@fel

二重かっこを描画する部分です。まず\setbox0=\hbox{$\@fen\g@rin$}で適切なかっこを数式モード描画したものをbox0変数に入れます。 \kernは水平方向の位置制御、\wd0box0変数の幅、\llapは中身を重ねて描画するもののようです。 \copy0box0変数の中身を描画しています。

pt@h

開きかっこの詰め具合で必要な開きかっこを描画するようです。

本体

\pt@h\sht@im\Rightが本体で、適切な開きかっこと中身を打ち出し、このマクロのパターンマッチで消えた\Rightを復活させます。

\Right

\@hat変数に閉じかっこを入れてから\@tを呼び出すことで、上と同じ方式でうまく二重かっこを描画しています。

参考文献