有没有办法测试 a 是否\pageref
是当前页面?例如,在下面的代码中:
\newcommand\figureref[1]{%
Figure~\ref{#1} (p.~\pageref{#1})
}
(p.~\pageref{#1})
如果引用的图与参考在同一页,我想消除。我尝试使用该varioref
包,但无法将其调整为所需的行为。
更新:
回到最初的问题测试当前页面,这几乎奏效了:
\newcounter{cPage}
\newcommand\figureref[1]{%
Figure~\ref{#1}%
\setcounter{cPage}{\value{page}}\addtocounter{cPage}{1}%
\ifthenelse{\value{cPage}=\pageref{#1}}{}{(p.~\pageref{#1})}%
}
但是,页面值不太一致。有时它会在页面中间发生变化。偏移量在 -1/1 和 +1/2 之间变化,我似乎找不到背后的任何逻辑。
答案1
如果您想要将 \pageref 与当前页面进行比较,则也应该通过设置内部标签对当前页面使用 \pageref。例如:
\documentclass{article}
\usepackage{ifthen}
\newcounter{cPage}
\newcommand\figureref[1]{%
Figure~\ref{#1}%
\refstepcounter{cPage}\label{current\thecPage}%
\ifthenelse{\equal{\pageref{#1}}{\pageref{current\thecPage}}}%
{}{~(p.~\pageref{#1})}}%
\begin{document}
\begin{figure}
\caption{blub}\label{bla}
\end{figure}
\figureref{bla} \newpage \figureref{bla} abc
\end{document}
(varioref 也设置了这样的内部标签,我相当确定可以使用 varioref 获得想要的行为,但我没有时间去查找它)。
您的 \spacefactor 错误可能是由于缺少 \makeatletter 造成的。
答案2
看起来你想要类似的东西
\newcommand*\figureref[1]{Figure~\vref{#1}}
\renewcommand*\reftextbefore{(p.~\thevpagerefnum)}
\let\reftextfacebefore\reftextbefore
\let\reftextafter\reftextbefore
\let\reftextfaceafter\reftextbefore
\renewcommand*\reftextfaraway[1]{(p.~\pageref{#1})}
编辑:varioref
仔细阅读后,我发现我对 \vref 的重新定义是不必要的。
修改 2:您之前没有提到任何内容hyperref
。我不确定最好的解决方法是什么,但下面的方法可行。
\newcommand*\figureref[1]{Figure~\ref{#1}\vpageref[]{#1}}
\makeatletter
\let\old@vpageref\@vpageref
\def\@vpageref[#1]{\@ifnextchar[%]
{\vpageref@interpose{#1}}%
{\vpageref@interpose{#1}[\unskip\vref@space]}%
}
\def\vpageref@interpose#1[#2]#3{%
\def\thereflabel{#3}%
\@@vpageref{#1}[#2]{#3}%
}
\makeatother
\renewcommand*\reftextbefore{\reftextfaraway{\thereflabel}}
\let\reftextfacebefore\reftextbefore
\let\reftextafter\reftextbefore
\let\reftextfaceafter\reftextbefore
\renewcommand*\reftextfaraway[1]{(p.~\pageref{#1})}
我认为hyperref
会发生变化\@@vpageref
,这就是为什么我不直接修改它。
更新:
好的,回到你最初的问题。这本质上就是varioref
解决这个问题的方法。
\documentclass{article}
\newcount\testpagecount
\testpagecount0
\DeclareRobustCommand\ifrefthispage[3]{%
\global\advance\testpagecount1
\getpagenum\refstartnum{tpcstart\the\testpagecount}%
\getpagenum\refendnum{tpcend\the\testpagecount}%
\getpagenum\labelnum{#1}%
\ifx\refstartnum\refendnum\else
\GenericWarning{}{Reference to #1 fell on page
boundary \refstartnum-\refendnum}%
\fi
\testpagelabel{tpcstart\the\testpagecount}%
\ifx\labelnum\refendnum
#2%
\else
#3%
\fi
\testpagelabel{tpcend\the\testpagecount}%
}
\makeatletter
\def\getpagenum#1#2{%
\@ifundefined{r@#2}{\@namedef{r@#2}{{??}{??}}}{}%
\protected@edef#1{\expandafter\expandafter\expandafter
\@cdr\csname r@#2\endcsname\@nil}%
}
\def\testpagelabel#1{%
\protected@write\@auxout{}{\string\newlabel{#1}{{}{\thepage}}}%
}
\makeatother
\begin{document}
\section{Foo}\label{sec:foo}
\ifrefthispage{sec:foo}{Ref is on this page}{Ref is not on this page}
\newpage
\ifrefthispage{sec:foo}{Ref is on this page}{Ref is not on this page}
\end{document}
基本上,它会生成两个新标签,一个位于两个替换文本的两侧,使用\testpagelabel
与标准几乎相同\label
,只是没有实际标签。在后续运行中,它会检查两个标签是否跨越页面边界。如果是,则会发出警告。(诚然,我没有检查该代码路径。)然后,如果第二个标签与您要测试的标签位于同一页面上,则它使用第二个参数中的标记,否则它使用第三个参数中的标记。
请注意,在页面边界上,每次编译时它都可能发生变化。我真的不知道该如何处理。