LaTeX教程(010)- LaTeX \LaTeX LATEX文档结构(10)
本篇是讲解标题样式的最后一篇
2.2.8 使用 LaTeX \LaTeX LATEX内部的底层方法设置标题格式
除了使用一些高级接口,了解一下
LaTeX
\LaTeX
LATEX内核中定义的接口也很有用。
LaTeX
\LaTeX
LATEX提供了一个名为\@startsection
的通用命令用来定义多种标题布局。还有一个可以用来生成具有任意布局的分节样式的命令\secdef
。它可以用来定义新的章节划分命令,标准类用它来定义\chapter
和\part
标题。
通用命令\@startsection
命令的形式如下:
\@startsection{name}{level}{indent}{beforeskip}{afterskip}{style}
介绍一下这些参数分别表示什么:
name
: 标题所对应的计数器的名称。我们已经知道了对于一个章节划分命令\<name>
,它的计数器名称就是<name>
,而编号的输出命令是\the<name>
。这里再补充一点,由该命令所生成的页眉命令是\<name>mark
。例如,\section
的计数器名称就是section
,编号的输出命令是\thesection
,如果要自定义当前的\section
标题所生成的页眉,可以在当前这一节的区域内使用\sectionmark{some text...}
。这样,这一节的页眉就会被替换为some text…level
表示要定义的章节划分命令的级别。indent
表示标题相对于左边距的缩进。可以是负数。它的作用和\titlespacing
命令的left-sep
参数类似。不同的是,indent
作为负数和正数对标题(尤其是长标题)的对齐会有不同的影响。当它是正数时,该标题的所有行都会按这个值进行缩进。当indent
是负数时,标题的第一行会插入左边距中,其余行不会(其余行默认靠左边距对齐)。我们做个演示:
\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\begin{document}
% 含有内部命令的命令用\makeatletter和\makeatother包括起来
\makeatletter
\renewcommand\section{\@startsection{section}{1}{2cm}{-\baselineskip}{0.5\baselineskip}{\fontsize{17.28pt}{17.28pt}\bf}}
\makeatother
\section{This is a very very \ldots\/ long title of a section}
some text
\end{document}
编译:
如果我们将2cm
换成-2cm
,标题就会变成:
beforeskip
参数定义了标题前面(上方)留出的空间。它的作用和\titlespacing
命令的before-sep
参数类似。不同的是,beforeskip
起作用的是它的绝对值。1cm
和-1cm
对标题上方空间的影响是一样的,不同的是,该参数是负数时,标题后面的第一段的首行缩进会被抑制。
在
LaTeX
\LaTeX
LATEX中,段落和段落之间的垂直距离存储在命令\parskip
中(它根据字体和字形发生变化),而
LaTeX
\LaTeX
LATEX在生成一个标题时也会开始一个新段落,因此标题前面的段落到标题的垂直距离其实是|beforeskip|+段落字体的\parskip+标题字体的\baselineskip
。\baselineskip
是文本行于文本行之间的间距,它随字体与字号发生变化。
afterskip
是标题之后要留出的空间。对于陈列标题,它表示垂直空间,对于嵌入标题,它表示水平空间。而afterskip
参数的符号(正负号)则决定了被定义的标题是陈列标题还是嵌入标题。大于0时则生成陈列标题,小于0时则生成嵌入标题。因此,对于陈列标题,它与后面的段落之间的垂直距离是afterskip+标题字体的\parskip+段落字体的\baselineskip
。对于嵌入标题,水平距离就是|afterskip|
。我们无法使标题到其后段落的距离小于\parskip
,因为这个参数的负号并不参与加减计算,而是意味着将陈列标题变成内嵌标题。
style
处放置一些可以影响标题文本排版样式的命令,如\bfseries
等。
\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\begin{document}
\makeatletter
\renewcommand\subsection{\@startsection{subsection}{2}{0mm}
{-\baselineskip}{0.5\baselineskip}{\normalfont\normalsize\itshape}}
\makeatother
\section{A section}
\ldots\ some text above.
\subsection{Subsection Heading}
The first paragraph following the redefined subsection heading \ldots \par And a second one (indented).
\end{document}
编译:
\@startsection
的第一个参数是subsection
,它是\subsection
的计数器。第二个参数是2,表示\subsection
是2级标题。第三个参数是0mm
,表示标题左侧不缩进。第四个参数是负数,因此后面的段落没有首行缩进。它的绝对值决定了标题前的垂直距离。第五个参数是正数,表示subsection
是一个陈列标题。它的绝对值决定了标题后的垂直距离。第六个参数表示标题用正常字体正常字号斜体字形排版。
在
LaTeX
\LaTeX
LATEX的标准类中,\part
和\chapter
都不是用\@startsection
定义的,使用该命令无法生成它们需要的布局。它们是用\secdef
命令定义的。\secdef
命令若要定义更多的样式,它需要与其他命令配套使用。\secdef
命令的形式如下:
\newcommand\myhead{\secdef\myheadA\myheadB}
它需要有定义\myheadA
和\myheadB
的命令与之配套。
有了这些定义之后,我们使用\myhead{title}
时,实际上是在调用\myheadA[title]{title}
; 使用\myhead[toc-entry]{title}
时,实际上是在调用\myheadA[toc-entry]{title}
; 使用\myhead*{title}
时,实际上是在调用\myheadB{title}
; 回顾一下003篇,这其实就是我们使用的章节划分命令的三种形式。
也就是说,\secdef
命令中包括了一些对命令与参数的判断,它根据我们输入的命令是否带有星号,以及有没有可选参数来决定调用哪个命令。
定义\myheadA
和\myheadB
的时候要注意,\myheadA
要有一个可选参数和一个必选参数,而\myheadB
只有一个可选参数。
在这之前,我们先讲一下如何用newcommand
定义带有可选参数的命令。使用
\newcommand{\mycom}[2][default]{#1\ldots A\ldots}
之后,就定义了一个形式为\mycom[test01]{test02}
的命令。如果不指定选项,那么#1
处就会出现default
; 如果指定了选项,那么就会出现指定的内容test01
。
现在我们演示一下\secdef
的作用:
\documentclass{article}
\usepackage[a5paper,margin=1in]{geometry}
\begin{document}
\newcommand\mycom{\secdef\mycomA\mycomB}
\newcommand{\mycomA}[2][default]{A-#1;A-#2}
\newcommand{\mycomB}[1]{B-#1}
\mycom{test01}
\mycom[test01]{test02}
\mycom*{test03}
\end{document}
编译:
在
LaTeX
\LaTeX
LATEX中,附录也是章节划分命令的变体。我们可以重定义一个简单的\appendix
变体(留意注释):
\makeatletter
\renewcommand\appendix{ % 重定义\appendix
\renewcommand\section{ % 使用\appendix会重定义\section命令
\clearpage\thispagestyle{plain} % \clearpage使得每个\section都会在一个新的页面上
\suppressfloats[t]\@afterindentfalse % 抑制顶部浮动体,并抑制第一段的首行缩进
\secdef\Appendix\sAppendix} % 定义两种待选择的变体
\setcounter{section}{0}\renewcommand\thesection{\Alph{section}}}
% 最后将section计数器置零,并重新格式化为大写字母。
接下来我们需要定义\Appendix
:
\newcommand\Appendix[2][?]{% % \Appendix有一个可选参数
\refstepcounter{section}% % 每次使用\Appendix后,section计数器+1
\addcontentsline{toc}{appendix}{\protect\numberline{\appendixname~\thesection}#1}% 生成目录条目
{\raggedleft\large\bfseries \appendixname\thesection\par\
% 设置标头样式,靠右,字号为large,字形为bf,并将标头生成为
% appendixname\thesection,即Appendix A这样的形式。
\centering#2\par}
% 将标题文本#2放在下一行,并居中。\par是换行
\sectionmark{#1} % 生成页眉条目
\@afterheading\addvspace{\baselineskip}}
% 设置段落缩进
再定义\sAppendix
:
\newcommand\sAppendix[1]{
{\raggedleft\large\bfseries\appendixname\par \centering#1\par}
\@afterheading\addvspace{\baselineskip}}
\makeatother
% \sAppendix命令是appendix命令是星号形式
% 因此它不需要有页眉和目录条目,只有标题文本
最后,我们使用已经定义好的命令:
\appendix
\section{The list of all commands}
Then follows the text of the first section in
the appendix. Some more text in the appendix.
编译: