用例

用例

我想可靠地检测文档最后一页还剩多少空间。最好可以在\AtEndDocument或类似的钩子中访问它,这样我就可以将此信息写入我自己的辅助文件。另一个选择是如果它自动写入标准文件.aux;然后我可以在下次运行中从那里恢复信息,这不是什么大问题。更重要的是,它必须考虑最后一页的浮动和脚注,包括[b]“一”。

用例

当以“TUGboat”风格整理期刊时,文章不需要从新页开始,需要知道前一篇文章留下了多少空间,这确实应该是自动化和可靠的。这将被纳入我工作的软件包中,该软件包允许编辑期刊。

例子

在下面的例子中,它\rule作为一种测量工具,通过反复试验来检测最终的空间。

示例 1 – 没有数字

\documentclass[a4paper]{article}
\usepackage{lipsum,showframe}
\begin{document}
\lipsum
%\rule[-1ex]{10pt}{0.75\textheight}
\end{document}
% SHOULD GIVE "0.75\textheight"

示例 2 – 上图

\documentclass[a4paper]{article}
\usepackage{lipsum,showframe}
\begin{document}
\lipsum

\begin{figure}[t] \rule{3cm}{3cm} \caption{A black square} \end{figure}

%\rule[-1ex]{10pt}{0.54\textheight}
\end{document}
% SHOULD GIVE "0.54\textheight"

示例 3 – 上图和下图

\documentclass[a4paper]{article}
\usepackage{lipsum,showframe}
\begin{document}
\lipsum

\begin{figure}[t] \rule{2cm}{2cm} \caption{A small black square} \end{figure}

\begin{figure}[b] \rule{3cm}{3cm} \caption{A black square} \end{figure}

%\rule[-1ex]{10pt}{0.37\textheight}
\end{document}
% SHOULD GIVE "flag: figure/footnote at the bottom of the last page" and "0.37\textheight" OR "0\textheight"

示例 4 – 图表在顶部,脚注在底部

\documentclass[a4paper]{article}
\usepackage{lipsum,showframe}
\begin{document}
\lipsum

Random text\footnote{A random footnote.}.

\begin{figure}[t] \rule{3cm}{3cm} \caption{A small black square} \end{figure}

%\rule[-1ex]{10pt}{0.50\textheight}
\end{document}
% SHOULD GIVE "flag: figure/footnote at the bottom of the last page" and "0.50\textheight" OR "0\textheight"

答案1

这将使用\tikzmark\vfill来计算最后一页(或任何使用的页面)的剩余空间\pagespace。需要运行两次来计算长度,再运行一次才能将值返回到\begin{document}

可以使用\pdflastypos而不是 tikz 来实现这一点。您甚至可以通过\lastpagegap在读取辅助文件时而不是在结束时进行计算将其减少到 2 次运行。

\documentclass[a4paper]{article}
\usepackage{lipsum,showframe}
\usepackage{tikz}
\usetikzlibrary{tikzmark}

\newlength{\lastpagegap}% reserve global name

\makeatletter
\newcommand{\pagespace}{%
  \hrule height0pt %terminate last paragraph, it needed
  \strut\tikzmark{lastpage}
  \vfill
  \noindent\begin{tikzpicture}[remember picture,overlay]
    \coordinate (lastpage) at (pic cs:lastpage);
    \pgfextracty{\lastpagegap}{\pgfpointanchor{lastpage}{center}}
    \global\advance\lastpagegap by \ht\strutbox
    %\node[above right]{\the\lastpagegap};
  \end{tikzpicture}%
  \write\@auxout{\string\global\string\lastpagegap=\the\lastpagegap}% store in aux file
 }
\makeatother

\begin{document}
\the\lastpagegap

\lipsum

Random text\footnote{A random footnote.}.

\begin{figure}[t] \rule{3cm}{3cm} \caption{A small black square} \end{figure}

\pagespace\smash{\rule{10pt}{\lastpagegap}}
\end{document}

答案2

