如何让 longtable 在开始时尊重 \nopagebreak?

如何让 longtable 在开始时尊重 \nopagebreak?

对于我现在正在排版的书,我需要具有以下功能的表格环境:

  1. 跨越多页;
  2. 允许\nopagebreak两行之间
  3. 不要忽略\nopagebreak环境开始之前

第1点和第2点可以通过环境来实现longtable;但是最近我遇到了这样的情况:

\section{Some section}

\begin{longtable}{...}
...

将节标题留在一页上,然后longtable在下一页开始排版。和\nopagebreak之间没有帮助。 我发现\section\begin在 longtable 上提交的 bug大约 9 年前,但似乎没有人感兴趣,并且我对 TeX 不够了解,无法自己修复它。

我尝试了supertabular包 — 它有同样的问题,并且stabular有要点 1 和 3,但没有要点 2。有什么方法可以让它longtable监听?或者也许有其他支持所有这三个要点的包?或者以所需的方式堆叠s 和s\nopagebreak会更容易吗?\hbox\vbox

答案1

编辑:正如下面的评论所指出的那样,这个解决方案有时会产生虚假的标题;我不知道如何(也没有时间)来修复它,抱歉。

有两个问题:首先,\longtable在开始读取表格内容之前,计算当前页面是否有足够的空间。其次,它会插入一个惩罚\z@(读作“零”),换句话说,就是允许 TeX 进行分页的地方。我们需要抑制这两者,但如果您的书中有多个 longtable,则更改不能是永久性的。

将更改放在组中似乎是不可能的(因为\longtable我认为这会在本地重新定义输出例程),因此我添加了一个私有开关来控制是否\break插入惩罚和惩罚。将其放在longtable\normalLTfalse之前和\normalLTtrue之后(而不是内部),以禁止该表的分页符和惩罚。(请注意,注释我们的行将\normalLTfalse导致那里出现分页符。)

也许可以使用的“值”,\if@nobreak而不必明确使用开关,但我不确定何时\if@nobreak\iftrue\iffalse

\documentclass{article}
\usepackage{longtable}
\usepackage{etoolbox}

\newif\ifnormalLT
\normalLTtrue

\makeatletter
\patchcmd {\LT@start}
          {\vfil \break}
          {\ifnormalLT \vfil \break \fi}
          {\typeout{Patching longtable succeeded!}}
          {\typeout{Patching longtable failed!}\ERROR}
\patchcmd {\LT@start}
          {\penalty \z@}
          {\ifnormalLT \penalty \z@ \fi}
          {\typeout{Patching longtable succeeded!}}
          {\typeout{Patching longtable failed!}\ERROR}
\makeatother

% "lipsum" is just used to have some dummy text.
% The vspace is there so that without patch
% we would have a bad page break. Remove all that.
\usepackage{lipsum}
\begin{document}
\lipsum[1-2]
\vspace{2.5cm}
\lipsum[3-4]

\section{XY}
\normalLTfalse
\begin{longtable}{c}
A \\
C \\
\end{longtable}
\normalLTtrue

\end{document}

答案2

使用 needspace 包并放在\Needspace{5\baselineskip}节之前。(确切的值取决于类和节插入的空格。)

相关内容