我确实想在附录中放一些源代码条目和一些图表/图像有关详细信息,请参阅此问题),因此我发现在那里有一个反向链接非常有用(就像你可以在参考书目或首字母缩略词目录中有的acro
那样),因为引用的部分离打印的位置很远(即在附录中)。
简而言之,这个问题基本上假设了问题的“相反”“将表格/图表放在靠近提及的地方”,即我的图像/列表距离提及它们的位置很远,因此我希望为它们提供一个反向引用,这样人们只需查看附录就可以找到我引用的代码片段或图像的解释。
我使用了hyperref
命令来引用通过 minted 创建的图形或列表,例如\autoref
,\nameref
或\fullref
。
因此,是否有可能以某种方式向标题添加反向引用(backref/backlink)- 或者记住我的另一个想法,使用标题代替说明文本中的其他地方?
例如,我想要这样的标题:
源代码片段展示了 A 如何生成 B。(第 5、7-8 页提到)
确切的风格,即它是否紧凑并跳过页面或它使用什么介绍(“页面上提到”也可以用“pp”或可能已经在某些 biblatex 或 acro 宏中定义的其他缩写代替)所以,并不重要,但我例如喜欢这种风格acro
。)
我希望这些“S. 10, 14, 27”等反向链接到该页面。@John Kormylo 的回答提供了一个很好的例子,但并不完整。但我确实不是希望它们成为首字母缩略词或参考列表(我知道 biblatex 也可以做到这一点),但对于一些附录中的图表/清单/标题。
顺便说一下足够的如果它反向链接到页,不必是精确的位置。
我无法提供 MWE,因为它在这里不起作用。
笔记:出于显而易见的原因,backref 可能应该排除目录中的链接,如\listoflistings
或\listoffigures
。
答案1
这是一些大致基于biblatex
backref 方法的内容。
每次调用\ref
/时\autoref
,我们都会向文件发送一个标记.aux
,表示该标签在此特定页面上被引用。在每次运行 LaTeX 时,我们都可以从文件中读取标签-页面组合.aux
,并为每个标签编译一个引用该标签的页面列表。此列表随后可用于打印。
通过这种简单的方法,我们只链接回页面,而不是引用标签的确切位置,我们也不会自动发出 LaTeX 重新运行警告。
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{etoolbox}
\usepackage{hyperref}
\makeatletter
% stolen from biblatex
% we need a way to check if printable text is in a list
\newrobustcmd{\rugk@ifprintableinlist}[2]{%
\begingroup
\def\rugk@tempa{\endgroup
\@secondoftwo}%
\renewcommand*{\do}[1]{%
\ifstrequal{##1}{#1}
{\def\rugk@tempa{\endgroup
\@firstoftwo}%
\listbreak}
{}}%
\dolistloop{#2}%
\expandafter\rugk@tempa}
\newrobustcmd{\rugk@ifprintableinlistcs}[2]{%
\expandafter\rugk@ifprintableinlistcs@i\csname #2\endcsname{#1}}
\long\def\rugk@ifprintableinlistcs@i#1#2{\rugk@ifprintableinlist{#2}{#1}}
% add <page> to the list of pages where <label> was referenced
% {<label>}{<page>}{<page int>}
\protected\def\rugk@ref@backref#1#2#3{%
\ifcsundef{rugk@ref@backreflist@\detokenize{#1}}
{\global\cslet{rugk@ref@backreflist@\detokenize{#1}}\@empty}
{}%
\rugk@ifprintableinlistcs{#2}{rugk@ref@backreflist@\detokenize{#1}}
{}
{\listcsgadd{rugk@ref@backreflist@\detokenize{#1}}{#2}}}
% write label backref to aux file
% {<label>}
\def\rugk@write@ref@backref#1{%
\if@filesw
\protected@write\@mainaux{}{\string\rugk@ref@backref
{#1}{\thepage}{\noexpand\the\c@page}}%
\fi}
\newcommand{\backref}[1]{%
\rugk@write@ref@backref{#1}%
\ref{#1}%
}
\newcommand{\autobackref}[1]{%
\rugk@write@ref@backref{#1}%
\autoref{#1}%
}
\newcounter{backrefpages}
\newcounter{totalbackrefpages}
\newcommand*{\printbackrefpage}[1]{%
\stepcounter{backrefpages}%
\hyperlink{page.#1}{#1}%
\ifnumless{\value{backrefpages}}{\value{totalbackrefpages}}
{, }
{}}
\newrobustcmd*{\printlabelbackrefs}[1]{%
\setcounter{backrefpages}{0}%
\setcounter{totalbackrefpages}{0}%
\ifcsundef{rugk@ref@backreflist@\detokenize{#1}}
{Not referenced}
{\def\do##1{\stepcounter{backrefpages}}%
\dolistcsloop{rugk@ref@backreflist@\detokenize{#1}}%
\setcounter{totalbackrefpages}{\value{backrefpages}}%
\setcounter{backrefpages}{0}%
\ifnumgreater{\value{totalbackrefpages}}{1}
{pp.}
{p.}~%
\forlistcsloop{\printbackrefpage}{rugk@ref@backreflist@\detokenize{#1}}}}
\makeatother
\newrobustcmd{\backcaption}[3][]{%
\if\relax\detokenize{#1}\relax
\def\rugk@tmpcapt{\caption[#2]}%
\else
\def\rugk@tmpcapt{\caption[#1]}%
\fi
\rugk@tmpcapt{#2 (see \printlabelbackrefs{#3})}%
\label{#3}}
\begin{document}
\section{Introduction}
\listoffigures
Here is a reference to \backref{test} and \autobackref{test}
\clearpage
And here we talk about it again: \autobackref{test}
\clearpage
\begin{figure}[p]
\backcaption{This is a test.}{test}
\end{figure}
\end{document}
基于标签的替代方案,带有运行计数器。backref 输出将只反向引用每个页面和标签的一个反向引用标签,但如果您愿意,可以更改它(它可能看起来很奇怪,因为您会得到类似“pp. 1, 1”的内容)。
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{etoolbox}
\usepackage{hyperref}
\makeatletter
\newcounter{backrefinst}
% stolen from biblatex
% we need a way to check if printable text is in a list
\newrobustcmd{\rugk@ifprintableinlist}[2]{%
\begingroup
\def\rugk@tempa{\endgroup
\@secondoftwo}%
\renewcommand*{\do}[1]{%
\ifstrequal{##1}{#1}
{\def\rugk@tempa{\endgroup
\@firstoftwo}%
\listbreak}
{}}%
\dolistloop{#2}%
\expandafter\rugk@tempa}
\newrobustcmd{\rugk@ifprintableinlistcs}[2]{%
\expandafter\rugk@ifprintableinlistcs@i\csname #2\endcsname{#1}}
\long\def\rugk@ifprintableinlistcs@i#1#2{\rugk@ifprintableinlist{#2}{#1}}
% add <page> to the list of pages where <label> was referenced
% remember the first instance counter for each label/page combination
% {<label>}{<backref instance counter>}{<page>}{<page int>}
\protected\def\rugk@ref@backref#1#2#3#4{%
\ifcsundef{rugk@ref@backreflist@\detokenize{#1}}
{\global\cslet{rugk@ref@backreflist@\detokenize{#1}}\@empty}
{}%
\rugk@ifprintableinlistcs{#3}{rugk@ref@backreflist@\detokenize{#1}}
{}
{\listcsgadd{rugk@ref@backreflist@\detokenize{#1}}{#3}%
\csgdef{rugk@ref@backrefinst@\detokenize{#1}@\detokenize{#3}}{#2}}}
% write label backref to aux file
% {<label>}
\def\rugk@write@ref@backref#1{%
\if@filesw
\protected@write\@mainaux{}{\string\rugk@ref@backref
{#1}{\the\value{backrefinst}}{\thepage}{\noexpand\the\c@page}}%
\fi}
\newcommand*{\rugk@create@backref@label}[1]{%
\begingroup
\refstepcounter{backrefinst}%
\label{backref.\the\value{backrefinst}}%
\rugk@write@ref@backref{#1}%
\endgroup
}
\newcommand{\backref}[1]{%
\ref{#1}%
\rugk@create@backref@label{#1}%
}
\newcommand{\autobackref}[1]{%
\autoref{#1}%
\rugk@create@backref@label{#1}%
}
\newcounter{backrefpages}
\newcounter{totalbackrefpages}
% {<label>}{<page>}
\newcommand*{\printbackrefpage}[2]{%
\stepcounter{backrefpages}%
\pageref{backref.\csuse{rugk@ref@backrefinst@\detokenize{#1}@\detokenize{#2}}}%
\ifnumless{\value{backrefpages}}{\value{totalbackrefpages}}
{, }
{}}
\newrobustcmd*{\printlabelbackrefs}[1]{%
\setcounter{backrefpages}{0}%
\setcounter{totalbackrefpages}{0}%
\ifcsundef{rugk@ref@backreflist@\detokenize{#1}}
{Not referenced}
{\def\do##1{\stepcounter{backrefpages}}%
\dolistcsloop{rugk@ref@backreflist@\detokenize{#1}}%
\setcounter{totalbackrefpages}{\value{backrefpages}}%
\setcounter{backrefpages}{0}%
\ifnumgreater{\value{totalbackrefpages}}{1}
{pp.}
{p.}~%
\forlistcsloop{\printbackrefpage{#1}}{rugk@ref@backreflist@\detokenize{#1}}}}
\makeatother
\newrobustcmd{\backcaption}[3][]{%
\if\relax\detokenize{#1}\relax
\def\rugk@tmpcapt{\caption[#2]}%
\else
\def\rugk@tmpcapt{\caption[#1]}%
\fi
\rugk@tmpcapt{#2 (see \printlabelbackrefs{#3})}%
\label{#3}}
\begin{document}
\section{Introduction}
\listoffigures
Here is a reference to \backref{test} and \autobackref{test}
\clearpage
And here we talk about it again: \autobackref{test}
\clearpage
\begin{figure}[p]
\backcaption{This is a test.}{test}
\end{figure}
\end{document}
如果您想要打印所有 backref 场合,这段代码可以稍微简化一下:只需要记住每个标签的 backref 实例计数列表,而不是每个标签的页面列表。
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{etoolbox}
\usepackage{hyperref}
\makeatletter
\newcounter{backrefinst}
% add <page> to the list of pages where <label> was referenced
% remember the first instance counter for each label/page combination
% {<label>}{<backref instance counter>}
\protected\def\rugk@ref@backref#1#2{%
\ifcsundef{rugk@ref@backreflist@\detokenize{#1}}
{\global\cslet{rugk@ref@backreflist@\detokenize{#1}}\@empty}
{}%
\ifinlistcs{#2}{rugk@ref@backreflist@\detokenize{#1}}
{}
{\listcsgadd{rugk@ref@backreflist@\detokenize{#1}}{#2}}}
% write label backref to aux file
% {<label>}
\def\rugk@write@ref@backref#1{%
\if@filesw
\protected@write\@mainaux{}{\string\rugk@ref@backref
{#1}{\the\value{backrefinst}}}%
\fi}
\newcommand*{\rugk@create@backref@label}[1]{%
\begingroup
\refstepcounter{backrefinst}%
\label{backref.\the\value{backrefinst}}%
\rugk@write@ref@backref{#1}%
\endgroup
}
\newcommand{\backref}[1]{%
\ref{#1}%
\rugk@create@backref@label{#1}%
}
\newcommand{\autobackref}[1]{%
\autoref{#1}%
\rugk@create@backref@label{#1}%
}
\newcounter{backrefpages}
\newcounter{totalbackrefpages}
% {<label>}{<page>}
\newcommand*{\printbackrefpage}[1]{%
\stepcounter{backrefpages}%
\pageref{backref.#1}%
\ifnumless{\value{backrefpages}}{\value{totalbackrefpages}}
{, }
{}}
\newrobustcmd*{\printlabelbackrefs}[1]{%
\setcounter{backrefpages}{0}%
\setcounter{totalbackrefpages}{0}%
\ifcsundef{rugk@ref@backreflist@\detokenize{#1}}
{Not referenced}
{\def\do##1{\stepcounter{backrefpages}}%
\dolistcsloop{rugk@ref@backreflist@\detokenize{#1}}%
\setcounter{totalbackrefpages}{\value{backrefpages}}%
\setcounter{backrefpages}{0}%
\ifnumgreater{\value{totalbackrefpages}}{1}
{pp.}
{p.}~%
\forlistcsloop{\printbackrefpage}{rugk@ref@backreflist@\detokenize{#1}}}}
\makeatother
\newrobustcmd{\backcaption}[3][]{%
\if\relax\detokenize{#1}\relax
\def\rugk@tmpcapt{\caption[#2]}%
\else
\def\rugk@tmpcapt{\caption[#1]}%
\fi
\rugk@tmpcapt{#2 (see \printlabelbackrefs{#3})}%
\label{#3}}
\begin{document}
\section{Introduction}
\listoffigures
Here is a reference to \backref{test} and \autobackref{test}
\clearpage
And here we talk about it again: \autobackref{test}
\clearpage
\begin{figure}[p]
\backcaption{This is a test.}{test}
\end{figure}
\end{document}
答案2
该解决方案使用\backcaption
和\backref
而不是\caption\label
和\ref
。
\documentclass{article}
\usepackage{hyperref}
\newcommand{\backref}[1]% #1 = label name
{\raisebox{\baselineskip}[\ht\strutbox]{\hypertarget{#1.back}{}}\ref{#1}}
\newcommand{\backcaption}[2]% #1 = caption, #2= label
{\caption[#1]{\hyperlink{#2.back}{#1}}\label{#2}}
\begin{document}
\listoffigures
\vspace{2in}
Here is a reference to \backref{test}.
\begin{figure}[p]
\backcaption{This is a test.}{test}
\end{figure}
\end{document}
答案3
好的,感谢@John Kormylo我得到了一个部分解决方案,即如果我们使用通常的方法,\label
我们当然可以用它\pageref
来引用该页面。
唯一的问题是:这也只有在我们只有一个参考。
以下是一些代码:
\documentclass{article}
\usepackage[utf8]{inputenc}
\title{test-backref}
\date{August 2020}
\usepackage{hyperref}
% thanks https://tex.stackexchange.com/a/559834/98645
\newcommand{\backref}[1]% #1 = label name
{
\raisebox{\baselineskip}[\ht\strutbox]{\label{#1.back}{}}%
\ref{#1}
}
\newcommand{\autobackref}[1]% #1 = label name
{
\raisebox{\baselineskip}[\ht\strutbox]{\label{#1.back}{}}%
\autoref{#1}
}
\newcommand{\backcaption}[2]% #1 = caption, #2= label
{\caption[#1]{#1 (see p.~\pageref{#2.back})}\label{#2}}
\newcommand{\backcaptionoptional}[3]% #1 optional label, 2 = caption, #3= label
{\caption[#1]{#2 (see p.~\pageref{#3.back})}\label{#3}}
\begin{document}
\maketitle
\section{Introduction}
\listoffigures
\vspace{2in}
Here is a reference to \backref{test} and \autobackref{test}….
\newpage
And here we talk about it again: \autobackref{test}
\newpage
\begin{figure}[p]
\backcaption{This is a test.}{test}
\end{figure}
\end{document}
请注意,它也演示了这个问题。LaTeX(理所当然地)抱怨:
您多次使用了同一个标签。请检查每个 \label{...} 是否只标记一个项目。
发生这种情况是因为我确实多次引用了该图。最终,输出仅使用最后一个标签作为参考。
所以它还没有完全完成,但我想我们需要使用计数器之类的东西来计算标签的数量,才能得到完整的解决方案?不是吗?(如果您有任何想法,请随时提交并以此作为您的基础。)