0番染色体

科学は全世界を照らす光である

ぼくのかんがえたさいきょうの相互参照 on LaTeX

LaTeX には文書中に出てくる章番号や式・図表の番号など “連番” の登場する箇所に \label 命令でラベリングを行い,これを別の箇所から \ref 命令で参照する相互参照機能が備わっています.これは大変便利な機能で,数式の美しさと並んで「LaTeX のよいところ」としてよく取り上げられます.

しかし,そんな LaTeX の相互参照も使っていると(特に大きな文書を作成する際に)少々面倒さを感じる場面があります.一つは「文書内で一意性のあるラベル名を考えること」です.見出し・式・図表など文書内に登場するあらゆる番号に,何とも被らないラベル名をいちいち考えるのは案外骨が折れます.章ごとに異なる人が執筆を担当しているというような場合にも,ラベル名の衝突を防ぐには何らかの工夫が必要になります.

あるいは複数のラベル箇所を参照したい場合に何度も \ref 命令を並べて書かなければならないケースがあり得ます.式番号に (1) のような括弧をつける書式を利用している場合など,周辺の決まった書式や記号をいちいち入力するのは冗長ですし,それらをベタ打ちしていると,例えば原稿を書き上げてから式番号に括弧を付けない方針に転換した場合などに修正がとても煩雑です.

そこで,LaTeX オリジナルの相互参照機能を拡張して名前空間やスコープといった概念を導入し,さらに参照する番号の種類ごとに書式を柔軟にカスタマイズ可能とするパッケージを作ってみました.

github.com

WTRef パッケージを使うには

以下,本稿では現時点での最新バージョン v0.2 の基本的な使い方について解説していきます.

インストール

WTRef パッケージを使用する場合は GitHub 上のリリースページからパッケージをダウンロードし,wtref.sty をパスの通ったところに配置してください.

パッケージの読み込み

パッケージの読み込みには \usepackage 命令を用います.オプションは存在しません.

\usepackage{wtref}

相互参照命令の新設

WTRef パッケージは,読み込みを行っただけではその相互参照の拡張機能を利用することができません.そのためプリアンブル中で \newref 命令を用いて新たな相互参照命令を宣言する必要があります.

例えば,プリアンブルで

\newref{eq}

と宣言すると,それ以降 \eqlabel 命令と \eqref 命令という2つの命令が利用できるようになります.

WTRef パッケージでは,これら2命令のうち \〜label の形をしたものをラベル命令,\〜ref の形をしたものを参照命令と呼んでいます.さらに,このラベル命令と参照命令を合わせて相互参照命令と総称します.

ここで,\newref 命令の完全な書式を示しておきます.

\newref[〈options〉]{〈ref types〉}

〈options〉には名前空間やスコープに関する設定を key-value リストの形で指定することができますが,その話は後で詳しく解説するのでここでは措いておきます.

必須引数は〈ref types〉と複数形になっており,カンマ区切りで複数の〈ref type〉を指定することが可能です *1 .すなわち

\newref{eq,fig,tab}

と宣言すると,\eqlabel・\eqref・\figlabel・\figref・\tablabel・\tabref の6命令を一度に宣言することができます.〈options〉に何らかの設定を書き込んでいる場合,その設定はこれらすべてに適用されます.

相互参照命令を使う

WTRef パッケージの相互参照命令は LaTeX オリジナルの相互参照命令(\label と \ref)と同じように使用することができます.

ピタゴラスは直角三角形の各辺の長さについて,
次の等式で示される三平方の定理を発見したとされる.
\begin{equation}
a^2 + b^2 = c^2 \eqlabel{三平方の定理}
\end{equation}
ただし,式(\eqref{三平方の定理})の関係はピタゴラス
の時代よりも前から知られていたとする説も存在する.
上記コードの出力結果

一方で WTRef パッケージの相互参照命令は LaTeX オリジナルの相互参照命令にはない次のような性質があります.

名前空間

\newref 命令の引数として与えた〈ref type〉は名前空間としての役割を担います.すなわち \〈ref type〉label 命令によって作成されたラベルは,同じ〈ref type〉の \〈ref type〉ref 命令でしか参照することはできません.逆にいうと〈ref type〉が異なれば同じラベル名を使用しても衝突を起こすことはありません.

