LaTeX教程(017)- cleverref 宏包使用全攻略

文摘   2025-01-10 22:20   浙江  

LaTeX教程(017)-文档结构(17)

2.4.2cleveref包-索引文本的智能格式化

在前面的内容中我们已经看到,基于索引中使用的计数器,为索引文本格式化提供了一些轻便的支持。cleveref包(作者Toby Cubitt)则为这一功能提供了重量级的支持。并且可以对数字引用和页码引用进行排序,适当地缩小范围。varioref包的命令\vref,\Vref, 以及\vpageref均被增强,以支持多个key和引用的格式化。所有格式化的内容都在导言区,这使得cleveref成为一个全面而强大的方案。

\cref{key-list}
\cref*{key-list}

\Cref{key-list}
\Cref*{key-list}

cleveref包提供的主要命令是\cref。它可以接收一个key,就像\ref那样。也可以接收多个key,这些key之间用逗号隔开。它将这些key对应的索引文本,根据它们自身的类型进行格式化,例如,在这些索引文本的前面添加前缀,"section","fig"等。也可能会添加一些其他的装饰,例如在公式编号的两边添加一对圆括号。

如果给定一个由多个key组成的列表,它会根据需要显示复数形式(例如一个公式显示eq.,多个公式显示eqs.),对于更长的列表,它知道适当地连接。例如,它可以区分哪些是成对的引用,哪些是多个单独的引用,哪些是一个连续的范围,并且可以处理这些组合。

根据以往的经验,读者可能已经想到\Cref的作用了。它和\cref的不同之处是,\Cref会判断生成的索引文本是否出现在句首,如果出现在句首,则首字母大写(如果索引文本是以单词开头的话)。但其实这里还有一个新的差异,那就是\cref生成的索引文本的前缀,有些会使用缩写,如"fig. xx","eq. (xx)"等等,而\Cref总是会生成完整的单词,如"figure","equation"等等。

和前面一样,它们的星号形式均有抑制hyperref链接的特性。

我们用一个例子演示一下:

\documentclass{article}
\usepackage[a5paper,margin=1.5in]{geometry}
\usepackage{amsmath}
\usepackage[colorlinks=true,linkcolor=blue]{hyperref}
\usepackage{cleveref}
\begin{document}
\section{A section}\label{sec:this}

A reference to an equation in this section looks like : ``see \cref{eq:a} in \cref{sec:this}''.

\begin{align}
   a &= b \label{eq:a}\\
   b &< c \label{eq:b}\\
   c &< d \label{eq:c}
\end{align}

\Cref{eq:c,eq:a,eq:b} above are \ldots
\end{document}

编译:

可以看到,\cref生成的公式的索引文本和标题的不同,公式的索引文本的前缀是缩写"eq.",并且用一对圆括号公式的编号围起来,而标题的索引要本的前缀是"section"。\Cref生成的公式的索引文本,前掇是"Equations",是一个完整的单词,并且由于它出现在句首,首字母大写。

留意索引代码\Cref{eq:c,eq:a,eq:b},可以看到我们是将这些key乱序输入的,但是在生成的文档中,它们仍然被正确地排序了,结果呈现了一个正确的范围,并且由于我们输入了多个key,前缀也都变成的复数形式(equations, 或eqs.)。索引的自动排序是一个很实用的特性,编写文档时,你很可能会需要重新排列某些内容,这可能会导致这些key也跟着变动。而此时如果没有自动排序的话,索引就会生成像"see figures(1),(3),and(2)"这样的文本。

我们在前面的例子中多添加两行公式,并且使用一个不同的间隔符号,就可能会出现不同的情形:

\documentclass{article}
\usepackage[a5paper,margin=1.4in]{geometry}
\usepackage{amsmath}
\usepackage[colorlinks=true,linkcolor=blue]{hyperref}
\usepackage{cleveref}
\begin{document}
\section{A section}

\begin{align}
   a &= b \label{eq:a}\\
   b &< c \label{eq:b}\\
   c &< d \label{eq:c}\\
   a &< c \label{eq:d}\\
   b &< d \label{eq:e}
\end{align}

\Cref{eq:c,eq:b,eq:a,eq:d,eq:e} are sorted and \cref{eq:c,eq:b,eq:a,eq:e} are sorted with a gap. But compare these results with referencing \cref{eq:c,,eq:b,eq:a,eq:d,eq:e}! Surprised?
\end{document}

编译:

我们知道这里公式(1)到(5)是一个连续的范围,但是最后一个\cref命令生成的内容却是"eqs.(1) to (3), (4) and (5)",这是为什么呢? 注意观察最后一个\cref命令的参数,我们在eq:c的后面放了两个逗号,正是这两个逗号,使得在排序之后的key时,逗号前面的key是前面一组的最后一个索引。也就是说,eq:c是前面那一组的最后一个引用,而eq:c后面的key在下一组。注意先排序,再分组,尽管我们将eq:aeq:b都写在了这两个逗号的后面,但是由于它们排序后在eq:c的前面,所以它们也被分到了前面的那组,即公式(1)到(3)。

