I am using XeTeX. I need to redefine the \section and \subsection commands in order to use some macros which don't behave well with the titlesec
and/or sectsty
packages. I found some code to do this, which comes up repeatedly over the net, and which seems to originate from the resume.sty
source {link here}.
Despite the rather awful decision tree at the beginning, the actual code looks as you'd expect: put some glue, insert the section title, then some more glue, and get on with it, after suggesting where good and bad breaks would be. However, if I follow a \section{foo}
call immediately by another \section{bar}
or \subsection{baz}
, it inserts too much whitespace/glue (the \vskip-\lastskip
doesn't seem to 'grip'). I have also redefined \subsection
in precisely the same fashion, but omitted it from the MWE here as the inbuilt command reproduces the behaviour exactly (easy enough to reconstruct if necessary by copy/paste/substitute).
It would be wonderful if someone can either see the reason why the code does this, or provide an alternative way to place section headings that can:
- have some defined amount of leading (glue/whitespace) before and after (but remove the 'after' leading in between consecutive section/subsection calls)
- take other macros, which call, eg,
zpos
andetoolbox
, and behave - be extended to preserve the functionality of the MWE below (the 'if starred this then if two args that' tree, counter increments, and TOC updates, can be omitted from solutions, as they're trivial to build, but they are ultimately necessary to include)
Apologies for drawn out MWE, but I've commented the code to try to explain what's going on (I've left the full code in, as mutations of it do appear all over, and people with a similar problem might use the long and rather unique macro names, which tend not to change between examples, to winnow down Google results: I did).
Illustrations
The image on the left is what is produced by the MWE code below. The image on the right uses the exact same document content, using the inbuilt \section
definition, and is the desired behaviour for the redefined command (ignore actual text size, weight, etc, the problem is the leading).
MWE code
\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}
\@startsection
and friends)\@startsection
begins expanding and writing to the.aux
etc., as the LaTeX commands are either inbuilt or inarticle.cls
which is loaded first in the process) Even defining these other macros using\DeclareRobustCommand
results in all kinds of other pain relating tozpos
etc. This problem, ie insert some whitespace and delete it in certain well-defined cases, seems a much easier one to solve, and more general.\@startsection
is concerned with exactly this problem of putting suitable spaces before and after possibly consecutive headings, so using\@startsection
is likely to be the answer unless you can show an example where it doesn't work.