【2021年1月 追記】\autoref
にはここに書いたもの以外にも欠点がいくつかある。代替方法を \autorefの欠点と代替 に書いたので、そちらも参照して欲しい。
\newtheorem の基本
LaTeX で数学の文章を書く際には、 \newtheorem
コマンドによって定理用の環境(下の例だと theorem
という名前)を定義できる。
\newtheorem{theorem}{Theorem} % theorem 環境を定義
\begin{theorem}
人類は滅亡する。
\end{theorem}
このとき、自動的に定理番号がついて「Theorem 1 人類は滅亡する。」と出力される。
この定理を別の場所で参照したいと思った時は、定理を書くときに
\begin{theorem} \label{thm:very-important-theorem}
人類は滅亡する。
\end{theorem}
という風にラベルをつけておく。参照するときは「Theorem \ref{thm:very-important-theorem} より
」と書けば「Theorem 1 より」という風に自動的に定理番号が出力される。(ただし、定理番号を正しく出力するためには LaTeX を2回実行する必要がある)
\autoref の基本
さて、 hyperref パッケージを使うと、定理番号の部分がハイパーリンクになる。だが、「Theorem 1 より」の「1」の部分だけではなくて、「Theorem」の部分もハイパーリンクにできないものか。
そのために、 hyperref パッケージには \autoref
というコマンドが用意されている。 “Theorem \ref{thm:very-important-theorem}
” の代わりに “\autoref{thm:very-important-theorem}
” と書くと 「Theorem 1」全体がハイパーリンクになる。
ただし、環境の名前(より正確には、カウンターの名前)が “theorem
” 以外の場合は、定理番号の前の “Theorem” に相当する文字列を自前で定義してやらねばならない。また、環境(カウンター)の名前が “theorem
” であっても、定理番号の前の文字列を ”Theorem” から変えたい場合は自分で上書きする必要がある。
定理番号の前の文字列は、 “\〈環境の名前〉autorefname
”(より正確には “\〈カウンターの名前〉autorefname
”)という名前のコマンドで定義・上書きできる。
\newtheorem{theorem}{Theorem} % theorem 環境を定義
\renewcommand{\theoremautorefname}{定理} % \theoremautorefname は hyperref によって定義済み。なので「上書き」する
\newtheorem{lemma}{Lemma} % lemma 環境を定義
\newcommand{\lemmaautorefname}{補題}
\begin{theorem} \label{thm:very-important-theorem} % → Theorem 1
人類は滅亡する。
\end{theorem}
\begin{lemma} \label{lem:very-important-lemma} % → Lemma 1
第 $n$ 次世界大戦($n\gg 1$)が勃発することは、人類が滅亡する十分条件である。
\end{lemma}
\autoref{thm:very-important-theorem} % → 定理 1
\autoref{lem:very-important-lemma} % → 補題 1
カウンターを流用する場合
定理と補題の番号付けを共通にしたい場合、つまり、「定理 1」の後の補題を「補題 2」にしたい場合は、「定理」(theorem 環境)に使っているカウンターを「補題」(lemma 環境)の方で使い回すことができる。
\newtheorem{theorem}{Theorem} % 新しく theorem カウンターが作られる
\renewcommand{\theoremautorefname}{定理}
\newtheorem{lemma}[theorem]{Lemma} % theorem カウンターを流用
\newcommand{\lemmaautorefname}{補題}
\begin{theorem} \label{thm:very-important-theorem} % → Theorem 1
人類は滅亡する。
\end{theorem}
\begin{lemma} \label{lem:very-important-lemma} % → Lemma 2
第 $n$ 次世界大戦($n\gg 1$)が勃発することは、人類が滅亡する十分条件である。
\end{lemma}
\autoref{lem:very-important-lemma} % → 「補題 2」ではなく「定理 2」になってしまう
しかし、 \autoref は環境の名前ではなくカウンターの名前を参照しているため、上の例の \autoref では「補題」ではなく「定理」が出てくる(Lemma 2 で使っている環境は “lemma” だが、使っているカウンターは “theorem”)。
こういう場合、 hyperref のマニュアルには、 aliascnt パッケージを使って次のようにすると良いと書かれている。
\usepackage{aliascnt}
\newtheorem{theorem}{Theorem} % 新しく theorem カウンターが作られる
\renewcommand{\theoremautorefname}{定理}
\newaliascnt{lemma}{theorem} % lemma カウンターを作成、ただし値は theorem カウンターと同じ
\newtheorem{lemma}[lemma]{Lemma} % すでに作った lemma カウンターを使う
\aliascntresetthe{lemma} % 必要らしい
\newcommand{\lemmaautorefname}{補題}
\begin{theorem} \label{thm:very-important-theorem} % → Theorem 1
人類は滅亡する。
\end{theorem}
\begin{lemma} \label{lem:very-important-lemma} % → Lemma 2
第 $n$ 次世界大戦($n\gg 1$)が勃発することは、人類が滅亡する十分条件である。
\end{lemma}
\autoref{lem:very-important-lemma} % → 「定理 2」ではなく「補題 2」になる
ここでは、「定理」とカウンターを共有するのは「補題」だけだったが、他に「命題」だの「系」だのと増やしていくと、同じようなコードを何回も書く羽目になる。しかし、マクロを作れば同じようなコードの重複を避けることができる。
例えば、次のようにマクロを定義する。
% \newaliastheorem{(環境とカウンターの名前)}{(元となるカウンターの名前)}{(表示される文字列)}
\newcommand*{\newaliastheorem}[3]{%
\newaliascnt{#1}{#2}%
\newtheorem{#1}[#1]{#3}%
\aliascntresetthe{#1}%
\expandafter\newcommand\csname #1autorefname\endcsname{#3}%
}
使用例は次の通り。
\usepackage{aliascnt}
% \newaliastheorem{(環境とカウンターの名前)}{(元となるカウンターの名前)}{(表示される文字列)}
\newcommand*{\newaliastheorem}[3]{%
\newaliascnt{#1}{#2}%
\newtheorem{#1}[#1]{#3}%
\aliascntresetthe{#1}%
\expandafter\newcommand\csname #1autorefname\endcsname{#3}%
}
\newtheorem{theorem}{Theorem} % 新しく theorem カウンターが作られる
\renewcommand{\theoremautorefname}{定理}
\newaliastheorem{lemma}{theorem}{Lemma} % 補題
\newaliastheorem{prop}{theorem}{Proposition} % 命題
\newaliastheorem{cor}{theorem}{Corollary} % 系
\begin{theorem} \label{thm:very-important-theorem} % → Theorem 1
人類は滅亡する。
\end{theorem}
\begin{lemma} \label{lem:very-important-lemma} % → Lemma 2
第 $n$ 次世界大戦($n\gg 1$)が勃発することは、人類が滅亡する十分条件である。
\end{lemma}
\begin{prop} \label{prop:very-important-proposition} % → Proposition 3
人間は必ず死ぬ。
\end{prop}
\begin{cor} \label{cor:very-easy-corollary} % → Corollary 4
ソクラテスは死ぬ。
\end{cor}
使っている TeX/LaTeX のテクニック:
\newcommand*
のように*
をつけると、引数が空行(改段落)を受け付けなくなる。こうすることで、引数の閉じカッコ}
を忘れた時のエラーメッセージが明快になると期待できる。\csname
〜\endcsname
は、トークン列をコントロールシーケンスに変える。引数によってコントロールシーケンスの名前を変える際に有用である。\newcommand\csname ほにゃららautorefname\endcsname
と書くと、\newcommand
に渡されるコマンド名が\ほにゃららautorefname
ではなくて\csname
となってしまう。そこで、\expandafter
によって\csname
を先に展開させる。展開・実行の順序は次のようになる。\expandafter\newcommand\csname ほにゃららautorefname\endcsname
→\expandafter
が展開される\newcommand\csname ほにゃららautorefname\endcsname
→\csname
が展開される\newcommand\ほにゃららautorefname
→\newcommand
が実行される
【編集】6月2日:しょうもない誤字を修正。
ピンバック: autorefの欠点と代替 | 雑記帳