\thepage 在哪里开始起作用?

\thepage 在哪里开始起作用?

我已经看过相关问题,例如\thepage 的稳定替代品,但我还是像以前一样困惑。MWE:

\documentclass{article}
\begin{document}
\thepage\par
\null\null\null\null\null\null\null\null
\null\null\null\null\null\null\null\null
\null\null\null\null\null\null\null\null
\null\null\null\null\null\null\null\null
\null\null\null\null\null\null\null\null
\null\null\null\null\null\null
\thepage\par
\end{document}

上述代码生成了一份两页的文档。\thepage两页上都打印为 1。再添加一\null两页,第二页\thepage就会正确显示为 2。

显然,\thepage直到页面的第三行左右才会启动。我尝试过更复杂的代码,这似乎是一般情况。

错误?功能?我的错误?有什么方法可以\thepage在页面的第一行就纠正吗?可以使用 LuaTeX。

答案1

你的错误...

下面是一个包含 24 页的示例(你可以增加一点)结果相同 -\thepage继续打印1

在此处输入图片描述

\documentclass{article}

\usepackage[nopar]{lipsum}

\def\x{\lipsum[1]~\thepage~}
\def\xx{\x\x\x\x\x\x\x\x\x\x}

\begin{document}
\xx\xx\xx\xx\xx\xx\xx\xx\xx\xx
\end{document}

这是为什么呢?这是因为第一个(唯一)段落分隔符位于文档末尾(实际上,在 期间发出\end{document}\clearpage。TeX 将上述 100 个\lipsum[1]~\thepage~构造视为一个段落,并且只有某些位置 TeX 才会启动页面生成器(请参阅27.2 激活页面构建器TeX 按主题分类或第 110 页TeX 书):

页面构建器在下列情况下发挥作用。

  • 段落周围:\everypar插入标记后,以及将段落添加到垂直列表后。请参阅本章末尾的示例。
  • 围绕显示公式:\everydisplay插入标记之后,以及将显示添加到列表之后。
  • \par在垂直模式下的命令、框、插入和明确惩罚之后。
  • 输出例程结束后。

如何获得合适的页码?使用\labels,具体来说\pageref

在此处输入图片描述

\documentclass{article}

\usepackage[nopar]{lipsum}

\def\x{\lipsum[1]~\thepage~}
\def\xx{\x\x\x\x\x\x\x\x\x\x}

\begin{document}
\xx\xx\xx\xx\xx\xx\xx\xx\xx\xx%
\label{mylabel}\pageref{mylabel}
\end{document}

这是有效的,因为\labels 被设计为围绕页面构建器运行,因为它需要页面引用功能。

答案2

在决定分页位置后,输出例程在添加页眉和页脚时会递增页码。请注意,这与构成最终将拆分为页面的垂直样张的宏的执行无关。

段落生成器会考虑整个段落,将其排版为一个较长的水平列表,然后再将该列表拆分为行,这意味着无法在宏中直接测试您所在段落的哪一行,因为所有宏都是在考虑换行之前执行的。同样,分页器会切入并考虑拆分构建的垂直列表的一部分,而此时任何宏都将在很久之前展开。如果您的段落很短并且没有太多延伸,分页器可能只会制作一页,因此thepage只会“错误​​”处理从上一页保留下来的段落的最后几行,但通常它可以是任意数量的页面。如果您有足够的文本来制作 10 页的段落,那么该段落内的所有宏都将在任何线已构造(因此在任何页面发出之前),因此\thepage即使打印在第 10 页也会打印 1,例如:

\documentclass{article}

\def\a{one two three four five six seven }
\def\b{\a red blue green\a\a pink yellow }
\def\c{\b\b\a\a\b\b\b aples oranges pears }
\def\d{\c\c\a\a\b\b\b\b\c\c\c\c\c}

\begin{document}
\d\d\d\d\d\d\fbox{\thepage}
\end{document}

在此处输入图片描述

答案3

在思考了 Werner 和 David 所说的话后,我意识到我最初的问题是错误的。我宁愿在日志中获取信息消息,而不是在页面上写些什么,或强制将文本放在一个块中。原因是还有很多其他事情在发生,太复杂了,无法在这里用问题来表达(而且我不是一名优秀的程序员)。

但我能够提出以下 MWE,它表现出预期的行为:

\documentclass[letterpaper,12pt]{article}
\RequirePackage{everyshi}
\RequirePackage{xifthen}
\newcounter{runningPage} % Not necessarily the page number!
\newcounter{tempInsertStuff}
\newcounter{tempFinishStuff}
\EveryShipout{\stepcounter{runningPage}}
\newcommand\insertStuff{%
  \setcounter{tempInsertStuff}{\value{runningPage}}%
  \setcounter{tempFinishStuff}{\value{runningPage}}%
}
\newcommand\finishStuff{%
  \strut% seems necessary?
  \setcounter{tempFinishStuff}{\value{runningPage}}%
  \ifthenelse{\equal{\value{tempInsertStuff}}{\value{tempFinishStuff}}}{}{%
    \typeout{Ahoy: `Stuff` crossed page, at or before page \thepage.^^J}%
  }%
}
\begin{document}
yada0\par yada1\par yada2\par yada3\par yada4\par yada5\par yada6\par    yada7\par yada8\par yada9\par
yada10\par yada11\par yada12\par yada13\par yada14\par yada15\par yada16\par yada17\par yada18\par yada19\par
yada20\par yada21\par yada22\par yada23\par yada24\par yada25\par yada26\par yada27\par yada28\par yada29\par\insertStuff
yada30\par yada31\par yada32\par yada33\par yada34\par yada35\par yada36\par yada37\par yada38\par \finishStuff yada39\par
yada40\par yada41\par yada42\par yada43\par yada44\par yada45\par yada46\par yada47\par yada48\par yada49\par
\end{document}

当 放在 yada38 之后时,会写入日志消息(Ahoy)finishStuff,yada38 是第二页的第一段。但是当 放在finishStuffyada37 之后时,不会写入消息,yada37 是第一页的最后一段。因此,如果我的文本块是 yada30 到 38,它可能会中断,但我会收到消息。

在我看来,段落越长越好,但其他人可能会发现上述解决方案无效。

相关内容