2014」の1日目の記事です。LaTeXのマクロ定義」と題して、「LaTeXのマクロ(ユーザ定義命令)」を作る命令(\newcommandなど)の使い方を紹介しました。そこで述べられているように、LaTeX標準での命令定義機能には割と大きな制約があります。複数の引数をとる命令の場合、最初の1つしかオプション引数([...]で表される省略可能な引数)にできない。ユーザ定義命令の引数が「段落をまたぐ」ことの可否を選べるが、全部の引数について一律に許可する(\newcommand)か、あるいは一律に禁止する(\newcommand*)かの選択しかなく、個別の引数ごとに選ぶことができない。LaTeXの慣習では、ある命令の“変種”を命令の制御綴の後に*を置いたもので表す。(例えば\hspace命令に対する\hspace*など。)しかし、標準の命令定義機能はこれに対応できない。LaTeXの慣習では、必須の引数は{...}、オプション引数は[...]で表すのが原則である。例外的に「変な括弧」が用いられること(例えば\framebox(1,1){...}やBeamerの\only<2>{...}など)がある。標準の命令定義機能はこれにも対応できない。これらの制限を全て取り払って「極めて自由な書式をもつユーザ命令を定義可能にする」機能を提供するのが、“LaTeX3チーム”が開発したxparseパッケージです。本記事では、このxparseパッケージの基本的な利用方法を解説します。LaTeX)を開発するチームのことであって、xparseパッケージもLaTeX3と多少の繋がりがあるのですが、ここではLaTeX3については触れません。付けて示すことにします。普通に\usepackage命令で読み込みます。パッケージオプションはありません。\usepackage{xparse}以下で示す例では、xparseパッケージ(および\color命令のためにcolorパッケージ)が読みこまれていることを前提にします。新たに命令を定義するすなわち、標準の\newcommandに相当するものです。xparseでは、\NewDocumentCommandという命令を使います。\NewDocumentCommand\命令名{引数仕様}{定義本体}これを従来の\newcommandと比較してみましょう。\newcommand[*]{\命令名}[引数の個数]{定義本体}\NewDocumentCommandでは非常に複雑な「引数の書式」、例えば「引数は5個あって、そのうち2・4番目はオプションで、最初の3つは段落をまたがない」のようなものが許容されます。specification)という文字列を定義時に指定する必要があります。この引数仕様は少し複雑で取っつきにくいものですが、xparseを使う上で不可欠なものなので、取りあえずは必要なものから確実に理解していくことにしましょう。簡単な、引数のない場合です。赤い大きな文字で「アレ」と出力する命令\myAreを定義してみましょう。この場合、引数仕様には空の文字列を指定します。引数仕様は必須引数なので決して省略できないことに注意して下さい。使ってみる{\TeX}は{\myAre}です。次に、必須の引数のみをもつ命令を定義しましょう。例として、2つの必須引数をもつ命令\myAlertを定義してみます。\newcommandの場合は引数の個数を表す[2]を付けるのでした。mを指定します(空白は任意)。使ってみる{\TeX}は\myAlert{red}{アレ}です。既存の命令の定義を変更する、など\NewDocumentCommand命令は\newcommandに相当するものなので、当該の名前の命令が既に定義済の場合はエラーが発生します。\NewDocumentCommandは「LaTeX3形式のエラー通知機能」を使用するので次のようなド派手なエラーメッセージを表示しますが、要するに「定義済だからエラー」ということです。#2}}既に定義済の命令の定義を変更するには、\RenewDocumentCommand命令を利用します。標準の\renewcommandに相当するものです。\RenewDocumentCommand命令を使用すると、やはり次のようなド派手な警告メッセージが出ますが、意図通りであるなら気にする必要はありません。※xparseは、命令が再定義された時に必ず警告メッセージを出します。命令が新たに定義された場合はログに情報(Info)メッセージを書き出します。\providecommandに相当するもの、つまり「当該の命令が未定義の場合のみ定義する」を実行するには\ProvideDocumentCommandを利用します。\ProvideDocumentCommand\命令名{引数仕様}{定義本体}ここまでは標準と同じですが、実はxparseにはもう1つのパターンがあります。\DeclareDocumentCommand命令は「当該の命令が定義済か否かに関わらず無条件に指定の定義を実行する」という動作をします。マクロ定義」の記事を読んだ人ならば、標準LaTeXがこのパターンをサポートしていない理由は既に解っているでしょう。\DeclareDocumentCommandは結局同じ危険性を持ち合わせているわけです。\defとは異なりこちらはxparseの命令なので、先に述べたように再定義が起こったときは例のド派手な警告が出現するので、\defよりは安全でしょう。いってもやはりこの命令の使用については慎重であるべきだと私は思います。オプション引数をもつ命令\newcommand等の標準の命令では、「オプション引数にできるのは先頭の引数のみ」という大きな制約がありました。xparseでは、必須引数とオプション引数を任意に混在させた書式の命令が定義できます。オプション引数をもつ命令を定義するには、引数仕様としてmではなく大文字のO(<optional)を指定します。「2つの引数をもち、そのうち1つ目がオプションである」という場合はOとmを順に並べればよいわけです。実際にはOは「引数を省略した時の既定の値」を“引数”にとってO{値}のように書く必要があります。「2つの引数をもち、そのうち1つ目がオプションで既定値がredである」ような命令\myAlertAを定義する場合は以下の文を実行します。#2}}引数仕様の中の1文字が1つの引数に対応するので、これまでの説明から、「2つ目の引数だけをオプションにする」「両方の引数をオプションにする」方法も容易に解るでしょう。それぞれ次のようになります。(これらは\newcommandでは実現できません。#2}}もう少し複雑な例として、「必須引数の前後にオプション引数がある」命令を定義してみます。{#1は{\color{#2}#3アレ}}この引数の形式の場合、[テキスト]と[フォント命令]の両方について明示・省略が選べるようになります。アレ}.引数が段落をまたぐのを許可するLaTeX標準の機能で命令を定義する場合、引数が段落をまたぐことを許すか否かを選択することができました。argument)と呼びます)。xparseの機能を用いて定義された命令の場合、既定では引数は「短い引数」になります。これを「長い引数」に変えたい場合は、引数仕様の中の対応する文字の前に+を付けます。引数の各々に対して、それが「長い」か「短い」かを指定することができるわけです。{\fcolorbox{#1}{#2}{\parbox{#3}{#4}}}上の例では、色名と寸法値が入るはずの引数は「短い」ものとしつつ、最後のテキスト(\parboxの引数となるもの)の引数については、指定を+mとして「長い」引数にしています。従って、次のように、改段落(空行で表される)を含むテキストを引数にとることが可能です。\myFramedParBox{red}[yellow]{10zw}{%{\TeX}はアレです。TikZはもっともっとアレです。今までに紹介した命令(\ナントカDocumentCommand)で定義した命令は必ず(LaTeXの意味で)「頑強(robust)」(さらに言うと、「保護付(protected)」と同様の状態)になります。「LaTeXのマクロ」の範囲で頑強・保護付になって不利になるという場面はほぼあり得ないと思うので、「頑強」の概念をまだ理解していない人は特にこれを気にする必要はありません。要するにe-TeXの\protectedにより保護されたマクロになります。既定値無しのオプション引数オプション引数の指定Oは必ず「既定値の指定」をもち、省略した時の動作は「既定値を指定したときと同じ」でした。これに対して、「引数が指定されたか否かで条件分岐したい」という場合が考えられます。先の例の\myAlertA[色名]{テキスト}について、「色名が省略された場合は特定の“既定の色”にするのでなく、そもそも色変更を行わない」という動作に変えたいとします。この命令を\myAlertDとすると、この命令の動作は次のようになるべきで、どうしても条件分岐が必要となってきます。アレ}これを実現するには、「既定値なしのオプション引数」を表す引数仕様文字である小文字のo<optional)を利用します。“値無し”を意味する特殊な「NoValueマーカー」が紐づけられます。従って、あとは値が「NoValueマーカー」であるかを判定して条件分岐する機構があればよさそうです。xparseではそのような命令を用意しています。コードの一方を実行する(存在しない場合は何もしない)」という動作を行います。これらの命令は完全展開可能です。}%}実際に試してみましょう。{\color{blue}{\TeX}は\myAlertD[red]{アレ}で\myAlertD{アレ}です。以下のような「*-形」をもつ命令\myAlertEを定義したいとします。アレ}(*-形の時はさらに赤くする)xparseの場合、「*があるか」というのを一種の引数とみなし、それを引数仕様文字s(<star)で表します。\myAlertEの場合、先頭に「*の引数」があるので以下のような引数仕様になります。#2=テキスト}この場合、#1には「*があるか」の真偽値を示す特殊なフラグが紐づけられます。この真偽値フラグを以下の命令に渡して条件分岐ができます。\IfBooleanTF{引数}{真}{偽}\IfBooleanT{引数}{真}\IfBooleanF{引数}{偽}これらは何れも、「引数の真偽値フラグの値に応じて真と偽のコードの一方を実行する(存在しない場合は何もしない)」という動作を行います。)最終的に\myAlertEの実装は以下のようになります。}%}実際に試してみます。{\TeX}は\myAlertE{アレ}で\myAlertE*{アレ}です。ちなみに、引数仕様sは先頭引数以外でも使用できます。次のような命令定義も可能です。使用例\mySampleA*{\TeX}{アレ}、だが\mySampleA{TikZ}*{もっとアレ}。“*”以外の記号を使うLaTeXにおいて、*以外の記号による条件分布を行う命令が使われることがあります。xkeyvalパッケージには\setkeysという命令がありますが、これには*-形\setkeys*の他に“+-形”\setkeys+も持ちます。xparseではこのような“変なスター”で分岐する命令を作ることもできます。引数仕様にSの代わりにt記号(<token)を指定するだけです。定義本体での引数の扱いはsと全く同じです。“変な括弧”を使う次のように解釈される命令\myPutTextを定義したいとします。※これはpicture環境内で用いて、「指定の座標に指定の位置をアンカーとしてテキストを出力する」ためのものです。\put(座標){\makebox(0,0)[位置]{テキスト}}座標は必須、位置はオプションで既定値はc。)で囲まれる必須引数を持っています。このような“変な括弧”で囲まれた必須引数を扱う引数仕様文字がr(<required)で、これは後に「括弧として使う文字のペア」を付けて使います。今の場合、引数仕様の中でr()を指定することになります。この場合、もし\myPutTextの直後に(が無かったとすると、「(が無い」という趣旨の(ド派手な)エラーメッセージが出ます。\myPutText(10,10){\color{magenta}\TeX}\end{picture}また同様に、“変な括弧”をもつオプション指定を扱うこともできます。r()の代わりにd()を指定すると、変な括弧であることを除いてoと同じ動作になります。(がない場合は当該引数は「NoValueマーカー」になります。(d<delimited)r()の代わりにD(){既定値}を指定すると、変な括弧であることを除いてO{既定値}と同じ動作になります。(が無い場合は当該引数は既定値になります。長い引数なお、引数仕様文字には、ここで紹介しなかったもっと変態なもの(verbatim引数、区切り付引数、......)も存在するので、変態に興味がある人はxparseのマニュアルを参照してください。(ただし、xparseのマニュアルの説明には少しばかりexpl3の概念が入り込んでいることに注意。