完全攻略! LaTeX のマクロ定義

  • 107
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

これは「TeX/LaTeX Advent Caleandar 2013」の 1 日目の記事です。
(2 日目は k16shikano さん です。)

長い前置き

(さっさと飛ばして次に進みましょう :-) )

マークアップ言語としての LaTeX の強みの一つとして「マクロが使える」ことがあります。すなわち、「自分流のマークアップ」を新たに作って、その実現(表現)方法を既存の命令の組み合わせとして定義できる、ということです。

たとえば、論文などで、新出の語句をその英訳とともに次のような書式で出力したいとします。

\textsf{参照透過性}(\emph{referential transparency})

Fig.1

ここで、次のようなマクロを作っておきます。

\newcommand*{\xTerm}[2]{\textsf{#1}{(\emph{#2})}}

すると最初の例は次のように表されます。

\xTerm{参照透過性}{referential transparency}

これで「新出語句の出力」という機能を、 \xTerm という命令(マークアップ)で表せたことになります。このようにマクロを作っておくと、後で「新出語句の出力」の書式が変えたい(例えば英訳のフォントサイズを小さくしたい、等)場合でも、この \xTerm という命令の定義内容だけを変えれば済むことになります。

このように、マクロ作成は非常に便利で重要な機能ですが、残念ながら、LaTeX の初級者の間では「LaTeX のマクロは難しい」と思い込んでいる人が多いようにみえます。実のところ、現在入手可能な参考書の多くは「LaTeX のマクロ」を扱ってませんし、また解説のある参考書の多くでは、それが「TeX 言語の解説(特に TeX でのマクロ定義)」と同じ個所に載せられています。このため、「LaTeX のマクロ機能」が「TeX 言語の知識」と同じくらい難解な上級者向けの機能と思われがちなのかも知れません。

しかし、実際には、「LaTeX のマクロ作成」は何も難しくありません。特に、 TeX 言語の知識は全く必要ありません。この記事を読めば(LaTeX 標準の範囲の)マクロ機能は完全にマスターできるので、マクロをどんどん活用しましょう!

基本編

さて、これまで「マクロ」と言ってきましたが、厳密には、LaTeX の用語に「マクロ(macro)」というものはなくて、「LaTeX のマクロ」は本当は「ユーザ定義命令(user-defined command)」と呼ばれます。(元々正式な用語でないので、LaTeX で何を「マクロ」と呼ぶかは人によって異なります。)なのでここからは「マクロ」でなく「(ユーザ定義)命令」と呼ぶことにします。

ユーザ定義命令を定義するには \newcommand という命令を使用します。

引数無しの命令

\newcommand{\命令名}{定義本体}

ここで \命令名 は定義したい命令の名前で、通常の(LaTeX の)「命令の名前の規則」に合ったもので、まだ意味が定義されていないものを指定します。(指定した命令が既に定義されていた場合はエラーになります。)この文の実行以降では、「\命令名 を実行する」ことは「定義本体」を実行することと等価になります。

例を示します。

% \xAre: 赤い大きな文字で"アレ"と出力する.
\newcommand{\xAre}{{\color{red}\Large アレ}}

この定義文を実行した以降で、例えば

{\TeX}\xAre です。

のように記述すると、

{\TeX}{\color{red}\Large アレ}です。

Fig.2

という記述と等価になるわけです(\color 命令は color パッケージで提供される)。ここで注意ですが、もし \xAre の定義を

% \xAre: 赤い大きな文字で"アレ"と出力する.
\newcommand{\xAre}{\color{red}\Large アレ}

のようにしてしまう(つまり「定義本体」部分には外側の { } がない)と、{\TeX}は\xAre です。

{\TeX}\color{red}\Large アレです。

Fig.3

と等価になってしまい、これでは「です。」の部分にも色とフォントの変更が及んでしまいます。

引数付きの命令

\newcommand{\命令名}[引数の個数n]{定義本体}

ここで「引数の個数n」には 1~9 の整数を指定します。この文を実行すると、\命令名{引数1}{引数2}...{引数n} という命令実行が「定義本体の中の、#1引数1 に、…、#n引数n に置換したテキスト」の実行と等価になります。例えば、

% \xAlertA{テキスト} : 赤い大きな文字で出力する.
\newcommand{\xAlertA}[1]{{\color{red}\Large #1}}

と定義すると、命令 \xAlertA の解釈は以下のようになります。

  • \xAlertA{アレ}{\color{red}\Large アレ}
  • \xAlertA{}{\color{red}\Large }

色の指定を可変にした命令を作ることもできます。

% \xAlertB{色名}{テキスト} : 指定の色を用いて大きな文字で出力する.
\newcommand{\xAlertB}[2]{{\color{#1}\Large #2}}
  • \xAlertB{red}{アレ}{\color{red}\Large アレ}
  • \xAlertB{blue}{コレ}{\color{blue}\Large コレ}

オプション引数付きの命令

「オプション引数」というのは省略してもよい引数のことで、LaTeX では、通常の(必須の)引数を { } で囲うのに対し、オプション引数は [ ] で囲うという規則になっています。実は、さっき出てきた \newcommand{\xAlert}[1]{...}[1] もオプション引数です。

標準 LaTeX でのオプション引数付きのユーザ定義命令のサポートは限定的で、「最初の引数しかオプションにできない」という制限があります。

\newcommand{\命令名}[引数の個数n][引数1既定値]{定義本体}

この文を実行すると、\命令名[引数1]{引数2}...{引数n} という命令実行(引数1[ ] 囲みであることに注意)は先と同様に「定義本体の中の、#1引数1 に、…、#n引数n に置換したテキスト」の実行と等価になります。ところが、引数 1 はオプション引数なので省略することが可能で、もし省略して \命令名{引数2}...{引数n} の形で実行した場合、定義本体の #1 は命令定義時に指定された 引数1既定値 で置換されることになります。

例として、先に出てきた \xAlertB で色名をオプション引数(既定値 red)にしてみます。

% \xAlertC[色名]{テキスト} : 指定の色(既定値はred)を用いて大きな文字で出力する.
\newcommand{\xAlertC}[2][red]{{\color{#1}\Large #2}}

この命令 \xAlertC の解釈は以下のようになります。

  • \xAlertC[blue]{コレ}{\color{blue}\Large コレ} (オプション引数指定)
  • \xAlertC{コレ}{\color{red}\Large コレ} (オプション引数省略、既定値 red が使われる)
  • \xAlertC[]{コレ}{\color{}\Large コレ} (これはエラーになる)

発展編

引数が段落をまたぐのを禁止する

命令を定義する際に、\newcommand 命令の代わりに \newcommand* 命令を用いると、定義される命令の(全ての)引数の中に改段落(ソースでは空行で表される)を含めることが禁止されます。これは一種のフールプルーフ(誤り予防の策)として機能します。例えば、先に示した \xAlertC を使う時に、誤って引数の終わりの } を書き忘れたとします。

{\TeX}\xAlertC{アレです。

しかも{\TeX}\<(略

このソース(を含む文書)をコンパイルすると、LaTeX は \xAlertC{{ に対応する } を見つけようとしてソースファイルを(恐らく)最後まで読んでいって、そこで初めてエラーを出します(「! File ended while scanning use of \xAlertC.」が発生)。ここでもし、次のように、\xAlertC\newcommand* 命令で定義していたとします。

\newcommand*{\xAlertC}[2][red]{{\color{#1}\Large #2}}

この場合は、先に示した(間違った)ソースをコンパイルすると、LaTeX は「アレです。」の後で改段落されているのを見つけた時点でエラーを出してくれます。なぜなら \xAlertC の引数に改段落を含むことは禁止されているからです。

もちろん、定義する命令によっては、引数に改段落を含むことが正当な場合もあります。例えば、次に示す命令 \framedParBox は、引数のテキストを一定の行幅で出力しさらに周りに枠を付けるものです。

% \framedParBox[幅]{テキスト} : テキストを指定の行幅で組み枠を付けて出力する.
\newcommand{\framedParBox}[2][10zw]{%
  \fbox{\parbox{#1}{#2}}%
}

この命令は次のように段落をまたいで使用される可能性があるので、\newcommand* ではなく \newcommand を用いて定義すべきです。

\framedParBox{%
{\TeX}はアレです。

しかしWordはもっとアレです。
}

Fig.4

既存の命令の定義を変更する

\newcommand 命令で新しい命令を定義しようとした時、指定した名前の命令が既に定義されていた場合はエラーになります。これは、うかつに既存の命令の定義が変更される(そのせいで後で意味不明な動作が発生する)のを防ぐための安全装置です。

(余談)TeX 言語(LaTeX でなくて)では \def という命令でマクロを定義しますが、これは指定した命令名が定義済であっても黙って上書きするという恐ろしい性質を持ちます。ドヤ顔で TeX の \def\let を使って、その結果 LaTeX を壊してしまって後で酷い目に合ったという話は時折聞きます。「TeX の機能を使うと偉い」なんてことはないので、素直に \newcommand を使いましょう。

しかし、 「命令の定義が変更されることの影響」を完全に把握している状況 では、定義を変更することが意味を持つでしょう。これを行うのが \renewcommand 命令です。この命令の書式は \newcommand と全く同じで、また * 付きの \renewcommand* 命令も存在します。

\renewcommand{\命令名}[引数の個数n][引数1既定値]{定義本体}
\renewcommand*{\命令名}[引数の個数n][引数1既定値]{定義本体}

この命令が使われる典型的な例は「自分で(\newcommand で)定義した命令の定義を変える」という場合です。その他に、LaTeX やパッケージについて、設定変更を \renewcommand で行うことが指示されている場合があります。以下に例を示します。

  • \renewcommand{\abstractname}{ABSTRACT} ー 概要(abstract 環境)の見出しを変更する
  • \renewcommand{\topfraction}{.9} ー ページ上部へフロート(浮動体)を入りやすくする
  • \renewcommand{\theenumi}{(\arabic{enumi})} ー 番号付箇条書き(enumerate 環境)の項目ラベルの体裁を変える

LaTeX の範囲内では、\renewcommand を使うのは以上にようなケースに限られます。何れにしても、 「それで何が起こるのか」 を知っていることが大前提です。

フォールバックの定義を与える

あまり LaTeX で使う機会はないのですが、「完全攻略」にするために書いておきます。

\providecommand は、指定した命令名が未定義のときだけ、指定された命令定義を行います。定義済だった場合は単に無視されます。

\providecommand{\命令名}[引数の個数n][引数1既定値]{定義本体}
\providecommand*{\命令名}[引数の個数n][引数1既定値]{定義本体}

「テンプレート」的な文書でパッケージの使用状況が変化しうる場合に、特定のパッケージで定義されるはずの命令のフォールバック定義を与えるのに使われることがあります。

\documentclass[a4paper]{jsarticle}
% color パッケージは \textcolor 命令を定義する
\usepackage[dvipdfmx]{color}
% color が"無い"時の \textcolor の定義
\providecommand*{\textcolor}[2]{#2}
\begin{document}
{\TeX}\textcolor{red}{アレ}です。
\end{document}

上掲の例では、color パッケージの使用を止めた場合に色指定の \textcolor 命令が「単に無視される」ようにフォールバックの定義を行っています。

まとめ

「LaTeX のマクロ」は怖くありません! どんどん活用しましょう!