Как сделать обратную ссылку на плавающую среду, такую как списки или цифры, туда, где они упоминаются?
Я действительно хочу поместить некоторые записи исходного кода и некоторые рисунки / изображения в свое приложение, для получения более подробной информации см. Этот вопрос ), и поэтому мне было бы очень полезно иметь там обратную ссылку (точно так же, как вы можете иметь в библиографии или аббревиатуре TOC с acro
или около того), потому что та часть, где на нее есть ссылка, находится очень далеко от того места, где она напечатана (то есть в приложении).
Короче говоря, этот вопрос в основном предполагает «противоположность» вопроса «Хранить таблицы / рисунки близко к тому месту, где они упоминаются» , то есть мои изображения / списки находятся далеко от того места, где они упомянуты, и поэтому я хотел бы получить обратную ссылку на них , чтобы люди могли найти объяснение цитируемого мной фрагмента кода или изображения, просто взглянув на приложение.
Я использовал hyperref
команды для ссылки на рисунок или листинг, созданный с помощью minted, например \autoref
, \nameref
или \fullref.
Таким образом, возможно ли каким-то образом добавить обратную ссылку (обратную ссылку / обратную ссылку) к подписи - или, имея в виду другую мою идею, использовать заголовки вместо подписей где-то еще в тексте?
Я, например, хочу такую подпись:
Фрагмент исходного кода, показывающий, как A создает B. (упоминается на страницах 5, 7-8.)
Точный стиль, т. Е. Является ли он компактным и пропускает страницы или какое вступление оно использует («упомянуто на страницах» также можно просто заменить на «pp.» Или другое сокращение, которое, вероятно, уже определено в каком-то макросе biblatex или acro), поэтому, не имеет значения, но мне, например, нравится стиль acro
использования.)
Изменить: поскольку это все еще не кажется ясным, я хочу что-то вроде acro:

Мне нужны эти "S. 10, 14, 27" и т.д. обратные ссылки на страницу. Ответ от @John Kormylo дает хороший пример, но не полный. Но я не хочу их аббревиатуры или список ссылок (biblatex также может сделать это, я знаю , что), но для некоторых фигур / списков / подписи в приложении .
Кстати, достаточно, если он ссылается на страницу , это не обязательно должна быть точная позиция.
Я не могу дать MWE, потому что здесь он не работает.
Примечание. По очевидным причинам обратная ссылка, возможно, должна исключать ссылку в оглавлении, например \listoflistings
или \listoffigures
.
Ответы
Вот кое-что, что в некоторой степени основано на 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}

Альтернатива, основанная на этикетках с работающим счетчиком. Вывод обратной ссылки будет только обратной ссылкой на одну метку обратной ссылки на страницу и метку, но это можно изменить, если хотите (это может выглядеть странно, поскольку вы получите что-то вроде «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}
Если вы хотите распечатать все случаи обратных ссылок, этот код можно немного упростить: нужно будет только запомнить список счетчиков экземпляров обратных ссылок для каждой метки, а не список страниц для каждой метки.
\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}
Это решение использует \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}
Хорошо, благодаря ответу @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 {...} помечает только один элемент.
Это происходит потому, что я неоднократно упоминал эту цифру. В конце концов, вывод просто использует последнюю метку как ссылку.
Так что это еще не все, но я думаю, нам нужно будет использовать счетчики или около того, чтобы подсчитать метки для полного решения? Не так ли? (Если у вас есть идеи, пожалуйста, отправьте их и используйте их в качестве основы.)