参考范围中的交叉引用

参考范围中的交叉引用

我只是 LaTeX 的初学者,我在 Ref Range 中遇到了一个问题,

\documentclass{article}
\usepackage{amsmath,amsfonts,amssymb,cleveref}
\begin{document}
\ref{eq1a,eq1b,eq1c,eq1d,eq1e}
\begin{subequations}
  \begin{align}
    1+1=2\label{eq1a}\\
    1-1=0\label{eq1b}\\
    23+23=46\label{eq1c}\\
    d+e=f\label{eq1d}\\
    e+f=g\label{eq1e}
  \end{align}
\end{subequations}
\ref{eq1a,eq1b,eq1c,eq1d,eq1e}
\cref{eq1a,eq1b,eq1c,eq1d,eq1e}
\end{document}

我的问题是我想显示重新排列,1a-e如果我使用\cref,但我得到一个类似的输出,1a-1e但是否有可能隐藏重新排列中的 1(1a-e)

我查看了 cleveref 样式文件(对此一无所知:)),我发现了替换(1a-1e)的命令(cleverref.sty 行号:1022)

            \textup{(#3#1#4)}--\textup{(#5#2#6)}}}{}}{}%

在上面提到的 cleverref.sty 编码中,我需要删除数字并保留 #2 中的“e”,请指导我解决这个问题,提前谢谢

答案1

您无需破解任何内部结构即可完成此操作cleveref。这些命令的优点\cref<x>format在于您实际上是在定义 LaTeX 宏的主体,而不仅仅是要填充占位符的模式。这允许您在排版之前对标签文本进行任意复杂的操作。

为了生成形式(1a-e)为 而不是 的方程范围引用(1a)-(1e),您可以借助(新的)\crefstripprefix实用宏(见下文)重新定义方程范围标签格式,如下所示:

\crefrangelabelformat{equation}{(#3#1#4--#5\crefstripprefix{#1}{#2}#6)}

\crefstripprefix宏接受两个参数,并输出第二个参数,其中删除了公共前缀(如果有)。以下是实现(可能需要稍微整理一下):

\newcommand\crefstripprefix[2]{%
  \begingroup%
    \edef\@toksa{#1}%
    \edef\@toksb{#2}%
    \def\@accum{}%
    \@crefstripprefix%
    \@result%
  \endgroup}

\def\@crefstripprefix{%
  \let\@iterate\relax%
  \def\accum@flag{0}%
  \let\@tempc\@tempb%
  \cref@poptok{\@toksa}{\@tempa}%
  \cref@poptok{\@toksb}{\@tempb}%
  \ifx\@tempa\@tempb\relax%
    \def\@iterate{\@crefstripprefix}%
    \ifx\@accum\@empty\relax%
      \let\@accum\@tempb%
    \else%
      \ifcat\@tempb\@tempc\relax%
        \ifcat\@tempb a\relax%
          \def\accum@flag{1}%
        \else%
          \expandafter\chardef\expandafter\@tempa%
            \expandafter=\expandafter`\@tempb\relax%
          \ifnum\@tempa>`/\relax%
            \expandafter\ifnum\@tempb<`:\relax%
              \def\accum@flag{1}%
            \fi%
          \fi%
        \fi%
      \fi%
      \def\@tempa{1}%
      \ifx\accum@flag\@tempa%
        \edef\@accum{\@accum\@tempb}%
      \else%
        \let\@accum\@empty%
      \fi%
    \fi%
  \else%
    \ifcat\@tempb\@tempc\relax\else%
      \let\@accum\@empty%
    \fi%
    \edef\@result{\@accum\@tempb\@toksb}%
  \fi%
  \@iterate}

\def\cref@poptok#1#2{%
  \expandafter\expandafter\expandafter\def%
    \expandafter\expandafter\expandafter#2%
    \expandafter\expandafter\expandafter{%
      \expandafter\@cref@firsttok#1\@nil}%
  \expandafter\expandafter\expandafter\def%
    \expandafter\expandafter\expandafter#1%
    \expandafter\expandafter\expandafter{%
      \expandafter\@cref@poptok#1\@nil}}
\def\@cref@firsttok#1#2\@nil{#1}
\def\@cref@poptok#1#2\@nil{#2}

这个crefstripprefix实用宏似乎通常可用于生成更复杂的标签格式,因此我可能会将类似的内容cleveref与此示例用法一起添加到下一个版本中。

以下是一些评论:

  1. 上述解决方案的格式\crefrange{eq1}{eq32}eqs.~(1--32),与 Qrrbrbirlbel 的解决方案略有不同。这是经过深思熟虑的选择。\crefrange应该是一个愚蠢的后备命令,它只是将您传递给它的任何标签转储为适当的范围格式。我更喜欢保持\crefrange简单和愚蠢,避免太多的聪明才智。如果您想要聪明的参考范围,请将所有引用传递给\cref并让它为您整理它们。(这需要更多工作,但它更安全,因为无论您如何重新排列文档中的文本,交叉引用都是正确的。)

  2. 比较格式化标签文本并删除任何常见前缀在我看来是“正确”的做法。一种可能的替代方法是比较值c@<counter>和重置列表,并从中推断出适当的格式(cleveref 无论如何都会跟踪此信息)。这种方法的问题(除了更复杂之外)是标准 LaTeX 允许使用p@<counter>,并且基本上没有办法弄清楚交叉引用的标签计数器部分是如何格式化的,与对它所做的其他任何事情(例如添加章节/部分/小节编号)分开。这迫使人们猜测适当的格式并希望它不会改变(如 Qrrbrbirlbel 的解决方案)。最后,它是格式化页面上的标签文本决定了是否可以安全地隐藏通用前缀。因此,最好比较最终格式化的文本,而不是计数器。

  3. 上述代码抑制了全部方程,而不仅仅是子方程。例如,如果您的方程编号包括章节编号,并且 eq1、eq2 和 eq3 都在第 1.2 节中,则将\cref{eq1,eq2,eq3}产生eqs.~(1.2.1--3)。这可能是也可能不是您想要的。如果您只想对子方程执行此操作,您可以應該能够简单地重新定义subequation范围格式,而不是一个equation……但由于 amsmath 子方程实现的变化,没有单独的subequation类型cleveref!它不存在的主要原因是到目前为止没有明显的需求。添加新的子方程类型需要对cleverefamsmath 支持进行一些轻微的黑客攻击(无论如何,它必须支持子方程作为特殊情况)。如果我crefstripprefix在下一个版本中添加宏和示例,我可能会subequation同时添加一种新类型。

  4. 我想象一个非常相似的解决方案应该与包生成的子图引用一起工作subfig,这是人们偶尔会问到的问题。



借用 Qrrbrbirlbel 的示例文档,这里有一个 MWE:

\documentclass{article}

\usepackage{amsmath}
\usepackage[colorlinks]{hyperref}
\usepackage{cleveref}


\makeatletter
\newcommand\crefstripprefix[2]{%
  \begingroup%
    \edef\@toksa{#1}%
    \edef\@toksb{#2}%
    \def\@accum{}%
    \@crefstripprefix%
    \@result%
  \endgroup}

\def\@crefstripprefix{%
  \let\@iterate\relax%
  \def\accum@flag{0}%
  \let\@tempc\@tempb%
  \cref@poptok{\@toksa}{\@tempa}%
  \cref@poptok{\@toksb}{\@tempb}%
  \ifx\@tempa\@tempb\relax%
    \def\@iterate{\@crefstripprefix}%
    \ifx\@accum\@empty\relax%
      \let\@accum\@tempb%
    \else%
      \ifcat\@tempb\@tempc\relax%
        \ifcat\@tempb a\relax%
          \def\accum@flag{1}%
        \else%
          \expandafter\chardef\expandafter\@tempa%
            \expandafter=\expandafter`\@tempb\relax%
          \ifnum\@tempa>`/\relax%
            \expandafter\ifnum\@tempb<`:\relax%
              \def\accum@flag{1}%
            \fi%
          \fi%
        \fi%
      \fi%
      \def\@tempa{1}%
      \ifx\accum@flag\@tempa%
        \edef\@accum{\@accum\@tempb}%
      \else%
        \let\@accum\@empty%
      \fi%
    \fi%
  \else%
    \ifcat\@tempb\@tempc\relax\else%
      \let\@accum\@empty%
    \fi%
    \edef\@result{\@accum\@tempb\@toksb}%
  \fi%
  \@iterate}

\def\cref@poptok#1#2{%
  \expandafter\expandafter\expandafter\def%
    \expandafter\expandafter\expandafter#2%
    \expandafter\expandafter\expandafter{%
      \expandafter\@cref@firsttok#1\@nil}%
  \expandafter\expandafter\expandafter\def%
    \expandafter\expandafter\expandafter#1%
    \expandafter\expandafter\expandafter{%
      \expandafter\@cref@poptok#1\@nil}}
\def\@cref@firsttok#1#2\@nil{#1}
\def\@cref@poptok#1#2\@nil{#2}
\makeatother


\crefrangelabelformat{equation}{(#3#1#4--#5\crefstripprefix{#1}{#2}#6)}


\numberwithin{equation}{subsection}
\def\ra{\hfill(\texttt{range})}% only for this example
\textwidth=.6\textwidth        % only for this example

\begin{document}


\section{A section}
\subsection{A subsection}

\Cref{eq1a,eq1b,eq1c,eq1d,eq1e,eq2a,eq2b,eq2c,eq2d,eq2e,eq3a,eq3b,eq3c,eq3d,eq3e}\\
\Cref{eq1,eq2,eq3}\\
\Cref{eq1,eq2}\\
\Cref{eq1,eq3}\\
\Crefrange{eq1a}{eq3d} \ra
\begin{subequations}\label{eq1}
  \begin{align}
    1+1=2    \label{eq1a} \\
    1-1=0    \label{eq1b} \\
    23+23=46 \label{eq1c} \\
    d+e=f    \label{eq1d} \\
    e+f=g    \label{eq1e}
  \end{align}
\end{subequations}

\noindent
\Cref{eq1a,eq1b,eq1c,eq1d,eq1e} \\ 
\Crefrange{eq1a}{eq1e} \ra
\begin{subequations}\label{eq2}
  \begin{align}
    1+1=2    \label{eq2a} \\
    1-1=0    \label{eq2b} \\
    23+23=46 \label{eq2c} \tag{*} \\
    d+e=f    \label{eq2d} \\
    e+f=g    \label{eq2e}
  \end{align}
\end{subequations}

\noindent
\Cref{eq2a,eq2b,eq2c,eq2d,eq2e} \\
\Crefrange{eq2a}{eq2e} \ra
\begin{subequations}\label{eq3}
  \begin{align}
    1+1=2    \label{eq3a} \\
    1-1=0    \label{eq3b} \\
    23+23=46 \label{eq3c} \\
    d+e=f    \label{eq3d} \\
    e+f=g    \label{eq3e} \tag{**}
  \end{align}
\end{subequations}

\noindent
\Cref{eq3a,eq3b,eq3c,eq3d,eq3e}\\
\Crefrange{eq3a}{eq3d} \ra
\end{document}



以下是相应的排版输出:

排版示例文档

答案2

该解决方案通过重新定义来实现\@@setcrefrange

为了找到hyperref解决方案,这将需要额外的工作。

而且子方程的编号方案(实际上是计数器equation)没有与标签一起保存(方程的方案(实际上是计数器parentequation)也没有)。

问题是,不是ab等等 与标签 一起存储,但是12等等。
在 中\[C|c]refrangeformat#2指的是5,在您的情况下。使用,这会从\@alph转换回。没有简单的方法可以单独存储 (或从 中提取)干净的 。e1ee1e

虽然希望您不要每页都更改子公式样式,但这样做应该可以。(无论如何,您应该在整个文档中保持一致,不是吗?)

代码

\documentclass[varwidth]{standalone}
\usepackage{amsmath,amsfonts,amssymb,cleveref}
\makeatletter
\Crefrangeformat{equation@special}{\Cref@equation@name@plural~(#1--\@alph{#2})}
\crefrangeformat{equation@special}{\cref@equation@name@plural~(#1--\@alph{#2})}
\crefrangemultiformat{equation@special}
  {\cref@equation@name@plural~(#1--\@alph{#2})}{\crefpairgroupconjunction (#1--\@alph{#2})}
  {\crefmiddlegroupconjunction(#1--\@alph{#2})}{\creflastgroupconjunction (#1--\@alph{#2})}
\Crefrangemultiformat{equation@special}
  {\Cref@equation@name@plural~(#1--\@alph{#2})}{\crefpairgroupconjunction (#1--\@alph{#2})}
  {\crefmiddlegroupconjunction(#1--\@alph{#2})}{\creflastgroupconjunction (#1--\@alph{#2})}
\begingroup
  \edef\x{\endgroup
    \noexpand\def\noexpand\cref@insert@special##1\string @##2\string @##3\noexpand\@nil}
  \x{\csname#1@#2@special@#3\endcsname}
\def\@@setcrefrange#1#2#3{%
  \cref@getlabel{#2}{\@labela}%
  \cref@getlabel{#3}{\@labelb}%
  \cref@getprefix{#2}\@prefixa
  \cref@getprefix{#3}\@prefixb
  \ifx\@prefixa\@prefixb
    \ifx\@prefix\@empty
      #1{\@labela}{\@labelb}{}{}{}{}%
    \else
      \cref@getcounter{#3}\@counterb
      \expandafter\expandafter\expandafter\cref@insert@special\expandafter\@gobble\string
        #1\@nil{\@labela}{\@counterb}{}{}{}{}%
    \fi
  \else
    #1{\@labela}{\@labelb}{}{}{}{}%
  \fi}
\makeatother
\def\ra{\hfill(\texttt{range})}% only for this example
\textwidth=.6\textwidth        % only for this example
\begin{document}

\Cref{eq1a,eq1b,eq1c,eq1d,eq1e,eq2a,eq2b,eq2c,eq2d,eq2e,eq3a,eq3b,eq3c,eq3d,eq3e}\par
\Crefrange{eq1a}{eq3e} \ra\par
\cref{eq1a,eq1b,eq1c,eq1d,eq1e,eq2a,eq2b,eq2c,eq2d,eq2e,eq3a,eq3b,eq3c,eq3d,eq3e}\par
\crefrange{eq1a}{eq3e} \ra
\begin{subequations}
  \begin{align}
    1+1=2    \label{eq1a} \\
    1-1=0    \label{eq1b} \\
    23+23=46 \label{eq1c} \\
    d+e=f    \label{eq1d} \\
    e+f=g    \label{eq1e}
  \end{align}
\end{subequations}

\Cref{eq1a,eq1b,eq1c,eq1d,eq1e} \par \Crefrange{eq1a}{eq1e} \ra\par
\cref{eq1a,eq1b,eq1c,eq1d,eq1e} \par \crefrange{eq1a}{eq1e} \ra

\begin{subequations}
  \begin{align}
    1+1=2    \label{eq2a} \\
    1-1=0    \label{eq2b} \\
    23+23=46 \label{eq2c} \tag{*} \\
    d+e=f    \label{eq2d} \\
    e+f=g    \label{eq2e}
  \end{align}
\end{subequations}

\Cref{eq2a,eq2b,eq2c,eq2d,eq2e} \par \Crefrange{eq2a}{eq2e} \ra\par
\cref{eq2a,eq2b,eq2c,eq2d,eq2e} \par \crefrange{eq2a}{eq2e} \ra

\begin{subequations}
  \begin{align}
    1+1=2    \label{eq3a} \\
    1-1=0    \label{eq3b} \\
    23+23=46 \label{eq3c} \\
    d+e=f    \label{eq3d} \\
    e+f=g    \label{eq3e} \tag{**}
  \end{align}
\end{subequations}

\Cref{eq3a,eq3b,eq3c,eq3d,eq3e}\par \Crefrange{eq3a}{eq3e} \ra\par
\cref{eq3a,eq3b,eq3c,eq3d,eq3e}\par \crefrange{eq3a}{eq3e} \ra
\end{document}

输出

在此处输入图片描述

相关内容