我正在使用 XeTeX。我需要重新定义 \section 和 \subsection 命令,以便使用一些与titlesec
and/orsectsty
包不兼容的宏。我找到了一些可以执行此操作的代码,这些代码在网上反复出现,似乎源自resume.sty
源代码 {链接在这里}。
尽管一开始的决策树相当糟糕,但实际代码看起来就像您预期的那样:添加一些胶水,插入章节标题,然后再添加一些胶水,然后继续进行,在建议好坏断点的位置之后。但是,如果我在调用后\section{foo}
立即使用另一个\section{bar}
或\subsection{baz}
,它会插入太多空格/胶水(似乎\vskip-\lastskip
没有“抓取”)。我也\subsection
以完全相同的方式重新定义,但在这里将其从 MWE 中省略,因为内置命令可以精确地重现行为(如果有必要,可以通过复制/粘贴/替换轻松重建)。
如果有人能够明白代码这样做的原因,或者提供另一种放置章节标题的方法,那就太好了:
- 在前后定义一些行距(粘合/空白)(但删除连续部分/小节调用之间的“后”行距)
- 采用其他宏,例如调用
zpos
和etoolbox
,并表现 - 进行扩展以保留下面的 MWE 的功能('如果加星标,则如果两个参数' 树、计数器增量和 TOC 更新可以从解决方案中省略,因为它们很容易构建,但最终必须包含它们)
抱歉,MWE 写得太长了,但我已经注释了代码,试图解释发生了什么(我保留了完整的代码,作为它的变体做出现在各处,遇到类似问题的人可能会使用长而独特的宏名(这些宏名在示例之间往往不会改变)来筛选 Google 搜索结果:我就是这么做的)。
插图
左侧的图像是下面的 MWE 代码生成的。右侧的图像使用完全相同的文档内容,使用内置定义\section
,并且是重新定义命令所需的行为(忽略实际文本大小、粗细等,问题在于行距)。
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
并且标题后的实际文本将缩进。请参阅\@afterheading
latex 节标题用于抑制缩进的代码/
% For ease of use, disregard whether the text has a blank line following the call
此注释是错误的:\ignorespaces
忽略空格标记但不\par
忽略空白行(如果您使用\@startsection
以下内容则\par
处理正确)