如何将浮动环境(如列表或图形)反向引用到提到它们的地方?

如何将浮动环境(如列表或图形)反向引用到提到它们的地方?

我确实想在附录中放一些源代码条目和一些图表/图像有关详细信息,请参阅此问题),因此我发现在那里有一个反向链接非常有用(就像你可以在参考书目或首字母缩略词目录中有的acro那样),因为引用的部分离打印的位置很远(即在附录中)。

简而言之,这个问题基本上假设了问题的“相反”“将表格/图表放在靠近提及的地方”,即我的图像/列表距离提及它们的位置很远,因此我希望为它们提供一个反向引用,这样人们只需查看附录就可以找到我引用的代码片段或图像的解释。

我使用了hyperref命令来引用通过 minted 创建的图形或列表,例如\autoref\nameref\fullref

因此,是否有可能以某种方式向标题添加反向引用(backref/backlink)- 或者记住我的另一个想法,使用标题代替说明文本中的其他地方?

例如,我想要这样的标题:

源代码片段展示了 A 如何生成 B。(第 5、7-8 页提到)

确切的风格,即它是否紧凑并跳过页面或它使用什么介绍(“页面上提到”也可以用“pp”或可能已经在某些 biblatex 或 acro 宏中定义的其他缩写代替)所以,并不重要,但我例如喜欢这种风格acro。)

编辑:由于它似乎仍然不清楚,我想要类似 acro 的东西:

我希望这些“S. 10, 14, 27”等反向链接到该页面。@John Kormylo 的回答提供了一个很好的例子,但并不完整。但我确实不是希望它们成为首字母缩略词或参考列表(我知道 biblatex 也可以做到这一点),但对于一些附录中的图表/清单/标题

顺便说一下足够的如果它反向链接到,不必是精确的位置。

我无法提供 MWE,因为它在这里不起作用。

笔记:出于显而易见的原因,backref 可能应该排除目录中的链接,如\listoflistings\listoffigures

答案1

这是一些大致基于biblatexbackref 方法的内容。

每次调用\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}

图 1:这是一个测试。(见第 1、2 页)


基于标签的替代方案,带有运行计数器。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{...} 是否只标记一个项目。

发生这种情况是因为我确实多次引用了该图。最终,输出仅使用最后一个标签作为参考。

所以它还没有完全完成,但我想我们需要使用计数器之类的东西来计算标签的数量,才能得到完整的解决方案?不是吗?(​​如果您有任何想法,请随时提交并以此作为您的基础。)

相关内容