マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

\index 命令中の”\”の機能がヤヤコシイ話

LaTeXでMakeIndex(mendexやupmendexも含む)を利用して索引を作る場合の、\index命令中の「エスケープ処理」について。具体的には、quote(")とescape(\)の違いについて。

※実はMakeIndexは「LaTeX専用」でも「TeX専用」でもないのであるが、ここではLaTeXとの併用を前提とする。

\index にイロイロ書ける件

\index命令の「実際のテキスト」の部分(@の右側に相当する部分)には「索引中でその項目を実際に出力するためのLaTeXコード」を書く。このLaTeXコードはその場では実行されず、コードの文字列が.idxファイル(MakeIndexの入力)を経由して.indファイル(同じく出力)にそのまま書き出されて、それがLaTeXで読み込まれる際に実行されることになる。従って、\verbなどの「呪われた命令」を書くこともできる。

\index{%@\verb+%+ (comment)}

※つまり、\index命令の引数はverbatimなものとして解釈されている。なので、引数中に「呪われた命令」を書ける代わりに、\index自体が「呪われた命令」になってしまう。この辺りの「実際の仕様」については以下の記事を参照されたい。

\index でquoteする件

ただし、\indexの引数の書式では、幾つかの文字に特別な意味を持たせている。例えば、@は「『キー』と『実際のテキスト』の区切り文字」であり、!は「階層の区切り文字」として使われる。従って、「実際のテキスト」の内容にこれらの文字を含めたい場合は“エスケープ”をする必要がある。もちろん、これはMakeIndexのレベルのもので、LaTeXにおけるエスケープとは別物である。(LaTeXエスケープ文字\は寧ろそのまま出力されてほしい。)MakeIndex(の既定)では、“エスケープ”の役割を"に割り当てていて、これを“quote”と呼んでいる。

例えば、MakeIndexの特殊文字である!を「実際のテキスト」(および「キー」)に書くには、これをquoteして"!と書く必要がある。

% ! を " でquoteした
\index{Happy TeXing"!@Happy {\TeX}ing"!}
%→"実際のテキスト"は Happy {\TeX}ing!

※quoteを付けた文字列は.idxにはそのまま書き出される。.idxを読み込み“引数を解析する”際に「quoteの解釈」が行われる。

注意として、MakeIndexの処理においては原則的に(La)TeXの文法は考慮されない。(前述の通り、そもそもMakeIndexは(La)TeX専用ではない。)従って、例えば\verbが絡む場合でも「MakeIndexの特殊文字をquoteする("を前置する)」という規則は変わらない。

% ! を " でquoteした
\index{"!@\verb+"!+ (level operator)}
%→"実際のテキスト"は \verb+!+

% もし \verb の区切りを | にしたい場合は,
% | も特殊文字なのでquoteする必要がある.
\index{"!@\verb"|"!"| (level operator)}
%→"実際のテキスト"は \verb|!|

quoteをquoteする件

"がquoteに使われるということは、"自身もMakeIndexの特殊文字の一種ということになる。もし"を「実際のテキスト」に含みたい場合は""と書く必要がある。

% " を " でquoteした
\index{""@\verb+""+ (quote)}
%→"実際のテキスト"は \verb+"+

\index で“\”も特殊な件

これまでの話から考えると、(La)TeXエスケープ文字である\はMakeIndexにおいては特殊文字ではないように思える。事実、\!を「実際のテキスト」に書いた場合、!エスケープされることなく「階層の区切り文字」として働く。

% 失敗: ! で階層が分けられるので不正な入力になる
\index{\!@\verb+\!+ (negative thin space)}

ところが実は\もMakeIndexの特殊文字なのである。実際、MakeIndexの索引スタイルの中には“escape”という項目がありこれの既定値が\になっている。(恐らくLaTeX以外でMakeIndexを使う場合は別の文字を指定するのであろう。)といってもMakeIndexで\(つまりescape)が特殊な働きをする場面は限られていて、それは\"という文字列の扱いである。

\index{Godel@G\"odel}

この例では「実際のテキスト」の中でLaTeXのアクセント命令\"を使おうとしている。一見すると、"はquote文字であるためoを(無意味に)quoteするのに使われてしまって、結果的にG\odelと解釈されてしまうように思える。しかし実はMakeIndexでは「quoteはescapeでエスケープされる」ということになっているのである((\"命令を使うために\""oと書く必要が生じるのをMakeIndexの作者が嫌ったらしい。TeX Liveに含まれるind.pdfという文書にその旨が書かれている。))。従って、先ほどの例はこのままで正しい。

% \" の " はquoteにならない
\index{Godel@G\"odel}
%→"実際のテキスト"は G\"odel

\index の規則がさらにややこしくなる件

ただこのように\を特殊扱いしたせいで、MakeIndexの規則が不用意に複雑になっている感じもする。例えば以前に出した\!を書く例を考える。単純にquoteだけ考えると、!"!に変えればよさそうに見える。

% 実はこれでもダメ: " はquoteにならない
\index{\"!@\verb+\"!+ (negative thin space)}

ところがこれだと\"という形になっているため、"がquoteにならないのである。正しい解決策は何かというと、\の特殊性を消すために\"でquoteすればよい。

% \ と ! の両方をquoteした
\index{"\"!@\verb+"\"!+ (negative thin space)}
%→"実際のテキスト"は \verb+\"+

本の種類によっては、索引のテキストでLaTeX命令を多用することもあるだろうから、\に注意を払わないといけないのは少し不便であると感じる。

escapeをescapeする件

LaTeXの規則で、\"はアクセント命令であるが、その前にさらに\がある場合は\\が命令になるため\"の部分は命令にならない。これに合わせる形で、MakeIndexの規則でも「escapeはescapeでエスケープされる」、つまり\\は(結果的に)通常の文字の\\と解釈される。

% \\ の \ はescapeにならない
\index{bogus@bo\\"!gus}
%→"実際のテキスト"は bo\\!gus

波括弧をescapeする件

MakeIndexの入力において波括弧({})は特に特殊な役割をもつわけではないが、「{}は均衡する必要がある」ことになっている。LaTeX文書中の\index命令では「均衡していないとそもそも\indexの引数が正しく読み取れない」ので当然であるが、.idxファイルの入力でも同じ規則が適用される。

自分が調べた限りだと、前にescapeのついた\{\}については「波括弧の均衡の判定」からは除外されるようである。従って、この場合もescapeは特殊な役割をもつことになる。

% \{ の波括弧は気にしない
\index{\{@$\{$ (left brace)}
%→"実際のテキスト"は $\{$

※ただしMakeIndexのマニュアル(makeindex.pdf、日付が1987年であり古い)では逆に「例外にならない」と書いてある。どこかの時点で仕様が変わったのかもしれない。

なお、\verb絡みで単独の(\のない){を入力に含めようとして"{と書くと、\index命令の引数の読取が失敗してしまう。(\index命令は波括弧はverbatim扱いしないので。)

% 失敗: \index が実行できない
\index{"{@\verb+"{+ (left brace)}

これについては簡単な解決策はないので「単独の{」は避けるしかなさそうである。それにしても、「実際のテキスト」では諸々の回避策をとれても、「キー」の部分では対処は極めて難しいように思う。

.idxファイルの入力としては「quoteされた単独の{」を含む形は許される。そのため、「ビルドのワークフローの中で.idxアドホックに書き換える」という手段で一応解決できる。

% .idxファイルの中でこの行はOK
\indexentry{"{@\verb+"{+ (left brace)}{8}   
%→"実際のテキスト"は \verb+{+

まとめ

f:id:zrbabbler:20210504102004p:plain