让反向引用更美观

让反向引用更美观

问题LaTeX 中的反向引用被标记为重复,所以我无法在该主题中发帖。尽管如此,我发现 Ryan Reich 在那里提供的代码是一个很好的学习练习。他的解决方案提供了一个逗号分隔的反向引用列表,没有空格。

我只是认为,如果可以修改他的方法,使其不仅生成一串以逗号分隔的数字,而且还生成可以在文档中使用的实际可读文本,那么他的方法将更加有用。

所以我尝试改进他的解决方案

答案1

cleveref-usedon包允许轻松地使用cleveref的格式进行反向引用(例如,“定理 1”、“第 II 节”)。

要使用它,我需要安装它,因为它不是我的 LaTeX 安装的一部分。

编辑:截至 2023 年 8 月,存在一个错误,cleverf-usedon导致某些反向引用不出现。请参阅这个问题在 GitHub 上。

答案2

因此,这里有一个解决方案:

\documentclass{article}
\usepackage{etoolbox}
\usepackage{stringstrings}

\makeatletter

\def\@newbackl@bel#1#2#3{%
 \@ifundefined{#1@#2}%
  {\global\@namedef{#1@#2}{#3}}
  {\cs@g@appendpair{#1@#2}{#3}}%
}
% #1 and #2 are each of the form {a}{b}, and the a and b groups are to be
% concatenated independently.
\def\cs@g@appendpair#1#2{{%
 \edef\first{\csname #1\endcsname}%
 \edef\firsta{\expandafter\@firstoftwo\first}%
 \convertword[q]{\firsta}{and}{}%
 \edef\firsta{\thestring}%
 \edef\firstb{\expandafter\@secondoftwo\first}%
 \convertword[q]{\firstb}{and}{}%
 \edef\firstb{\thestring}%
 \csxdef{#1}%
  {{\firsta, and \@firstoftwo#2}%
   {\firstb, and \@secondoftwo#2}}%
}}

% Patching into the existing commands
\def\newbacklabel{\@newbackl@bel B}
\let\backlabel=\label
\patchcmd\backlabel{\newlabel}{\newbacklabel}{}{}
\let\backref=\ref
\patchcmd\backref{r@#1}{B@#1}{}{}
\let\pagebackref=\pageref
\patchcmd\pagebackref{r@#1}{B@#1}{}{}
\pretocmd\ref{\backlabel{#1}}{}{}

\makeatother

\begin{document}
\begin{enumerate}
 \item \label{e:1} Part 1, referenced by part(s) \backref{e:1}
    on page(s) \pagebackref{e:1}.
 \item \label{e:x} Part 2, referenced by part(s) \backref{e:x} on
page(s) \pagebackref{e:x}, and referencing part \ref{e:1}.
 \item \label{e:2} Part 3, referencing part \ref{e:1} and \ref{e:x}
 \item \label{e:3} Part 4, referencing part \ref{e:1}.
\end{enumerate}
\newpage
\section{A section}
\label{s:1}
Here is another reference to part \ref{e:1}.

\end{document}

在此处输入图片描述

对于那些对 stringstrings 包的缓慢感到沮丧的人来说,这里有一个更长但更快的替代方案

\documentclass{article}
\usepackage{etoolbox}
\usepackage{stringstrings}

\makeatletter

\def\@newbackl@bel#1#2#3{%
 \@ifundefined{#1@#2}%
  {\global\@namedef{#1@#2}{#3}}
  {\cs@g@appendpair{#1@#2}{#3}}%
}
% #1 and #2 are each of the form {a}{b}, and the a and b groups are to be
% concatenated independently.
\def\cs@g@appendpair#1#2{{%
 \edef\first{\csname #1\endcsname}%
 \edef\firsta{\expandafter\@firstoftwo\first}%
 \replacewordF[q]{\firsta}{and}{}%
 \edef\firsta{\thestring}%
 \edef\firstb{\expandafter\@secondoftwo\first}%
 \replacewordF[q]{\firstb}{and}{}%
 \edef\firstb{\thestring}%
 \csxdef{#1}%
  {{\firsta, and \@firstoftwo#2}%
   {\firstb, and \@secondoftwo#2}}%
}}

% Patching into the existing commands
\def\newbacklabel{\@newbackl@bel B}
\let\backlabel=\label
\patchcmd\backlabel{\newlabel}{\newbacklabel}{}{}
\let\backref=\ref
\patchcmd\backref{r@#1}{B@#1}{}{}
\let\pagebackref=\pageref
\patchcmd\pagebackref{r@#1}{B@#1}{}{}
\pretocmd\ref{\backlabel{#1}}{}{}

\usepackage{ifnextok}
\usepackage{ifthen}

\def\string@end{$}
\def\converttilde{T}
\newcounter{arg@index}
\let\SaveHardspace~

\def\getargsF#1{%
  \if T\converttilde\def~{ }\fi%
  \protected@edef\the@string{#1}%
  \def\argi{}\setcounter{arg@index}{1}%
  \expandafter\parse@Block\the@string\string@end%
  \let~\SaveHardspace%
}

%ifthenelse needed when leading spaces end up as \argi
\def\parse@Block{\IfNextToken\string@end%
  {\edef\narg{\arabic{arg@index}}\@gobble}%
  {\IfNextToken\@sptoken{\addtocounter{arg@index}{1}%
   \ifthenelse{\equal{\argi}{}}{\addtocounter{arg@index}{-1}}{}%
   \expandafter\def\csname arg\roman{arg@index}\endcsname{}%
   \add@to{\parse@Block}}%
  {\add@to{\parse@Block}}}}

  \def\add@to#1#2{\if\@sptoken#2\else\expandafter\protected@edef%
                 \csname arg\roman{arg@index}\endcsname%
                {\csname arg\roman{arg@index}\endcsname#2}\fi#1}

\newcounter{word@count}

% Replaces a word of alphanumeric phrase with another
% Syntax: \replacewordF[mode]{orig_string}{word}{replacement}
% mode is v for verbose, q for quiet (saved in \thestring}
% word is one whole word; cannot contain spaces.
% replacement can be multiword
\newcommand\replacewordF[4][v]{%
  \getargsF{#2}%
  \edef\thestring{\argi}%
  \setcounter{word@count}{1}%
  \whiledo{\value{word@count} < \narg}{%
    \addtocounter{word@count}{1}%
    \ifthenelse{\equal{\csname arg\roman{word@count}\endcsname}{#3}}%
    {\edef\the@string{\thestring\@sptoken}\edef\thestring{\the@string#4}}%
    {\edef\the@string{\thestring\@sptoken}%
       \edef\thestring{\the@string\csname arg\roman{word@count}\endcsname}}%
  }%
  \if v#1\thestring\fi%
}

\makeatother

\begin{document}
\begin{enumerate}
 \item \label{e:1} Part 1, referenced by part(s) \backref{e:1}
    on page(s) \pagebackref{e:1}.
 \item \label{e:x} Part 2, referenced by part(s) \backref{e:x} on
page(s) \pagebackref{e:x}, and referencing part \ref{e:1}.
 \item \label{e:2} Part 3, referencing part \ref{e:1} and \ref{e:x}
 \item \label{e:3} Part 4, referencing part \ref{e:1}.
\end{enumerate}

\newpage
\section{A section}
\label{s:1}
Here is another reference to part \ref{e:1}.

\end{document}

相关内容