我使用 lstlisting (listins-package) 定义了一个大型列表。现在列表已超过三页。最后一页只有一行(最后一行)列表。看起来不太好看,因为该行仅包含一个括号。
如果列表在新页面上结束,是否有办法确保列表末尾出现至少 n(即三)行?
答案1
可能性是存在的,但实现起来有点困难。该listings
包包含许多钩子,但不幸的是,没有一个钩子能够直接实现这一点(至少我快速阅读后没有看到一个)。
问题在于,列表中的每一行实际上都是一个段落,因此\parskip
行与行之间会有一些断点,这些断点构成了有效的断点。因此,需要的是添加一些断点,\nobreak
以防止出现断点。这发生在命令中\lst@NewLine
,因此主要的技巧是修补此命令:
\makeatletter
\def\lst@NewLine{%
\ifx\lst@OutputBox\@gobble\else
\par
\ifnum\c@lstnumber > \@nobreaklinepoint \relax \nobreak \fi % <-- new code
\noindent \hbox{}%
\fi
\global\advance\lst@newlines\m@ne
\lst@newlinetrue}
现在\@nobreaklinepoint
应该是列表中倒数第三行的行号。好吧,这是第二个问题:我们不知道在处理过程中列表的行数。因此,为了自动获取此信息,需要记录列表中的行,将它们写入辅助文件(或类似文件),并在下一次排版运行中使用记录的值。--- 不,我还没有这样做 :-) 也许其他人有耐心。
相反,我采用了简单的方法让用户手动指定:
\def\lstnobreakafterline#1{\gdef\@nobreaklinepoint{#1}}
因此,如果您的列表有 15 行,并且您想确保最后 3 行始终在一起,则需要说\lstnobreakafterline{13}
。所以需要一点计数,抱歉。
现在所有这些都应该只发生在下一个列表中,所以我们必须做更多的工作:
\lst@AddToHook{ExitVars}{\lstnobreakafterline{\maxdimen}}
\lstnobreakafterline{\maxdimen}
\makeatother
这里我们可以使用内置钩子。我们将数字默认为,\maxdimen
并在列表环境结束时将其重置。
明显的改进可能性:\lstnobreakafterline
我们可以定义一个更适合包接口的新关键字(但现在快到午夜了),当然也可以在双程系统中自动确定数字。
还有一个缺陷:如果\c@lstnumber
对行进行编号,实际上是列表将使用的行号。因此,如果编号持续到多个列表(这可能取决于设置),那么这将不会在每个列表上从 1 重新开始。
尽管如此,还是享受吧;-)