\autorefの欠点と代替

hyperrefパッケージの\autorefの欠点と、\autorefを使わない代替方法を挙げてみる。

\refと\autoref

まずは \autoref を使わずに文書を書いてみる。

\documentclass{ltjsbook}
\usepackage{amsthm}
\usepackage[unicode]{hyperref}

\theoremstyle{definition}
\newtheorem{theorem}{定理}[chapter]
\newtheorem{lemma}[theorem]{補題}

\title{すごい文章}
\author{だめぽ}

\begin{document}
\maketitle

\chapter{すごい内容}
\label{chap:main}

にゃーん。にゃにゃ?にゃーお。
\begin{lemma}[すごい補題] \label{lem:bar}
    みゃおーん。
\end{lemma}

\begin{theorem}[すごい定理] \label{thm:foo}
    何がにゃーんですか。にゃおーん。
\end{theorem}

\chapter{あとがき}

第\ref{chap:main}章の定理\ref{thm:foo}は……すごい!
補題\ref{lem:bar}も、すごい!(手動)

\end{document}

この文書では章や定理の番号を \ref を使って参照している。生成されるPDFは次のような感じで、 \ref の部分がハイパーリンクになる(hyperrefパッケージの効能)。

この書き方には次の問題がある:

  • ハイパーリンクになるのが番号の部分だけであり、幅次第ではクリックしづらい。

この問題を解決するために、hyperrefパッケージは \autoref というコマンドを提供している。これを使うと、先ほどの文書は次のように書き直せる:

...

\theoremstyle{definition}
\newtheorem{theorem}{定理}[chapter]
\newtheorem{lemma}[theorem]{補題}
\renewcommand{\chapterautorefname}{第}
\renewcommand{\theoremautorefname}{定理}
\newcommand{\lemmaautorefname}{補題}

...

\autoref{chap:main}章の\autoref{thm:foo}は……すごい!
\autoref{lem:bar}も、すごい!% ←残念ながらこれだけでは「補題」にならない
(autoref)

...

\autoref については以前にも記事を書いたので、そちらも参照:

「定理」などの番号の前につく部分は \〈カウンター名〉autorefname というコマンドで指定できる。これを使った出力は次のようになる:

無事、ハイパーリンク(赤枠)の部分が広くなった。

しかし、 \autoref には次の問題がある:

  1. 「第n章」というような、番号の後に文字を置くことができない。
  2. 番号の直後に和欧間空白が挿入されない。
  3. newtheoremでカウンターを流用する場合に面倒な処理が必要になる(以前の記事 \newtheorem と \autoref を参照)

問題1と問題2は \def\ナントカautorefname#1\null{...} という回避方法があるようだが、LaTeX的ではないためここでは扱わない。

この記事では、 \autoref を使わずに似たようなこと(「定理」などの部分もハイパーリンクにする)を実現してみたい。

cleverefを使う方法

cleveref は、相互参照を強化するパッケージのようだ。筆者はあまり使ったことがない。cleverefに nameinlink オプションを指定することで、参照の部分をハイパーリンクにすることができる。

詳しい使い方はググって欲しい。ここでは使用例だけ載せる。

\documentclass{ltjsbook}
\usepackage{amsthm}
\usepackage[unicode]{hyperref}
\usepackage[nameinlink]{cleveref}

\theoremstyle{definition}
\newtheorem{theorem}{定理}[chapter]
\newtheorem{lemma}[theorem]{補題}

\crefname{theorem}{定理}{定理}
\crefname{lemma}{補題}{補題}
\crefname{chapter}{第}{第}
\creflabelformat{chapter}{#2#1章#3}

...

\cref{chap:main}の\cref{thm:foo}は……すごい!
\cref{lem:bar}も、すごい!(cleveref)

ポイントは

  • パッケージオプション nameinlink を使用することで参照の部分全体をハイパーリンクにできる。
  • \crefname で「定理」のような前につく文字列を指定する。単数形と複数形を指定できる。
  • 「第n章」のように番号の後ろに文字列をつける場合は \creflabelformat\crefformat を使う。
  • newtheoremでカウンターを共用する場合に特別な処理は必要ない。
  • パッケージの読み込みと \newtheorem の順番は amsthm等 / hyperref → cleveref → \newtheorem である必要がある。

である。

prettyrefと組み合わせる方法

ぶっちゃけcleverefは高機能だしそれで十分な気がするのだが、筆者がまだcleverefを習得する前に独自に編み出した方法があるのでここで供養しておく。

prettyrefは「定理」とかの部分を補ってくれるパッケージおよびコマンドである。独特なのは、環境やカウンターの名前ではなく、ラベルのコロンより前の部分によって種類を識別する点である。

これと \hyperref を組み合わせればオレオレautorefの出来上がりである。

...

\usepackage{prettyref}
\newrefformat{thm}{定理\ref*{#1}}
\newrefformat{lem}{補題\ref*{#1}}
\newrefformat{chap}{第\ref*{#1}章}
\newcommand\myautoref[1]{\hyperref[#1]{\prettyref{#1}}}

...

\myautoref{chap:main}の\myautoref{thm:foo}は……すごい!
\myautoref{lem:bar}も、すごい!(prettyref)

出力の比較

これまでに紹介した4通りの書き方の出力を比較してみる。

autorefの代替として紹介したcleverefとオレオレautoref(prettyref使用)は、ほぼ同じ見た目である。……が、微妙に空白の入り方が違う。

どうやらこれはcleverefで \creflabelformat を使うと番号の直前に空白が挿入されるのが原因のようだ。実際、prettyrefのnewrefformatの部分を

\newrefformat{thm}{定理~\ref*{#1}}
\newrefformat{lem}{補題~\ref*{#1}}
\newrefformat{chap}{第~\ref*{#1}章}

と変えたらcleverefと同じ見た目になった。cleverefでも \crefformat を使って

\crefformat{chapter}{#2第#1章#3}

と定義すれば余計な空白は入らないようだ。


1 thought on “\autorefの欠点と代替

  1. ピンバック: newtheorem と autoref | 雑記帳

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です