cleveref
\cpageref
当收到三个或更多跨越多个页面的标签时,似乎会出现问题。发生这种情况时,会\cpageref
打印第一个和最后一个标签(参数),而不是它应该打印的页面,并且不会发出任何警告。
这个问题早在两年前就出现在这个网站上(见\cpageref 结果不正确,其中包含跨页面范围的多个(3+)引用和使用 cleveref 进行多重引用: \cpageref 压缩是否存在错误,或者我使用方式是否错误?,但都没有得到任何答案)。此外,这个问题也已报告给上游,但至今尚未得到处理(该问题仍影响“版本 0.21.5(预发布版本)”,可从https://www.dr-qubit.org/cleveref.html)。
鉴于此,我也受到了这个问题的影响,并尝试了自己的想法。思考我理解这个问题,并有解决办法。但是,我的 TeX-fu 相当有限(说句客气话),所以我对此不确定。所以,我的问题是向更有经验的用户寻求确认。
以下 MWE 可以重现此问题本身:
\documentclass{article}
\usepackage{cleveref}
\begin{document}
See \cref{tab1,tab2,tab3,tab4} on \cpageref{tab1,tab2,tab3,tab4}.
\clearpage{}
\begin{table}
\caption{Table 1}
\label{tab1}
\begin{tabular}{cc}
1 & 2 \\
3 & 4 \\
\end{tabular}
\end{table}
\begin{table}
\caption{Table 2}
\label{tab2}
\begin{tabular}{cc}
1 & 2 \\
3 & 4 \\
\end{tabular}
\end{table}
\clearpage{}
\begin{table}
\caption{Table 3}
\label{tab3}
\begin{tabular}{cc}
1 & 2 \\
3 & 4 \\
\end{tabular}
\end{table}
\begin{table}
\caption{Table 4}
\label{tab4}
\begin{tabular}{cc}
1 & 2 \\
3 & 4 \\
\end{tabular}
\end{table}
\end{document}
编译时没有错误或警告,并产生:
现在,我认为问题出在哪里。在 的定义中\@cref
,在某一点,cleveref
执行以下操作:
\ifnum\count@consecutive=1\relax%
\edef\@tempa{{\@beginref}{\@pos}}%
\csname @set\cref@variant\expandafter\endcsname\@tempa%
\else%
\edef\@tempa{{\@beginref}{\@endref}{\@pos}}%
\csname @set\cref@variant range\expandafter\endcsname\@tempa%
\fi%
(我这里使用的是当前的 TeXLive,我的cleveref.sty
有日期2018/03/27
和版本0.21.4
,这发生在第 1021 行到 1027 行)。
此时\@cref
正在循环遍历一个连续标签子组。\cref@variant
是面向用户的宏的名称cleveref
,它作为的第一个参数接收\@cref
(例如cref
,,,等)。因此,这是调用一组名称为或的Cref
宏。cpageref
\@set<variant>
\@set<variant>range
我们确实发现其中大部分在以下位置有明确定义cleveref.sty
:\@setcref
,\@setCref
以及\@setlabelcref
第 1044-1046 行;\@setcrefrange
,\@setCrefrange
以及\@setlabelcrefrange
第 1072-1074 行;\@setcpageref
,\@setCpageref
以及\@setlabelcpageref
第 1087-1089 行(还有其他的)。
但是,我找不到\@setcpagerefrange
、\@setCpagerefrange
和\@setlabelcpagerefrange
,我认为这就是缺失的。此外,尽管所有相关问题均未提及\Cpageref
和\labelcpageref
,但这一观察表明它们会以与 相同的方式失败\cpageref
。事实上,它们确实会失败。
在上面的 MWE 中提供它们如下:
\makeatletter
\newcommand*{\@setcpagerefrange}[3]{%
\@@setcpagerefrange{#1}{#2}{cref}{#3}}
\newcommand*{\@setCpagerefrange}[3]{%
\@@setcpagerefrange{#1}{#2}{Cref}{#3}}
\newcommand*{\@setlabelcpagerefrange}[3]{%
\@@setcpagerefrange{#1}{#2}{labelcref}{#3}}
\makeatother
(请注意,中的参数顺序\@@setcpagerefrange
与其兄弟不同)。
现在将给出我们预期的结果:
那么,这个诊断和修复正确吗?
答案1
好吧,为了不让这个问题悬而未决,据我所知,问题确实是 OP 中诊断出来的。已尝试联系维护人员并提出建议的修复方案。
\documentclass{article}
\usepackage{cleveref}
\makeatletter
\newcommand*{\@setcpagerefrange}[3]{%
\@@setcpagerefrange{#1}{#2}{cref}{#3}}
\newcommand*{\@setCpagerefrange}[3]{%
\@@setcpagerefrange{#1}{#2}{Cref}{#3}}
\newcommand*{\@setlabelcpagerefrange}[3]{%
\@@setcpagerefrange{#1}{#2}{labelcref}{#3}}
\makeatother
\begin{document}
See \cref{tab1,tab2,tab3,tab4} on \cpageref{tab1,tab2,tab3,tab4}.
\clearpage{}
\begin{table}
\caption{Table 1}
\label{tab1}
\begin{tabular}{cc}
1 & 2 \\
3 & 4 \\
\end{tabular}
\end{table}
\begin{table}
\caption{Table 2}
\label{tab2}
\begin{tabular}{cc}
1 & 2 \\
3 & 4 \\
\end{tabular}
\end{table}
\clearpage{}
\begin{table}
\caption{Table 3}
\label{tab3}
\begin{tabular}{cc}
1 & 2 \\
3 & 4 \\
\end{tabular}
\end{table}
\begin{table}
\caption{Table 4}
\label{tab4}
\begin{tabular}{cc}
1 & 2 \\
3 & 4 \\
\end{tabular}
\end{table}
\end{document}