宏记录它在哪个页面上 - 一个可能的解决方案?

宏记录它在哪个页面上 - 一个可能的解决方案?

虽然我只使用 LuaLaTeX,但我相信这个问题同样适用于 pdflatex (也许还有 XeTeX)。这个问题之前已经由几个人以不同的方式提出过。

老问题:在编译期间,无需重新编译,位于主文本中的宏是否可以知道它在哪个页面上?

旧答案:不,因为异步页面输出例程。虽然\thepage会打印一些内容,但可能是错误的,因为在遇到时尚未确定分页符thepage。您能做的最好的事情是提供一个\label,它将被记录在aux文件中,并由第二个编译解释。

现在,就我而言,我从不使用超链接,因为我的文档仅用于打印到纸张。我加载它hyperref是因为涉及 PDF/X 的东西需要它,但从未创建过任何链接。而且,虽然我希望宏知道它的页码,但我实际上不必打印该数字,也不需要根据该数字重新格式化任何内容。我只是希望记录该数字,解析它,然后根据该数字稍后将消息写入日志文件。此外,我的布局始终是双面单列。

我相信这是可以做到的!但我的编程水平不够高,所以无法确定。

梅威瑟:

\documentclass{article}
\usepackage{hyperref} % because the real document uses it for non-link reasons
\edef\myscramble{\pdfcreationdate}
% If using lualatex, either \usepackage{luatex85} or alternative synatax for date.
\begin{document}
\vspace*{6in} % so that the strange paragraph straddles pages
yada\par
yada\par
yada\par
yada\par
\noindent\hspace{\parindent}\label{alpha\myscramble}\thepage{} aaa aa aaaa aaa aaa aa a aa aa aaa aa a aa aa aaa aa aaa aa aaa  aaa aa aa  aaaaa aaa aaaaa a a aaaaaa aaaa aaaa aa aaaaa a aaaaa aaa a aaaa aa aaa aa aaa a aaaaa aaa a aa aaaa aa a aaaaa a aaaaa a aaaa a aaa aa aaaa aaaa aa aaaaa a aaaaa aaa a aaaa aa aaa aa aaa a aaaaa aaa a aa aaaa aa a aaaaa a aaaaa a aaaa a aaa aa \thepage\label{beta\myscramble}\par
yada\par
yada\par
\end{document}

上面,我使用当前时间来防止在aux后续编译中读取标签。每次编译,标签名称都不同。

\label我发现,如果是段落中的第一个项目,这个技巧并不总是有效。但是,如果我插入一些空格然后将其删除,它就会起作用。在上述情况下,我删除了 ,然后又将其添加回去\parindent

正如异步布局所预期的那样,\thepage全 a 段落的开始和结束处都是 1,即使打印从第 1 页开始并在第 2 页结束。

但如果我查看文件aux,我会看到以下内容:

\newlabel{alphaD:20180416194433-07'00'}{{}{1}{}{Doc-Start}{}}
\newlabel{betaD:20180416194433-07'00'}{{}{2}{}{Doc-Start}{}}

也就是说,aux正确地知道该段落从第 1 页开始,到第 2 页结束。在我的实际测试中,我使用井号而不是普通的\pdfcreationdate,因此标点符号没有问题。

这可能不适用于所有情况(列表等),但似乎适用于普通的流动文本。如果是这样,那么它提供了一种方法来确定(通过宏)特定段落或其他项目是否在同一页上开始和结束。如果在日志文件关闭之前有该信息,则可以对其进行处理,并提供一条消息(例如“您的段落跨页”)作为潜在警告。

新问题 1:在普通、流畅的文本环境中,上述内容有意义吗?也就是说,我是否只是幸运地在测试中成功了,还是它通常应该有效?

新问题 2:在当前日志文件关闭之前,我究竟如何才能获取将写入文件的信息aux,并在宏中使用它?我查看了一些 TeX 代码(由 重写hyperref),头晕目眩。

答案1

经过进一步调查,我相信我找到了解决方案。我没有重写与\label或相关的现有命令\pageref,而是查看了代码(在 hyperref 中)并编写了自己的命令。如果“span”文本拆分页面,则会生成警告。不需要第二次编译。MWE:

\documentclass{article}
% Tested with lualatex and pdflatex. Not tested with xetex, but presumed OK.
\usepackage{xifthen}
% My application requires hyperref, for reasons other than this question.
% Since hyperref rewrites some critical commands, I include it here.
% If you do not use hyperref, some of this may need to be modified:
\usepackage{hyperref}
% Will detect proper use of start and end span:
\newif \ifinsidespan
% Possibly not needed, but I like to initialize things:
\def\myspanstart#1{}
\def\myspanend#1{}
\def\myspanstartpage{}
\def\myspanendpage{}
% hyperref uses @mainaux instead of @auxout for this purpose:
\makeatletter
\def\startspan{\protected@write\@mainaux{\makebox[0pt][l]{~}}{%
  \string\myspanstart{\thepage}}%
}
\def\endspan{\protected@write\@mainaux{\makebox[0pt][l]{~}}{%
  \string\myspanend{\thepage}}%
}
\makeatother
% This prevents repeated compile runs from duplicating messages:
\AtBeginDocument{
  \def\myspanstart#1{%
    \ifinsidespan%
      \ClassWarning{any}{Page #1. Cannot start span without prior end. ^^J}%
    \fi%
    \xdef\myspanstartpage{#1}%
    \global\insidespantrue%
  }
  \def\myspanend#1{%
    \ifinsidespan\else%
      \ClassWarning{any}{Page #1. Cannot end span without prior start. ^^J}%
    \fi%
    \global\insidespanfalse%
    \xdef\myspanendpage{#1}%
    % Now test whether start and end are on same page:
    \ifthenelse{\equal{\myspanstartpage}{\myspanendpage}}{}{%
      \ClassWarning{any}%
       {Span splits pages \myspanstartpage-\myspanendpage. ^^J}%
    }%
  }%
} % end \AtBeginDocument
\begin{document}
\vspace*{6in} % adjust to see effect
yada\par
yada\par
\startspan By changing the above vspace, you can move this paragraph up or down. If all of it fits on the same page, then you will not see a Warning message. However, if you adjust the above vspace so that this paragraph splits pages, then you will see the Warning message. Try 6.5in.\endspan\par
yada\par
yada\par
\clearpage
\vspace*{6.5in} % adjust to see effect
yada\par
yada\par
\startspan By changing the above vspace, you can move this paragraph up or down. If all of it fits on the same page, then you will not see a Warning message. However, if you adjust the above vspace so that this paragraph splits pages, then you will see the Warning message. Try 6.5in.\endspan\par
yada\par
yada\par
\end{document}

相关内容