是否有可能创建一个等同于方程式的反向引用用于定理、命题定义等?
这意味着在陈述定理之后,将会陈述引用该定理的位置,并且它将与 hyperref 一起工作。
标题中显示的表格/图形的使用几乎提供了一个答案,但如何将其附加到标记定理/定义的末尾以自动发生?
我需要自动发生的情况的示例,除了 \Cref
\documentclass{article}
\usepackage{etoolbox,xstring,xspace}
\usepackage{amsmath,amsthm,amssymb,thmtools}
\usepackage{hyperref}
\usepackage{cleveref}
\theoremstyle{plain}
\newtheorem{theorem}{Theorem}
\makeatletter
\AtBeginDocument{%
\let\origref\ref
\renewcommand*\ref[1]{%
\origref{#1}\xlabel{#1}}
}
\newrobustcmd*\xlabel[1]{%
\ifcsdef{siteref@doc@#1}{}{\csgdef{siteref@doc@#1}{,}}%
\@bsphack%
\begingroup
\csxdef{siteref@doc@#1}{\csuse{siteref@doc@#1},\thepage}%
\protected@write\@auxout{}%
{\string\SiteRef{siteref@#1}{\csuse{siteref@doc@#1}}}%
\endgroup
\@esphack%
}
\newrobustcmd*\SiteRef[2]{\csgdef{#1}{#2}}
\newrobustcmd*\xref[1]{%
\ifcsundef{siteref@#1}{%
\@latex@warning@no@line{Label `#1' not defined}
}{%
\begingroup
\StrGobbleLeft{\csuse{siteref@#1}}{2}[\@tempa]\relax%
\def\@tempb{}%
\@tempcnta=0\relax%
\@tempcntb=\@ne\relax%
\def\do##1{\advance\@tempcnta\@ne}%
\expandafter\docsvlist\expandafter{\@tempa}%
\def\do##1{%
\ifnum\@tempcntb=\@tempcnta\relax%
\hyperpage{##1}%
\else
\hyperpage{##1},%
\fi%
\advance\@tempcntb\@ne
}%
[\expandafter\docsvlist\expandafter{\@tempa}]\xspace%
\endgroup
}%
}
\makeatother
\begin{document}
\begin{theorem}\label{fancytheorem}
Fancy Theorem
\end{theorem}
Referenced on page(s)\xref{fancytheorem}
\newpage\section{page two}\ref{fancytheorem}
\end{document}
谢谢!
答案1
这是实现您想要的功能的一种方法。我从您的代码开始,添加和更改了一些内容。一个不太简短的摘要:
- 我将
siteref@
其重新命名thmref@
,因为这对我来说更有意义:) - 我将定理环境包装在一个
\NewDocumentEnvironment
名为中Theorem
,它接受两个参数:环境的可选参数theorem
和一个(强制)标签。标签用于定义一个thmref@<label>
宏,该宏用于存储包含定理引用的页码。在环境结束时,将调用Theorem
该\xref
命令以自动添加交叉引用信息。 - 我不再每次调用
\SiteRef
时都向 auxfile 写入命令,而是只使用 写入一次。\ref
\AtEndDocument
\SaveTheoremRef
- 我已经让
\ref
etc 变得足够智能,只保存与定理相关的参考文献的“thmref”信息。以前,无论何时\ref
使用,这些信息都会存储在 aux 文件中。 - 该代码适用于
\ref
和\cref
。我没有添加,\Cref
但这很容易做到。 - 我不得不更改
\xref
命令,因为它不适用于多个引用的情况。我还让它只打印每页的一个页面引用,并根据包含定理引用的页数使用page
或。pages
- 若无参考文献,
No references
则打印。
编辑
我已经更改了 的定义,\@theoremref
以便现在允许在定理之前出现引用。代价是thmref@<label>
现在为所有引用(而不仅仅是定理)构建引用,但它们仅存储在定理的辅助文件中。同时,当有多个引用时,我在最后两个页面引用之间添加了一个“and”,这有点棘手,并且我通过将嵌入式环境放入theorem
它们自己的组中来修复原始版本代码中的一个错误。我删除了不必要的包并重命名\xref
为\AddTheoremReferences
以避免名称冲突,因为我认为这\xref
可能在某个包中定义(?)。最后,根据评论中的要求,我允许将多个标签传递给\ref{...}
和朋友。
以下是包含这些更改的我的 MWE 第一页的输出:
代码如下:
\documentclass{article}
\usepackage{etoolbox}
\usepackage{amsmath,amsthm,amssymb,thmtools}
\usepackage{hyperref}
\usepackage{cleveref}
\theoremstyle{plain}
\newtheorem{theorem}{Theorem}
\makeatletter
% This command is written to the aux file by \SaveTheoremRef, hence
% allowing us to access the cross-referencing data via \thmref@aux@<label>
\newrobustcmd*\TheoremRef[2]{\csgdef{thmref@aux@#1}{#2}}
% save theorem reference data. Called via \AtEndDocument{...}
\newrobustcmd*\SaveTheoremRef[1]{
\ifcsdef{thmref@#1}{%
\immediate\write\@auxout{\string\TheoremRef{#1}{\csuse{thmref@#1}}}%
}{}
}
% stores page reference data in thmref@<label>
\newcommand\@theoremref[1]{%
\def\do##1{\ifcsdef{thmref@##1}{\csxappto{thmref@##1}{,\number\thepage}}%
{\csxdef{thmref@##1}{\number\thepage}}%
}%
\docsvlist{#1}%
}
% Overwrite definitions of \ref and \cref. Since other packages such as
% hyperref and cleverref change these this should be done at the
% beginning of the document.
\AtBeginDocument{
\let\originalref\ref
\renewcommand*\ref[1]{\originalref{#1}\@theoremref{#1}}
\let\originalcref\cref
\renewcommand*\cref[1]{\originalcref{#1}\@theoremref{#1}}
}
% \AddTheoremReferences<label> prints the cross-referencing information for theorem <label>
\newrobustcmd*\AddTheoremReferences[1]{%
\ifcsdef{thmref@aux@#1}{% proceed only if thmref data exists
\def\@tempa{0}% used to check for repeats
\@tempcnta=0% used to check for plural
\def\@thmref{}% will contain cross-referencing hyperlinks
\def\do##1{\ifnum##1=\@tempa\relax% skip over repeat references on each page
\else%
\ifnum\@tempcnta=1% skip \@tempcnta=0
\xappto\@thmref{\noexpand\hyperpage{\@tempa}}% first page reference
\else\ifnum\@tempcnta>1% already have ref so add a comma
\xappto\@thmref{, \noexpand\hyperpage{\@tempa}}%
\fi%
\fi%
\global\advance\@tempcnta by 1% increment reference counter
\edef\@tempa{##1}% store to check for repeat next time
\fi%
}
\xdef\@@thmref{\csuse{thmref@aux@#1}}
\expandafter\docsvlist\expandafter{\@@thmref}
\typeout{Refefenced: \the\@tempcnta.}
\ifnum\@tempcnta=1% only one reference
\noindent[Referenced on page \expandafter\hyperpage{\@tempa}]%
\else% at least two references so add an "and"
\noindent[Referenced on pages \@thmref\space and \expandafter\hyperpage{\@tempa}]%
\fi%
}{\noindent[Not referenced]\@latex@warning@no@line{Theorem reference `#1' is not defined}}%
}
\makeatother
\usepackage{xparse}
% \begin{Theorem}[heading]{label} ... \end{Theorem}
\NewDocumentEnvironment{Theorem}{ o m }
{\AtEndDocument{\SaveTheoremRef{#2}}
\IfNoValueTF{#1}{\begin{theorem}}{\begin{theorem}[#1]}
\label{#2}
}
{\end{theorem}\AddTheoremReferences{#2}}
\setcounter{page}{11}% for testing purposes only
\begin{document}
A reference to \cref{fanciertheorem}.
\begin{Theorem}{fancytheorem}
Fancy Theorem
\end{Theorem}
\begin{Theorem}[Really fancy!]{fanciertheorem}
Fancier Theorem
\end{Theorem}
\begin{Theorem}[Plain theorem]{plaintheorem}
Plain Theorem
\end{Theorem}
\newpage\section{page two}
\cref{fancytheorem,fanciertheorem}
\ref{fanciertheorem}
\newpage\section{page three}
\ref{fanciertheorem}
\end{document}