この名前空間として使用する文字列は \newref 命令の〈options〉中で namespace キーを記入することによって変更可能です.例えば,\eqlabel および \eqref で使用する名前空間として “eq” ではなく “equation” を使用したい場合,相互参照命令を次のような形で宣言します.

\newref[namespace=equation]{eq}

このしくみを利用すれば,複数の異なる〈ref type〉で1つの名前空間を共有することも可能です.

スコープ

スコープの機能はデフォルトでは無効に設定されているので,特に指定をしない場合,LaTeX ソース中で作成したラベルは同じ文書中のどこからでも参照することができます.

一方,\newref 命令の〈options〉で scope の指定を行うと,ラベルの参照可能な範囲を一定の区域内に制限することが可能です.具体的に利用可能な「区域」は使用するドキュメントクラスなどの環境に依存しますが,一般的な環境(article 系のドキュメントクラスを利用した場合)では sectionsubsection などを指定することが可能です *2

例えば,プリアンブルで次のような設定を行ったとします.

\newref[namespace=equation]{eq}
\newref[namespace=equation, scope=section]{seq}

その上で,\begin{document} に次のように続けることを考えます.

\section{ピタゴラスの定理}

ピタゴラスの定理は以下の通り.
\begin{equation}
a^2=b^2+c^2 \eqlabel{ピタゴラスの定理}
\end{equation}
式(\eqref{ピタゴラスの定理})がピタゴラスの定理である.

\section{余弦定理}

ピタゴラスの定理を一般化したものが余弦定理である.
\begin{equation}
a^2=b^2+c^2-2bc\cos A \seqlabel{余弦定理}
\end{equation}
この式(\seqref{余弦定理})が余弦定理である.

\section{復習}

ピタグラスの定理は式(\eqref{ピタゴラスの定理})で表され,
余弦定理は式(\seqref{余弦定理})で表される.

このとき,この出力結果は次のようになります.

上記コードの出力結果

\eqlabel によって貼られたラベルはスコープの設定がないので他の節(上記の例では “3 復習”)からも参照できています.一方,\seqlabel で貼られたラベルはスコープとして section が指定されているので,同じ節内からしか参照できません.そのため他の節(“3 復習”)からの参照は失敗し,出力が “(??)” となってしまっています.

スコープ外からの参照

WTRef パッケージでは,スコープの範囲外からもラベルを参照するための機能も用意しています.すなわち,参照命令のオプションに適当な参照先のカウンタ値を直接指定すると,スコープ外からもラベルを参照することが可能となります *3

例えば,上記コードの \section{復習} 以下を次のように変更することを考えます.

\section{復習}

ピタグラスの定理は式(\eqref{ピタゴラスの定理})で表され,
余弦定理は式(\seqref[2]{余弦定理})で表される.

これにより,さきほど “(??)” となっていた部分は,無事 “(2)” と参照に成功します.

ただし,このような直接指定は「後から章構成を変更しても番号が自動的に塗り替えられる」という LaTeX の長所を活かせません.そのため,このスコープ外からの参照機能は応急処置的な場合のみに使用し,常用しないことをおすすめします.スコープ外からの参照を多用しなければならないような場合は,スコープの設定自体を見直すべきです.

複数ラベルの同時指定

WTRef パッケージの参照命令の引数には,カンマ区切りで複数のラベル名を書き込むことができます *4

一例を挙げるのであれば,プリアンブルで \newref{chap} が宣言され,各章の宣言時(\chapter 命令の使用時)に \chaplabel によるラベル付けが適切になされている場合,文書中で

\chapref{数式の基本,複雑な数式,グラフィック}

などとすれば “第 5, 6, 7 章” のような出力を得ることができます.この際,デフォルトでは上記のように各参照カウンタの間にカンマと半角スペースが挿入されるように設定されていますが,この印字形式は後述する \setrefstyle 命令によってお好きなように変更することができます.

参照書式を変更する

WTRef パッケージの参照命令による出力は参照書式変更命令 \setrefstyle で自由にカスタマイズすることが可能です.はじめにこの命令の使用法を説明しておきます.

\setrefstyle{〈ref type〉}{〈options〉}

\setrefstyle 命令は \newref 命令とは異なり,プリアンブル以外でも好きな場所で利用することが可能です.

