问题
我正在写一个文档,其中我的所有方程式都用名称而不是数字来标记,我提供了数学的\tag
命令。我还使用聪明人以便于交叉引用。我今天才决定添加超链接.虽然这并没有破坏任何东西老的(至少在我弄清楚把它放在哪里之后),它并没有完全起作用:方程式的链接跳转不正确。这是为什么?我该如何修复它?
编辑:扩展问题。这不仅仅与方程有关,还与全部数学环境。我利用equation
、align
、align*
、alignat
、align*
和gather
以及这些全部需要支持适当的链接。不幸的是,我刚刚意识到这一点,这份文件的截止日期迫在眉睫,这是我自己的错;但解决方案对我来说非常重要,所以我增加了悬赏。(这个问题的其余部分只是指显示的 MWE.tex;然而,问题更为普遍。)
一个例子
在以下文档中,所有三个\eqref
链接都跳转到第一个等式:
\documentclass{book}
\usepackage{amsmath}
\usepackage{hyperref}
\usepackage{cleveref}
\begin{document}
\begin{equation}\label{eq:first}\tag{first}
\text{First equation}
\end{equation}
\begin{equation}\label{eq:second}\tag{second}
\text{Second equation}
\end{equation}
\begin{equation}\label{eq:third}\tag{third}
\text{Third equation}
\end{equation}
\begin{itemize}
\item A reference to~\eqref{eq:first}.
\item A reference to~\eqref{eq:second}.
\item A reference to~\eqref{eq:third}.
\end{itemize}
\newpage
For scrolling purposes.
\end{document}
如果我任何一个消除\usepackage{cleveref}
或者删除\tag
s 后,一切正常。但如果将 s 和 s 放在一起,则一切都会跳转到第一个等式。
编译消息
带有\usepackage{cleveref}
和\tag
当我编译此示例(在MWE.tex
)时,我在日志中收到以下警告消息:
[1{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}pdfTeX warning (ext4): des
tination with the same identifier (name{equation.0.0.1}) has been already used,
duplicate ignored
\AtBegShi@Output ...ipout \box \AtBeginShipoutBox
\fi \fi
l.27 \newpage
pdfTeX warning (ext4): destination with the same identifier (name{
equation.0.0.1}) has been already used, duplicate ignored
\AtBegShi@Output ...ipout \box \AtBeginShipoutBox
\fi \fi
l.27 \newpage
] [2] (./MWE.aux) )
果然,如果我查看MWE.aux
,它包含以下几行:
\newlabel{eq:first}{{{first}}{1}{\relax }{equation.0.0.1}{}}
\newlabel{eq:first@cref}{{[equation][2147483647][]{first}}{1}}
\newlabel{eq:second}{{{second}}{1}{\relax }{equation.0.0.1}{}}
\newlabel{eq:second@cref}{{[equation][2147483647][]{second}}{1}}
\newlabel{eq:third}{{{third}}{1}{\relax }{equation.0.0.1}{}}
\newlabel{eq:third@cref}{{[equation][2147483647][]{third}}{1}}
仅使用\tag
s(无\usepackage{cleveref}
)
如果我编译没有cleveref,然后我收到同样的警告:
[1{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}pdfTeX warning (ext4): des
tination with the same identifier (name{equation.0.0.1}) has been already used,
duplicate ignored
\AtBegShi@Output ...ipout \box \AtBeginShipoutBox
\fi \fi
l.27 \newpage
pdfTeX warning (ext4): destination with the same identifier (name{
equation.0.0.1}) has been already used, duplicate ignored
\AtBegShi@Output ...ipout \box \AtBeginShipoutBox
\fi \fi
l.27 \newpage
] [2] (./MWE.aux) )
但是,链接正常工作,并且辅助文件包含
\newlabel{eq:first}{{{first}}{1}{\relax }{AMS.1}{}}
\newlabel{eq:second}{{{second}}{1}{\relax }{AMS.2}{}}
\newlabel{eq:third}{{{third}}{1}{\relax }{AMS.3}{}}
只用\usepackage{cleveref}
s(无\tag
s)
如果我不使用\tag
s 进行编译,则不会收到任何警告,链接有效,并且我的 aux 文件包含
\newlabel{eq:first}{{1}{1}{\relax }{equation.0.0.1}{}}
\newlabel{eq:first@cref}{{[equation][1][0]1}{1}}
\newlabel{eq:second}{{2}{1}{\relax }{equation.0.0.2}{}}
\newlabel{eq:second@cref}{{[equation][2][0]2}{1}}
\newlabel{eq:third}{{3}{1}{\relax }{equation.0.0.3}{}}
\newlabel{eq:third@cref}{{[equation][3][0]3}{1}}
什么也没有(既不是\usepackage{cleveref}
也不\tag
是)
如果我不使用\usepackage{cleveref}
或\tag
s 进行编译,则不会收到任何警告,链接有效,并且我的辅助文件包含
\newlabel{eq:first}{{1}{1}{\relax }{equation.0.0.1}{}}
\newlabel{eq:second}{{2}{1}{\relax }{equation.0.0.2}{}}
\newlabel{eq:third}{{3}{1}{\relax }{equation.0.0.3}{}}
没有\usepackage{hyperref}
,但有其他一切
如果我删除`\usepackage{hyperref},那么我不会收到任何警告,也没有链接,而且我的辅助文件包含
\newlabel{eq:first}{{{first}}{1}}
\newlabel{eq:first@cref}{{[equation][2147483647][]{first}}{1}}
\newlabel{eq:second}{{{second}}{1}}
\newlabel{eq:second@cref}{{[equation][2147483647][]{second}}{1}}
\newlabel{eq:third}{{{third}}{1}}
\newlabel{eq:third@cref}{{[equation][2147483647][]{third}}{1}}
替换equation
为gather
hyperref README 报告称equation
环境“支持得不太好”,并建议用环境替换它gather
。这样做可以成功消除错误消息,但不能修复链接的行为;它们仍然会跳转到错误的位置。辅助文件包含
\newlabel{eq:first}{{{first}}{1}{\relax }{Doc-Start}{}}
\newlabel{eq:first@cref}{{[equation][2147483647][]{first}}{1}}
\newlabel{eq:second}{{{second}}{1}{\relax }{Doc-Start}{}}
\newlabel{eq:second@cref}{{[equation][2147483647][]{second}}{1}}
\newlabel{eq:third}{{{third}}{1}{\relax }{Doc-Start}{}}
\newlabel{eq:third@cref}{{[equation][2147483647][]{third}}{1}}
发生了什么?
诚然,这是我的问题的一部分,但在我看来,它就像 hyperref 并且\tag
不能很好地协同工作:如果我同时使用两者,我会收到有关重复的错误消息。但除非 cleveref 也存在,否则它似乎不会在文档中引起任何问题。
我还应该补充几点警告:
这是一份 85 页的文档。我现在真的不想更换任何软件包,但如果可行的话……
我在学校的机器上编译此文档,因此我无法控制主要的 TeX 安装。不过,我已经在本地 texmf 树中安装了一些更新版本。以下是我的日志文件中的所有软件包版本:
- amstext 2000/06/29 v2.01
- amsbsy 1999/11/29 v1.2d
- amsopn 1999/12/14 v2.01
- hyperref 2011/04/09 v6.82f
- ltxcmds 2011/11/09 v1.22
- ifpdf 2011/01/30 v2.3
- pdftexcmds 2011/11/29 v0.20
- infwarerr 2010/04/08 v1.3
- ifluatex 2010/03/01 v1.3
- 密钥值 1999/03/16 v1.13
- kvsetkeys 2012/04/25 v1.16
- etexcmds 2011/02/16 v1.5
- pdfescape 2011/11/25 v1.13
- ifvtex 2010/03/01 v1.5
- ifxetex 2009/01/23 v0.5
- hycolor 2011/01/30 v1.7
- xcolor 补丁 2011/01/30
- hopatch 2011/06/24 v1.1
- letltxmacro 2010/09/02 v1.4
- kvoptions 2011/06/30 v3.11
- intcalc 2007/09/27 v1.1
- 网址 2006/04/12 版本 3.3
- bitset 2011/01/30 v1.1
- bigintcalc 2012/04/08 v1.3
- atbegshi 2011/10/05 v1.16
- atveryend 2011/06/30 v1.8
- 重新运行文件检查 2011/04/15
- uniquecounter 2011/01/30 v1.2
- cleveref 2012/03/07{} v0.18.5{}
- nameref 2010/04/30 v2.40
- 引用计数 2011/10/16 v3.4
答案1
我有一个解决方案。然而,这可能不是最优雅的方法。
您必须为 hyperref 定义自己的编号方案,以便每个编号都是唯一的:
\listfiles
\documentclass{book}
\usepackage{amsmath}
\usepackage{hyperref}
\usepackage{cleveref}
%%% define a new counter and use it for \theHequation which hyperref uses for the links
\newcounter{Hequation}
\renewcommand{\theHequation}{\thechapter.\arabic{Hequation}}
\makeatletter
\g@addto@macro\equation{\stepcounter{Hequation}}
\makeatother
\begin{document}
\begin{equation}\tag{first}\label{eq:first}
\text{First equation}
\end{equation}
\begin{equation}\tag{second}\label{eq:second}
\text{Second equation}
\end{equation}
\begin{equation}\label{eq:firstreal}
\text{First equation without tag}
\end{equation}
\begin{equation}\tag{third}\label{eq:third}
\text{Third equation}
\end{equation}
\begin{equation}\label{eq:secondreal}
\text{Second equation without tag}
\end{equation}
\begin{itemize}
\item A reference to~\eqref{eq:first}.
\item A reference to~\eqref{eq:second}.
\item A reference to~\eqref{eq:third}.
\item A reference to~\eqref{eq:firstreal}.
\item A reference to~\eqref{eq:secondreal}.
\end{itemize}
\newpage
For scrolling purposes.
\end{document}
如您所见,\equation
也必须重新定义。然后带有和不带有的方程式\tag
就可以毫无问题地混合在一起。
马丁
答案2
正确使用\tag
withhyperref
和 的方法amsmath
是使用未编号的带星号的数学环境。然后,它们不会增加方程计数器,这会根据新的计数器值隐式定义一个锚点,而只会\tag
再次减少计数器(它对已经定义的锚点无能为力,但如果有必要,可以使用选项hypertexnames=false
来hyperref
部分缓解这种情况)。
hyperref
即使有上述情况,cleveref
和之间也存在不兼容问题amsmath
。正如 Martin 所指出的,问题在于cleveref
直接实现amsmath
宏并对其进行更改,从而忽略了hyperref
的工作。一种选择是进一步修补 提供的宏,amsmath
以整合hyperref
的增强功能和cleveref
的附加功能,我已在以下方面进行了此操作:
\documentclass{article}
\usepackage{amsmath}
\usepackage{hyperref}
\usepackage{cleveref}
\makeatletter
\def\make@df@tag@@#1{%
\gdef\df@tag{%
\maketag@@@{\Hy@make@anchor#1}%
\def\@currentlabel{#1}%
\def\cref@currentlabel{[equation][2147483647][]#1}%
}%
}
\def\make@df@tag@@@#1{%
\gdef\df@tag{%
\tagform@{\Hy@make@anchor#1}%
\toks@\@xp{\p@equation{#1}}%
\edef\@currentlabel{\the\toks@}%
\edef\cref@currentlabel{[equation][2147483647][]\the\toks@}
}%
}
\makeatother
\begin{document}
\begin{equation*}\label{eq:first}\tag{first}
\text{First equation}
\end{equation*}
\begin{equation*}\label{eq:second}\tag{second}
\text{Second equation}
\end{equation*}
\begin{equation*}\label{eq:third}\tag{third}
\text{Third equation}
\end{equation*}
\begin{equation}\label{eq:fourth}
\text{Fourth equation}
\end{equation}
\begin{itemize}
\item A reference to~\eqref{eq:first}.
\item A reference to~\eqref{eq:second}.
\item A reference to~\eqref{eq:third}.
\item A reference to~\eqref{eq:fourth}.
\end{itemize}
\newpage
For scrolling purposes.
\end{document}
答案3
作为参考,这个问题似乎已经在最近的版本中得到修复cleveref
(至少从 0.18.10 开始;CTAN 中还没有,但可以从我的网站)。其他答案中的重新定义不再是必要的。我还没有确切地追踪哪个版本cleveref
修复了这个错误。
答案4
由于我必须为文档的最终版本找到解决方案,因此我找到了以下解决方案;它在日志文件中产生了很多错误,但它们似乎与最终文档中的错误不符。不过,我仍然对正确的方法™ 感到好奇。
\makeatletter
\newif\if@plaintag
\@plaintagfalse
\let\plaintagform@\tagform@
\newcommand{\plaintag}[1]{\begingroup\let\tagform@\plaintagform@\tag{#1}\endgroup}
\def\tagform@#1{\if@plaintag\else\refstepcounter{equation}\fi%
\maketag@@@{[\textsc{\ignorespaces #1}]}}
\newcommand{\ptag}[1]{\@plaintagtrue\tag{#1}\@plaintagfalse}
\makeatother
由于我无论如何都要重新定义\tagform@
(在方括号中渲染\maketag@@@
小写字母),我强制它包含\refstep{equation}
(模数if
语句,用于\tag
ged 但未标记的方程式)。我还将所有\tag
s 放在 s 之前\label
(我不确定这是否有必要,但这样做没有坏处)。结果,尽管有很多关于重复标签的警告,但一切似乎都正常工作;步进方程式计数器使链接目标正确。