TeXの記憶(84) — \@tforよりパターンマッチングという手があった

\@tforを使って1文字ずつ取り出すマクロを書いた後に、引き数のパターンマッチングを使ったらあっという間に同じことができた、という例です。

LaTeXを使っていて、

リプシッツ(Lipsitz)定数

1027

のように索引項目の間に(欧文)が入っている用語が多く出てくるときがあります。( と ) 以外はボールドフォントです。
これらを索引するときに、和文と欧文を分けて

\index{リプシッツていすう@リプシッツ定数}
\index{Lipsitz@Lipsitz}

のようにする必要がありました。これをいちいち手動でするのは面倒くさい。そこで、「リプシッツ(Lipsitz)定数」全体を一つの引き数として扱って自動的に分ける方法を考えてみました。

最初に思ったのは引き数を1文字ずつ取り出して組み立てる方法です。

\newif\ifxbIdxIN
\newif\ifxbIdxPOS
\def\@xxbIdx[#1]#2{%
  \def\ARG{#1}\def\XXX{XXX}%
  \xbIdxINfalse\xbIdxPOSfalse
  \let\inS\empty\let\preS\empty\let\posS\empty
  \@tfor\STR:=#2\do{%
    \if\STR(\xbIdxINtrue
    \else\if\STR)\xbIdxPOStrue
    \else\ifxbIdxPOS\edef\posS{\posS\STR}%
    \else\ifxbIdxIN\edef\inS{\inS\STR}%
    \else\edef\preS{\preS\STR}\fi\fi\fi\fi}%
  {\bfseries\selectfont\mathversion{bold}%
    \preS{\normalfont(}\inS{\normalfont)}\posS}%
  \ifx\ARG\XXX\index{\preS\posS @\preS\posS}\else
  \index{\ARG @\preS\posS}\fi\index{\inS @\inS}}

1文字ずつ取り出しながら ( までの文字列が\preS、
( から ) までの文字列が\inS
引き数の最後までの文字列は\postS
として取り出しています。

これを

\xxbIdx[リプシッツていすう]{リプシッツ(Lipsitz)定数}

のように指定すると出力は

{\bf リプシッツ{\rm (}Lipsitz{\rm )}定数}

となり、idxファイルにも目的項目が入ります。

でも、後から考えてみたらTeXのパターンマッチングを使えばこんな面倒な手順は不要なことが分かりました。

\def\XXX[#1][#2(#3)#4]{{\bf #1{\rm (#2)}#3}%
  \index{#1@#2#4}\index{#3@#3}}

たったこれだけで、上の長いマクロと(ほぼ)同じことができてしまいます。ちょっと気が抜けてしまいました。

コメント