这是一个使用\pagegoal和 的解决方案\pagetotal。宏\getremainingheight将命令写入辅助文件,该文件将剩余高度写入另一个辅助文件(这里\jobname.xyz,我标记了每个以源结尾的文件,因为找到它们有点困难)。文件中的高度最终确定后,文件中的值即有效,因此在大多数情况下,在第一次运行后有效。

无需对浮点数和/或脚注做任何特殊处理,因为 TeX/LaTeX 已经做到了这一点。而且由于 的​​钩子\AtEndDocument几乎在 的开头执行\end{document},因此可以将宏放入 中\AtEndDocument

如果末尾有一个浮动页面,则宏不会识别它。它将报告最后一个非浮动页面的剩余高度。

\newpage如果由于某种原因,末尾有一个或类似的内容(可能隐藏在某些宏中),则会报告剩余高度为 0pt(您可以轻松更改此高度)。这无法避免,因为新页面已在\getremainingheight调用时启动。但我实现了一个标志\ifendonnewpage,其状态也写入辅助文件。

我还自由地实现了一个附加功能:您可以设置一个\minimumheight。如果剩余高度小于该高度,则报告高度 0pt。

\documentclass[a4paper]{article}
\usepackage{showframe}
\usepackage{lipsum}

\makeatletter
% write information about free space to \jobname.xyz
\AtEndDocument{\if@filesw\newwrite\tf@xyz
    %                                 ^^^
    \immediate\openout\tf@xyz\jobname.xyz\fi
    %                     ^^^         ^^^
}
\newdimen\remainingheight
\newdimen\minimumheight
\newif\ifendonnewpage
\endonnewpagefalse
\newcommand*{\calcremaining}{%
    \par
    % in case a new page just started report a remaining height of 0pt
    \ifdim\pagegoal=\maxdimen
        \remainingheight\z@
        \endonnewpagetrue
    \else
        \remainingheight\pagegoal
        \advance\remainingheight by -\pagetotal
        \advance\remainingheight by -\lineskip
        \endonnewpagefalse
    \fi
}
\newcommand*{\getremainingheight}{%
    \calcremaining
    % if not enough space, report 0pt remaining space
    \ifdim\remainingheight<\minimumheight
        \remainingheight\z@
    \else
        % important, otherwise the remaining height reported would be slightly too large
        \noindent
        \calcremaining
    \fi
    % write to own aux file via main aux
    \immediate\write\@auxout{\string\@writefile{xyz}{\string\remainingheight\the\remainingheight}}%
    %                                           ^^^
    \immediate\write\@auxout{\string\@writefile{xyz}{\ifendonnewpage\string\endonnewpagetrue\else\string\endonnewpagefalse\fi}}%
    %                                           ^^^
}
% just load the file to show the values in this document
% this will of course need two runs
\AtBeginDocument{\InputIfFileExists{\jobname.xyz}{}{}}
%                                            ^^^
\AtEndDocument{\getremainingheight
% just for testing, will of course produce a third page, if the
% remaining height is less then \baselineskip
%    \ifdim\remainingheight>0pt\rule{10pt}{\remainingheight}\fi
}
\makeatother

% set minimum space to be reported, less then that will be reported as 0pt
\setlength{\minimumheight}{\baselineskip}

\begin{document}
\lipsum

Remaining height: \the\remainingheight; ended on new page: \ifendonnewpage yes\else no\fi

Random text\footnote{A random footnote.}.

% see what happens if page is full
%\lipsum[4]
%\lipsum[4]
%One more line to fill the page.

\begin{figure}[t] \rule{2cm}{2cm} \caption{A small black square} \end{figure}

\begin{figure}[b] \rule{3cm}{3cm} \caption{A black square} \end{figure}

% this will produce a float page, which is not recognized at all
%\begin{figure}[p] \rule{4cm}{4cm} \caption{A big black square} \end{figure}

% see what happens, if there is a newpage at the end
%\newpage
\end{document}

相关内容