你可以在\cref以及\Cref的参数中放一些不同类型的keycleveref会选将索引分类,再在同类中排序。当然,前提是这些不同类型的索引是相容的,否则你可能会得到一些奇怪的范围结构。我们将前一个例子稍作改动:

\documentclass{article}
\usepackage[a5paper,margin=1.4in]{geometry}
\usepackage{amsmath}
\usepackage[colorlinks=true,linkcolor=blue]{hyperref}
\usepackage{cleveref}
\begin{document}
\section{A section}\label{sec:one}

\begin{align}
   a &= b \label{eq:a}\\
   b &< c \label{eq:b}\\
   c &< d \label{eq:c}\\
   a &< c \label{eq:d}\\
   b &< d \label{eq:e}
\end{align}

\Cref{eq:c,,eq:b,eq:a,eq:d,eq:e,sec:one,sec:two}

\section{A section too}\label{sec:two}
\end{document}

编译:

cleveref默认带有排序和范围精简的功能,排序是指将乱序的key生成顺序的索引,而范围精简功能是指将多个连续的索引缩写为一个范围,例如在前面的例子中,它将公式(1),公式(2)...公式(5)缩写成了eqs.(1) to (5)。通常默认的这些功能正是我们需要的,但如果你有特殊的需求,也可以通过指定包选项来修改它。在调用cleveref时,如果指定sort选项,将只有排序功能,而没有范围精简功能,如果指定compress选项,则只有范围精简功能,而不排序,如果指定nosort选项,则两个功能都没有,指定sort&compress选项,则两个功能都有(也即是默认情形)。我们知道使用\Cref会使出现在句首的索引前缀单词首字大写,而如果我们指定了capitalise选项,那么每一个索引前缀单词的首字母都将大写,且不论使用的是\Cref还是\cref。我们将前面的例子稍作更改(加两个包选项):

\documentclass{article}
\usepackage[a5paper,margin=1.4in]{geometry}
\usepackage{amsmath}
\usepackage[colorlinks=true,linkcolor=blue]{hyperref}
\usepackage[sort,capitalize]{cleveref}%加两个包选项
\begin{document}
\section{A section}\label{sec:one}

\begin{align}
   a &= b \label{eq:a}\\
   b &< c \label{eq:b}\\
   c &< d \label{eq:c}\\
   a &< c \label{eq:d}\\
   b &< d \label{eq:e}
\end{align}

\cref{eq:c,,eq:b,eq:a,eq:d,eq:e,sec:one,sec:two}

\section{A section too}\label{sec:two}
\end{document}

编译:

可以看到,索引被排序了,但是没有缩写成范围,并且所有的索引文本的前缀都是首字母大写的。

cleveref还支持很多语言选择,如italiangerman等(没有中文)。有需要的读者可以翻阅包文档,自行探索。

还有一个实用的选项,noabbrev,它会禁用缩写,而将所有前缀变成完整的单词,如此一来,使用\cref也总会生成完整的前掇。

最后,如果你同时使用了cleveref包和hyperref包,那么索引就会生成超链接(除非你使用的是星号形式的索引命令)。默认情况下,超链接文本,也就是前面的例子中那些蓝色的、你点了可以跳转的文本,仅限于那些编号,并且不包括其他的材料(观察上面的例子)。但如果你指定了nameinlink,就可以扩大超链接文本的范围。我们将前面的例子稍作修改:

\usepackage[nameinlink,noabbrev]{cleveref}
%只改这行即可,其他的不变

编译:

可以看到,超链接文本扩大到了括号以及前缀上。

在有些特殊情形下,你可能只想要一个索引生成的文本,而不想要索引值(通常是那些编号),此时我们就可以使用以下这些命令:

\namecref{key}
\namecrefs{key}
\nameCref{key}
\nameCrefs{key}
\lcnamecref{key}
\lcnamecrefs{key}

我使演示一下:

\documentclass{article}
\usepackage[a5paper,margin=1.4in]{geometry}
\usepackage{amsmath}
\usepackage[colorlinks=true,linkcolor=blue]{hyperref}
\usepackage{cleveref}
\begin{document}
\section{A section}\label{sec:one}

\begin{align}
   a &= b \label{eq:a}\\
   b &< c \label{eq:b}\\
   c &< d \label{eq:c}\\
   a &< c \label{eq:d}\\
   b &< d \label{eq:e}
\end{align}

\section{A section too}\label{sec:two}

some text ...

\namecref{eq:a}

\namecrefs{eq:a}

\namecref{sec:one}

\namecrefs{sec:two}

\nameCref{eq:c}

\nameCrefs{eq:d}

\lcnamecref{eq:e}

\lcnamecrefs{sec:one}

\end{document}

编译:

观察这些输出,可以很容易看出,\namecref{key}得到的文本就是\cref{key}生成的文本去掉索引值(通常是那些编号),而后面有个"s"的命令,如\namecrefs{key},则会得到\namecref{key}的复数形式。前四个命令都是这种规律,\nameCref{key}得到的通常是首字母可以大写的、完整的前缀,而\nameCrefs{key}到得的则是前者的复数形式。需要注意的是最后两个命令,\lcname...的形式的命令得到的总是小写的文本,哪怕你指定了capitalize选项也不行。

