amsmath 和 pdfcomment 之间的冲突

amsmath 和 pdfcomment 之间的冲突

我在一个文档中同时使用了amsmathpdfcomment。这导致由产生的引用(\ref{})看起来像(zref@1)而不是像的数字(1)。如果没有amsmath或,则pdfcomment不会出现此问题。

一个最小(不)工作示例:

\documentclass{article}
\usepackage{amsmath}
\usepackage{hyperref} 
\usepackage{pdfcomment}

\begin{document}

\begin{equation}
\label{eq:1}
E = m \pdftooltip{c}{speed of light}^2
\end{equation}

See eq. (\ref{eq:1}). % <- this produces (zref@1) instead of (1)

\end{document}

用 编译它pdflatex

欢迎任何建议。

答案1

问题其实与 无关pdfcomment,只不过人们更可能\pdftooltip在方程式中使用 而不是命令\section。但如果你愚蠢地尝试:

\begin{equation}
\label{eq:1}
x^2 + y^2 = z^2
\section{Pythagoras}
\end{equation}

然后(假设它确实编译了,但我对此表示怀疑)你会发现完全相同的问题。

这是因为,当amsmath处理方程环境(包括方程环境equation本身)时(因为它重新定义了方程环境​​),它会对方程进行一些复杂的操作,这需要多次处理(我相信这也会导致 beamer 和 tikz 出现问题)。这样做的后果之一是,如果您\label在方程环境中输入命令,则标签不会立即保存,而是至少处理一次方程,然后标签才会保存到文件.aux。这大概是为了处理诸如align整个方程内容的多个部分可以被标记之类的事情(我猜是这样)。

现在,\label命令通过使用 的值来确定要保存哪些信息\@currentlabel。这是一项巧妙的工作,它确保了\section{Introduction}\label{sec:intro}Just Works(TM) 之类的功能。但这确实意味着您需要确保在计数器递增和命令\label处理之间\@currentlabel不会重新定义 。

这就是魔法与之相反的地方。如果方程式中有一个命令,它以重新定义amsmath的方式增加计数器,那么它就是\@currentlabel保存的是公式标签而不是公式标签。我举的愚蠢例子\section就是这样一个命令,但它不太可能出现在公式环境中。另一个是\pdftooltip,正如我们所见,这更有可能出现。

为了验证我说的是否正确,我们可以模拟以下\section命令:

\documentclass{article}
\usepackage{amsmath}

\renewcommand{\thesection}{\alph{section}}

\begin{document}

\section{Introduction}
\label{sec:intro}

\begin{equation}
\label{eq:1}
E = m c^2
\refstepcounter{section}
\end{equation}

See eq.\ \ref{eq:1} in Section~\ref{sec:intro}.

\end{document}

得出的结果为:

参见第 a 节中的等式 b。

如果我们注释掉这一\refstepcounter行,我们会得到:

参见第 a 节中的公式 1。

作为另一个实验,我们可以amsmath使用以下代码来消除这个问题:

\documentclass{article}
\usepackage{pdfcomment}

\renewcommand{\thesection}{\alph{section}}

\begin{document}

\section{Introduction}
\label{sec:intro}

\pdftooltip{hello}{world}

\label{sec:introb}

Sections~\ref{sec:intro} and~\ref{sec:introb} are the same.

\end{document}

在这种情况下,答案很简单:确保在\label之前发出\pdftooltip。但对于这种amsmath情况,事情并不那么简单,因为一切都是内部的。

查看源代码,pdfcomment我可以看到\pdftooltip使用\refstepcounter哪个是重置的魔法命令\@currentlabel。我猜它只需要在内部使用它,之后不需要设置\@currentlabel任何特定内容。所以最好的解决方案是修补,以便它在调用时pdfcomment保存当前值,然后再次恢复它。\@currentlabel

但是,我不建议您自己修补软件包。因此,您应该联系软件包的维护者并请他这样做。与此同时,有一种方法可以解决这个问题。这只是为了确保在\@currentlabel等式末尾正确的值有效。所以我们需要调用\refstepcounter但不实际增加计数器。这是一个执行此操作的简单宏:

\makeatletter
\def\refsetcounter#1{%
    \protected@edef\@currentlabel
       {\csname p@#1\endcsname\csname the#1\endcsname}%
}
\makeatother

将其称为\refsetcounter{equation}。它必须放在结尾方程环境(或至少在之后\pdftooltip)。

现在,如果能自动完成这项工作就好了。这将涉及修补命令amsmath。通常,我也会对此保持警惕,但我对这个amsmath软件包比对那个软件包更有把握pdfcomment,所以我准备试一试!

我的实验表明,实际上只有equation命令存在此问题。不知何故,诸如aligngather和 之类的东西multline都可以正常工作。所以我们只需要确保我们的新命令在环境\refsetcounter{equation}结束时运行equation。以下是代码:

\makeatletter
\def\refsetcounter#1{%
    \protected@edef\@currentlabel
       {\csname p@#1\endcsname\csname the#1\endcsname}%
}
\let\orig@endequation=\endequation
\def\endequation{%
  \refsetcounter{equation}%
  \orig@endequation}
\makeatother

有了序言中的这段内容,您的代码将生成:

参见公式(1)。

正如它应该。

相关内容