答案1
下面提供了一个 \beforepage 命令,它将 \beforepage 的参数打印到上一页的顶部。这个想法是将发送到 \beforepage 的参数aux
连同我们想要内容所在的页码信息一起保存在文件中。我选择通过在表单上定义一个宏\later@pagenumber
(例如\csname later@1\endcsname
)来执行此操作,然后如果命令\csname later@1\endcsname
存在,它将在第 1 页的顶部执行。我不得不承认,我对 \write 和 \protected@write 并不完全满意,所以这可能有点“不完美”。但是,它确实有效,正如我常说的那样:
如果它看起来很愚蠢,但却有效,那它很可能就是愚蠢的——但它确实有效。
\documentclass{article}
\usepackage{everyshi}
\makeatletter
\def\beforepage#1{%
% For some (probably good) reason just writing \string\csname later@...
% would not include the space. However, the following
% worked to get that space to define the \csname inside
% the .aux file.
\edef\later@{ later@}%
% Write the previous page number to the .aux file. This could be generalized to take
% the page number as an argument! Then you can make an \AtPage{pagenumber}!
\write\@auxout{%
\string\expandafter\string\gdef\string\csname\later@\the\numexpr\c@page-1\endcsname{\unexpanded{#1}}
}%
}
% When a shipout happens, the current page number is too low (because the page number hasn't been updated yet).
% So we have to increase it by one.
\EveryShipout{\ifcsname later@\the\numexpr\c@page+1\endcsname\csname later@\the\numexpr\c@page+1\endcsname\fi}
% At the first page, no shipout has happened so we have to manually trigger that one.
\AtBeginDocument{\ifcsname later@1\endcsname\csname later@1\endcsname\fi}
\makeatother
\begin{document}
1st page\newpage
2nd page\beforepage{Top of 1st page\newline}\newpage
3rd page\beforepage{Top of 2nd page\newline}\newpage
4th page\beforepage{Top of 3rd page\newline}
\end{document}
答案2
\afterpage
的使用远远超出了它应有的范围,但\beforepage
如果不改变 tex 处理的正常模型就无法实现。
Tex(主要是因为它的 1970 年代的设计)从不将文档保存在内存中,它只保存足够的内容来决定当前的分页符,但是一旦页面被发送出去(你会在日志中看到 [1] [2]....),那么它就会从 TeX 内存中清除,根本无法访问,所以你不能影响早期的页面在这次运行中。
当然,它有可能在下一次运行中影响前面的页面,就像\section{...}
添加到文档中的命令会导致将条目写入 toc 文件一样,该条目将在下次运行开始时输入并影响目录。
因此,任何实现都需要是一个使用外部文件的多运行系统,并且像特定于特定功能集的目录一样。
鉴于现在可用的内存比乳胶理论上设计时可用的内存要多,您可以排版多页,将整个章节排版到一个垂直列表中,然后“手动”管理所有的分页和浮动位置,但这意味着要重写乳胶的很大一部分。