要注意是的,这六个命令不支持key列表,每个命令的参数中只能放置一个key

还有一些命令,只保留索引值,不生成其他文本。如\labelcref{key-list}\labelcpageref{key-list}。它们分别保留索引的编号和页码。并且默认都保留了自动排序功能和范围精简功能。但是要注意,尽管它们都支持key列表,但是不支持不同类型的key。因为没有了能够区分索引类型的前缀等文本,因此禁止将不同类型的key混在一起。

我们用一个例子演示:

\documentclass{article}
\usepackage[a5paper,margin=1.4in]{geometry}
\usepackage{amsmath}
\usepackage[colorlinks=true,linkcolor=blue]{hyperref}
\usepackage{cleveref}
\begin{document}
\section{A section}\label{sec:one}

\begin{align}
   a &= b \label{eq:a}\\
   b &< c \label{eq:b}\\
   c &< d \label{eq:c}\\
   a &< c \label{eq:d}\\
   b &< d \label{eq:e}
\end{align}

\labelcref{eq:c,,eq:b,eq:a,eq:d,eq:e}

\labelcpageref{sec:one,sec:two}

\section{A section too}\label{sec:two}

\end{document}

编译:

除了使用一串连续的key来生成一个范围之外,还可以使用两个key确定一个范围,可以使用如下命令实现这一点:

\crefrange{keyfirst}{keylast}
\crefrange*{keyfirst}{keylast}
\Crefrange{keyfirst}{keylast}
\Crefrange*{keyfirst}{keylast}

它其实是将两个索引用"to"连起来,因此使用它的时候,要确保keyfirstkeylast不是相连的,否则就会出现如下情形:

\documentclass{article}
\usepackage[a5paper,margin=1.4in]{geometry}
\usepackage{amsmath}
\usepackage[colorlinks=true,linkcolor=blue]{hyperref}
\usepackage{cleveref}
\begin{document}
\section{A section}\label{sec:one}

\begin{align}
   a &= b \label{eq:a}\\
   b &< c \label{eq:b}\\
   c &< d \label{eq:c}\\
   a &< c \label{eq:d}\\
   b &< d \label{eq:e}
\end{align}

\section{A section too}\label{sec:two}

\Crefrange{eq:a}{eq:e}

\crefrange{sec:one}{sec:two}

\end{document}

编译:

结果中是"sections 1 to 2"并不是我们想要的,在只有两个对象时,我们用"and"连接,此时更建议使用\cref

cleveref也提供了一套用来索引页码的命令:

\cpageref{key-list}
\Cpageref{key-list}
\cpagerefrange{keyfirst}{keylast}
\Cpagerefrange{keyfirst}{keylast}

根据以往的经验,我们基本上可以看出这几个命令的作用了。最基本的命令是\cpageref{key-list},它和\cref一样,支持key列表,并且一个命令的参数中可以输入不同类型的key。它默认有自动排序和范围精简功能。而\Cpageref\cpageref不同的是,它生成的前缀如果出现在句首,首字母会大写,并且总是使用完整单词。\cpagerefrange\Cpagerefrange,与我们前面讲过的\crefrange\Crefrange命令的使用方式相同,唯一不同的只是\cpagerefrange索引的是页码。对这四个命令,我们不再一一演示。

如果varioref包和cleveref一起使用,那么varioref包命令的一些功能就会发生改变,这可能是因为cleveref重定义了某些varioref的命令,以支持key列表,而不是单个key。我们将这些命令列一下:

\vref*{key-list}
\Vref*{key-list}
\vrefrange*{keyfirst}{keylast}
\vpageref*{key-list}
\vpagerefrange*{keyfirst}{keylast}

并且要注意的是,如果这两个包一起使用了,这些命令就不支持可选参数了。例如,如果使用

\vrefrange*[same page]{keyfirst}{keylast}

就会报错。

为了支持索引文本的首字母的大写,cleveref还定义了\Vrefrange\Vpageref以及\Vpagerefrange等命令,而这些是varioref包里没有的。

我们用一个例子演示一下:

\documentclass{article}
\usepackage[a5paper,margin=1.5in]{geometry}
\usepackage{kantlipsum}
\usepackage[colorlinks=true,linkcolor=blue]{hyperref}
\usepackage[nospace]{varioref}
\usepackage[noabbrev]{cleveref}
\begin{document}
\renewcommand\theequation{\thesection.\arabic{equation}}

\section{Test}

Observe \vrefrange{A}{C} and in particular \vref{B,C}.

\begin{equation}
a=b\label{A}
\end{equation}
Here is a second equation that appears
on the next page \ldots

\kant[1]

\begin{equation}
b<c\label{B}
\end{equation}
\ldots and finally one more equation:
\begin{equation}
a<c\label{C}
\end{equation}
\end{document}

出于篇幅考虑,这里不将编译结果帖出来了,请读者自行编译一下。


LaTeX工作室
精致科研生活从 LaTeX 开始! 模版定制 | 培训 | 排版 | 答疑 加VX:t314159265
 最新文章