连续的自定义 \section 宏调用之间出现不需要的垂直空格/粘连

连续的自定义 \section 宏调用之间出现不需要的垂直空格/粘连

我正在使用 XeTeX。我需要重新定义 \section 和 \subsection 命令,以便使用一些与titlesecand/orsectsty包不兼容的宏。我找到了一些可以执行此操作的代码,这些代码在网上反复出现,似乎源自resume.sty源代码 {链接在这里}。

尽管一开始的决策树相当糟糕,但实际代码看起来就像您预期的那样:添加一些胶水,插入章节标题,然后再添加一些胶水,然后继续进行,在建议好坏断点的位置之后。但是,如果我在调用后\section{foo}立即使用另一个\section{bar}\subsection{baz},它会插入太多空格/胶水(似乎\vskip-\lastskip没有“抓取”)。我也\subsection以完全相同的方式重新定义,但在这里将其从 MWE 中省略,因为内置命令可以精确地重现行为(如果有必要,可以通过复制/粘贴/替换轻松重建)。

如果有人能够明白代码这样做的原因,或者提供另一种放置章节标题的方法,那就太好了:

  • 在前后定义一些行距(粘合/空白)(但删除连续部分/小节调用之间的“后”行距)
  • 采用其他宏,例如调用zposetoolbox,并表现
  • 进行扩展以保留下面的 MWE 的功能('如果加星标,则如果两个参数' 树、计数器增量和 TOC 更新可以从解决方案中省略,因为它们很容易构建,但最终必须包含它们)

抱歉,MWE 写得太长了,但我已经注释了代码,试图解释发生了什么(我保留了完整的代码,作为它的变体出现在各处,遇到类似问题的人可能会使用长而独特的宏名(这些宏名在示例之间往往不会改变)来筛选 Google 搜索结果:我就是这么做的)。

插图

左侧的图像是下面的 MWE 代码生成的。右侧的图像使用完全相同的文档内容,使用内置定义\section,并且是重新定义命令所需的行为(忽略实际文本大小、粗细等,问题在于行距)。

MWE 图像 固定图像

MWE 代码

\documentclass{article}

\makeatletter
%We want to take a minimum of one command, with an optional command which holds
%a different title for the TOC; if starred, then don't insert number
%So, numbered or not?
\def\section{\@ifstar\unnumberedsection\numberedsection}
%One or two args?
\def\numberedsection{\@ifnextchar[%]%
\numberedsectionwithtwoarguments\numberedsectionwithoneargument}
\def\unnumberedsection{\@ifnextchar[%]%
\unnumberedsectionwithtwoarguments\unnumberedsectionwithoneargument}
%If one arg, duplicate it to make two, so only one set of commands needs be
%written
\def\numberedsectionwithoneargument#1{\numberedsectionwithtwoarguments[#1]{#1}}
\def\unnumberedsectionwithoneargument#1{\unnumberedsectionwithtwoarguments[#1]{#1}}

% Unstarred case, ie insert number:
\def\numberedsectionwithtwoarguments[#1]#2{%
%Check that previous paragraph ends sanely
\ifhmode\par\fi%
%Remove previous glue, to avoid huge spaces
\vskip-\lastskip%
%Insert some glue to separate heading; here's a good place to break the page
\vskip 3ex\@plus 1ex \@minus 0.5ex\goodbreak%
%Increment section number counter
\refstepcounter{section}%
%Insert formatted heading command here (plus number)
%In my actual usage, it has some other formatting macros, but this MWE reproduces
%the problem, so I know it's not them causing it
\begingroup \parindent=0pt {\Large \bfseries \thesection\  #2}
%We don't want to separate the heading from the text which follows
\nobreak\endgroup%
%Let it breathe a bit!
\vskip 2ex\@plus 0.67ex \@minus 0.5ex%
%No, we still /really/ don't want to separate it; nor indent the para which
%follows
\nobreak\noindent%
%Add it to the TOC
\addcontentsline{toc}{section}{%
\protect\numberline{\thesection}%
#1}%
%For ease of use, disregard whether the text has a blank line following the call
%to '\section'
\ignorespaces}

%Do exactly the same with the unnumbered case, except don't include a number
%This is closer to the original code I found, so can be used to verify it's none
%of my modifications, eg stretch and squeeze on vskips
\def\unnumberedsectionwithtwoarguments[#1]#2{%
\ifhmode\par\fi
\removelastskip
\vskip 3ex\goodbreak
%Insert formatted heading command here without number
\begingroup \parindent=0pt {\Large \bfseries #2}\par%
\nobreak\endgroup%
\vskip 2ex\nobreak\noindent%
\addcontentsline{toc}{section}{%
#1}%
\ignorespaces}
\makeatother

\begin{document}

\section{A new section}
\ldots which behaves as it should.

\subsection{A new subsection}
\ldots which also behaves, but:

\section{A new section}
\subsection{followed immediately by a subsection}
\ldots inserts too much white space.

\section{Two sections}
\section{One after the other}

\section*{Verify unnumbered}
\subsection*{Also a problem}

\section*{And check unnumbered without following subsection}
\noindent\ldots which is fine.  The fact that the subsection -- section
combination works suggests perhaps a problem with the final vskip in the macro?
\end{document}

答案1

除非有充分理由不这样做,否则您应该使用\@startsection,因为它包含处理连续标题的代码,以及处理多行标题或后跟空白行的代码,这些都不由本代码处理

\vskip-\lastskip%
%Insert some glue to separate heading; here's a good place to break the page
\vskip 3ex\@plus 1ex \@minus 0.5ex\goodbreak%

这可能会或可能不会删除空间(取决于现有空间是否受到惩罚保护)以及现有空间是否大于或小于要添加的 3ex。

如果您\addvspace按照标准分段和显示环境代码使用,则会检查先前的空间并使用现有空间和新值中的最大值。

\begingroup \parindent=0pt {\Large \bfseries \thesection\  #2}
%We don't want to separate the heading from the text which follows
\nobreak\endgroup%

这将在段落设置之前结束组,因此设置\parindent=0pt不执行任何操作,并且如果标题超过一行,即使它使用\Large文本,它也将被设置在较小的(正常尺寸)基线上。

\nobreak\noindent%

\noindent开始以下段落,因此如果源在节标题后有一个空白行(或如您的示例中所示,后面有一个标题),则此段落将以 结束,\par并且标题后的实际文本将缩进。请参阅\@afterheadinglatex 节标题用于抑制缩进的代码/

% For ease of use, disregard whether the text has a blank line following the call

此注释是错误的:\ignorespaces忽略空格标记但不\par忽略空白行(如果您使用\@startsection以下内容则\par处理正确)

相关内容