自定义 varioref 以仅添加“...第 XX 页”,并且仅当参考和图表之间有多页时

自定义 varioref 以仅添加“...第 XX 页”,并且仅当参考和图表之间有多页时

varioref是一个很好的软件包,因为它会在引用时添加“... 在 [上页/下页/前页/后页]”,如果引用和图表(或任何引用的对象)位于不同的页面上。如果中间有多个页面,varioref则会添加“... 在第 XX 页上”。

但是,我注意到所有这些“...在 [上页/下页/等]”有点多余;当引用很远时,我真正需要的只是“...在第 XX 页”。在我的文档中,我通过重新定义适当的 TeX 定义解决了这个问题varioref

\makeatletter
\vref@addto\extrasenglish{%
  \def\reftextfaceafter{}
  \def\reftextfacebefore{}
  \def\reftextafter{}
  \def\reftextbefore{}
  \def\reftextcurrent{}
}
\makeatother

但是,它感觉不太可靠,因为只有english选择 时才有效。对于american,我必须复制粘贴相同的命令,但用extraenglish替换extraamerican

是否有更有效、更“彻底”的方法来实现相同的目标,但适用于所有语言选项?对我来说这真的没有必要,因为我知道我会使用english,但出于好奇我对此很感兴趣。=)

答案1

由于这些命令是在 babel 的任何命令中定义的\extra...(如果正在使用 babel),因此需要对所有正在使用的语言应用此类更改,或者(更好的选择)自行修补varioref。幸运的是,这些命令仅在一个地方使用,即\@@vpageref。因此,一般解决方案是:

\documentclass{article}

\usepackage{varioref}
\usepackage{etoolbox}

\makeatletter
\patchcmd{\@@vpageref} {\reftextfacebefore}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}
\patchcmd{\@@vpageref} {\reftextfaceafter}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}

% for \reftextafter and \reftextbefore we have to patch twice

\patchcmd{\@@vpageref} {\reftextbefore}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}
\patchcmd{\@@vpageref} {\reftextbefore}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}

\patchcmd{\@@vpageref} {\reftextafter}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}
\patchcmd{\@@vpageref} {\reftextafter}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}

\show\@@vpageref  % have a look at the results
\makeatother

它有点粗糙,因为\@@vpageref现在包含一些绝对无用的代码,即一堆 if-then-else 语句,其中没有任何代码可执行。但谁在乎呢 ;-)

如果您只想禁用“面部”按钮但保留需要翻页的按钮,上述方法也能很好地发挥作用。

varioref + hyperref/nameref

如果 hyperref 或 nameref(hyperref 包的一个组件)与 varioref 结合使用,则修补需要略有不同。在这种情况下,包含调用的宏不是,\@@vpageref而是\NR@vprageref。此外,它只会在之后获得其定义\begin{document},因此修补命令将如下所示:

\makeatletter
\AtBeginDocument{%
\patchcmd{\NR@@vpageref} {\reftextfacebefore}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}%
\patchcmd{\NR@@vpageref} {\reftextfaceafter}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}%
\patchcmd{\NR@@vpageref} {\reftextbefore}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}%
\patchcmd{\NR@@vpageref} {\reftextbefore}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}%
\patchcmd{\NR@@vpageref} {\reftextafter}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}%
\patchcmd{\NR@@vpageref} {\reftextafter}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}}
\makeatother

重要的:即使执行了此代码,也\AtBeginDocument需要放置 hyperref已加载,原因是hyperref也用于\AtBeginDocument定义\NR@@vpageref

varioref + cleveref (+ hyperef)

如果cleveref使用该软件包,则需要更多/不同的修补,因为不幸的是,该软件包使用了部分代码的另一个“私有”副本varioref,唉。因此在这种情况下\cref@old@@vpageref需要修补,否则它就是完全相同的方法:

\makeatletter

\patchcmd{\cref@old@@vpageref} {\reftextfacebefore}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}
\patchcmd{\cref@old@@vpageref} {\reftextfaceafter}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}

% for \reftextafter and \reftextbefore we have to patch twice

\patchcmd{\cref@old@@vpageref} {\reftextbefore}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}
\patchcmd{\cref@old@@vpageref} {\reftextbefore}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}

\patchcmd{\cref@old@@vpageref} {\reftextafter}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}
\patchcmd{\cref@old@@vpageref} {\reftextafter}{\unskip}{\typeout{*** SUCCESS ***}}{\typeout{*** FAIL ***}}
\makeatletter

更新/修正

正如 Gabriel 指出的那样,我最初的想法以及我对它的概括是,修补命令\reftextafter和朋友,使它们什么都不做,其副作用是最终会产生一个额外的空格。原因是这个空格是在\vref第一个数字后自动生成的,假设后面会有一些文本(例如“下一页”)。因此,处理这个问题的正确方法是修补命令,而不是取下 mout,而是用 替换它们, \unskip从而再次删除多余的空格。

上面的代码已经修正了!

答案2

尝试:

\AtBeginDocument{\def\reftextfaceafter{\unskip}%
  \def\reftextfacebefore{\unskip}%
  \def\reftextafter{\unskip}%
  \def\reftextbefore{\unskip}%
  \def\reftextcurrent{\unskip}}

相关内容