\setrefstyle の〈options〉には様々な設定を key-value リストの形で指定することが可能です.以下,設定可能な具体的なキーを順々に解説していきます.

指定可能なキー

refcmd

実際の参照を行うためのコマンドを指定します.#1 を書き込むとその部分が,適切なラベル名に置換されるので,\ref や \pageref の引数としてこれを与えます.

例えば,数式番号が (1), (2), …… のような形式で表示されるのであれば

\setrefstyle{eq}{refcmd=(\ref{#1})}

と設定することで,自動的に半角の括弧で括られるように設定できます.すなわち,上記他の設定が適切になされているとき,ソース中で

\eqref{ピタゴラスの定理,余弦定理}

とすれば “式(1), (2)” のような出力を得ることが可能です.

sep

デフォルトでは参照カウンタ同士の仕切りは {,\space} のように設定されていますが,sep キーによって好きな形に変更することができます.例えば

\setrefstyle{eq}{refcmd=(\ref{#1}), sep=と}

のように設定すれば,

\eqref{ピタゴラスの定理,余弦定理}

の出力は “式(1)と(2)” のようになります.

last sep

最後の一区切りだけは sep と異なる区切りを指定することができます.日本語文書でこの機能を使用することはあまりないかもしれませんが,例えば英語の文書を作成する際に

\setrefstyle{eq}{refcmd=(\ref{#1}), sep={,\space}, last sep=\space and\space}

と指定すれば

equation \eqref{ピタゴラスの定理,余弦定理,正弦定理}

によって “equation (1), (2) and (3)” のような出力を得ることができます.

なお,last sep の値指定を省略した場合(= 以下を記入しない場合)最後の区切りには sep の値が用いられるように設定されます.デフォルトでは,この設定が有効になっています.

prefix と suffix

prefix キーでは参照命令を使うごとに,最初に1回だけ実行・印字される文字列(制御綴も使用可)を指定できます.一方 suffix キーでは最後に1回だけ実行・印字される文字列を指定できます.

1つ具体的な利用例を挙げておきます.

\setrefstyle{chap}{prefix=第, suffix=章}

のように設定しておくと

\chapref{数式の基本,複雑な数式,グラフィック}

だけで,さきほどと同じ “第 5, 6, 7 章” のような出力を得ることが可能になります.

おわりに

実は WTRef パッケージには類似品として refstyle なる先行パッケージが旧来より存在しています *5 .しかし,refstyle パッケージは欧米の諸言語で利用することを念頭に作られているため日本語文書中での使い勝手があまりよくない点や,やたらと機能が多く不必要なマクロを大量に生成するようなところがある点に不満があります.

WTRef パッケージは,そのような観点からなるべく定義する命令の数を抑えたシンプルな設計を心がけて開発しました.また,特定の言語に特化するということをせず,汎用性を維持することにも重点を置いています.LaTeX の相互参照にスコープの概念を導入するという事例は私の知る限り他に存在していないので,その点において WTRef パッケージには新規性も担保されています.

これがはじめて開発した「実用を目的とする」LaTeX パッケージということもあって,第三者にとってどれほど使いやすいインターフェースになっているか少々自信がない部分もありますが,個人的には満足な出来に仕上がったと思っています.もしよろしければ,WTRef パッケージによる快適な相互参照をあなたも是非体験してみてください.

*1:key-value リストとは異なりカンマ前後の空白も無視されないので注意してください.

*2:正確には任意の LaTeX カウンタを使用することが可能です.しかし,スコープとして利用する以上文書内で一意性のある値をもつカウンタが望ましいので,その選択肢は限られてくると思われます.特に,WTRef パッケージ内部では \the〈counter〉の出力が用いられているので,\thesubsection の出力が section カウンタの情報を含まない場合などはスコープとしてうまく機能しない可能性があるので注意が必要です.

*3:スコープが設定されていない相互参照命令系の参照命令でオプションに何かを指定した場合,その指定は単純に無視される.

*4:このリストも key-value リストとは異なりカンマ前後の空白も無視されないので注意してください.

*5:refstyle パッケージは名称の通り「参照命令の出力形式をカスタマイズする」ことを主目的としていますが,WTRef パッケージでいう名前空間の分離に相当する機能はサポートされています.