2. 用 LaTeX 排版文字

文字是排版的基础。在介绍 LaTeX 支持的各种文档元素之前,首先应当了解一下如何在 LaTeX 源代码中输入并排版文字,尤其是(西文中的)标点符号、连字符、重音等 一些细节。

本文的开头首先介绍了中文的支持方式。随着 LaTeX 和底层 TeX 引擎的发展,旧方式(CCT, CJK 等)日渐退出舞台,xelatex 编译命令配合 xeCJK 或 ctex 宏包的方式成为主流。

2.1 语言文字和编码

LaTeX 源代码为文本文件,而文本文件的一个至关重要的性质是它的编码。在此用尽量短的篇幅介绍一下。

2.1.1 ASCII编码

计算机的基本储存单位是字节(byte),每个字节为八位(8-bit),范围用十六进制写作 0x00-0xFF。ASCII(美国通用信息交换码)使用 0x00-0x7F 对文字编码,也就是 7-bit,能够表示 QWERTY 键盘上能够输入的拉丁字母、数字和符号。

由于 TeX 最初面向英文文档的排版,ASCII 编码完全够用,而早期版本的 TEX 也只支持 7-bit 和 ASCII。要排版西欧语系中带重音的字符,就必须用到后文所叙述的重音音符,如 Möbius 必须输入 M'‘obius。

2.1.2 扩展编码

在 ASCII 之后,各种语言文字都发展了自己的编码,比如西欧语言的 Latin-1,日本的 Shift-JIS,中国大陆的 GB2312-80 和 GBK 等。它们之中的绝大多数都向下兼容 ASCII,因此无论是在哪种编码下,TEX 以及 LaTeX 的命令和符号都能用。

TEX 从 3.0 版开始支持 8-bit,能够处理源代码里编码处于 0x80-0xFF 范围的字符。西欧(拉丁字母)、俄语系(西里尔字母)等语言的编码方案刚好能够利用 0x80-0xFF 这个范围,处理起来较为方便。LaTeX 命令及 pdflatex 命令下,这些编码的处理由 inputenc 宏包支持。比如将源代码保存为 Latin-1 编码,并在导言区调用宏包:

\usepackage[latin1][inputenc]

接下来,Möbius 就直接可以通过(用适当输入法)输入 Möbius 得到了。

GBK 等编码是多字节编码,ASCII 字符为一个字节,汉字等非 ASCII 字符为两个字节,这就需要借助一些宏包进行较为复杂的判断和处理。CJK 宏包就是用于处理中、日、韩等多字节编码的语言文字的宏包。但 CJK 宏包的使用非常不方便,笔者不再推荐直接使用。

2.1.3 UTF-8 编码

Unicode 是一个多国字符的集合,覆盖了几乎全球范围内的语言文字。UTF-8 是 Unicode 的一套编码方案,一个字符可以由一个到四个字节编码,其中单字节字符兼容 ASCII 编码。

LaTeX 命令及 pdflatex 命令下可以使用 inputenc 宏包支持 UTF-8 编码:

\usepackage[utf8][inputenc]

xelatex 和 lualatex 命令原生支持 UTF-8 编码,而且也不适用 inputenc 宏包。将 .tex 源代码保存为 UTF-8 编码,并借助 fontspec 宏包(见 5.1.5 小节)调用适当的字体,就可以在源代码中输入任意语言的文字。但各个语言(印地语、阿拉伯语等)的特殊排版要求需要更多的宏包支持,如 bable、polyglossia 等。

2.2 排版中文

2.2.1 xeCJK 宏包

用 LaTeX 排版中文的一大难题是中文字体的处理。TeX 使用的字体格式仅支持不超过 256 个字符,旧式的中文排版方案如 CJK 宏包往往需要复杂的预处理,将中文字体拆成数百个小字体,非常麻烦。

xelatex 命令支持直接使用系统安装的 TrueType(.ttf)/OpenType(.otf) 等格式的字体,加上对 UTF-8编码的原生支持,免去了预处理字体的麻烦。在此基础上的 xeCJK 宏包更进一步完善了排版中文的一些细节,比如中英文之间空隙、中文行尾的回车不引入空格、标点符号不出现在行首,等等。

xeCJK 宏包支持用简单的命令配置中文字体。举一个在 Windows 下使用 xeCJK 的例子(设置字体的命令详见 5.1.6 小节),源代码须保存为 UTF-8 编码,并使用 xelatex 命令编译:

\documentclass{article}
\usepackage{xeCJK}
\setCJKmainfont{SimSun}
\begin{document}
中文\LaTeX{}排版。
\end{document}

2.2.2 ctex 宏包和文档类

ctex 宏包和文档是对 CJK 和 xeCJK 等宏包的进一步封装。ctex 文档类包括 ctexart / ctexrep / ctexbook,是对 LaTeX 的三个标准文档类的封装,对 LaTeX 的排版样式做了许多调整,以切合中文排版风格。最新版本的 ctex 宏包/文档类甚至能够根据操作系统自动配置字体。比如上述例子可进一步简化为:

\documentclass{ctexart}
\begin{document}
中文\LaTeX{}排版。
\end{document}

虽然 ctex 宏包和文档类保留了对 GBK 编码以及 latex + dvipdfmx、pdflatex 等旧的编译命令的支持,笔者建议在使用 ctex 宏包和文档类时总是将源代码保存为 UTF-8 编码,用 xelatex 命令编译。

2.3 LaTeX 中的字符

2.3.1 空格和分段

LaTeX 源代码中,空格键和 Tab 键输入的空白字符视为“空格”。连续的若干空白字符视为一个空格。一行开头的空格忽略不计。

行末的回车视为一个空格;但连续两个回车,也就是空行,会将文字分段。多个空行被视为一个空行。也可以在行末使用 \par 命令分段。

Several spaces equal one.
    Front spaces are ignored.
An empty line starts a new
paragraph. \par
A \verb|\par| command also
starts a new line.

2.3.2 注释

LaTeX 用 % 字符作为注释。在这个字符之后直到行末,所有的字符都被忽略,行末的回车也不引入空格。

This is an % short comment
% ---
% Long and organized
% comments
% ---
example:Comments do not bre%
ak a word.

2.3.3 特殊字符

以下字符在 LaTeX 里有特殊用途,如 % 表示注释,$、^、_ 等用于排版数学公式,& 用于排版表格,等等。直接输入这些字符得不到对应的符号,还往往会出错:

# $ % & { } _ ^ ~ \

如果想要输入以上符号,需要使用以下带反斜线的形式输入:

\# \$ \% \& \{ \} \_
\^ {} \-{} \textbackslash

事实上这些带反斜线的形式就是 LaTeX 命令。 ^ 和 ~ 两个命令是需要带参数的,如果不加一对花括号(空参数),就将后面的字符作为参数,形成重音效果(详见 2.3.6 节)。\ 被直接定义成了手动换行的命令,输入反斜杠就只好用 \textbackalash。

2.3.4 连字

西文排版中经常会出现连字(Ligatures),常见的有 ff / fi / fl / ffi / ffl。

It's difficult to find \idots .\\
it's dif{}f{}icult to f{}ind \idots.

2.3.5 标点符号

中文的标点符号(绝大多数为非 ASCII 字符)使用中文输入法输入即可,一般不需要过多留意。而在英文标点符号上,有许多需要留意的地方。

引号

LaTeX 的单引号 ‘ ’ 用 ` 和 ' 输入;双引号 “ ” 用 `` 和 ‘ ’ 输入(虽然 “ 也能表示双引号,但没有合适的单个符号用来表示前双引号,所以不常用在正文)。

“Please press the 'x' key.”

连字号和破折号

LaTeX 中有三种长度的 “横线” 可用:连字号(hyphen)、短破折号(en-dash)和长破折号(em-dash)。它们分别有不同的用途:连字号 - 用来组成复合词;短破折号 — 用来连接数字表示范围;长破折号 — 用来连接单词,与中文语境中的破折号用法类似。

daughter-in-law, X-rated\\
pages 13--67\\
yes---or no?

省略号

LaTeX 提供了命令 \Idots 来生生省略号,相对于直接输入三个点的方式更为合理。\Idots 和 \ dots 是两个等效的命令。

one, two, three, \Idots one hundred.

波浪号

我们在 2.3.3 小节中了解 ~ 命令,它可以用来输入波浪号,但位置靠顶端(~ 命令主要用作重音,参考下一小节)。西文中较少将波浪号作为标点符号使用,通常使用中文的全角波浪号(~)。

2.3.6 特殊西文符号与重音

LaTeX 支持用命令输入各种西欧语言的特殊符号和重音:

H\^otel, na\"\i ve, \'el\^eve,\\
sm\o rrebr\o d, !'Se\ norita!,\\
Sch\"onbrunner Schlo\ss{}
Stra\ss e

更多可用的符号和重音见表 2.1 。注意与 4.3.7 小节的数学重音区分开来。

前四行实际上都是带一个参数的命令。^o 也可以写作 ^{o},以此类推。

2.3.7 其他符号

LaTeX 预定义了其他一些文本模式的符号,部分符号可参考表 4.4

\P{} \S{} \dag{} \ddag{}
\copyright{} \pounds{}

\textasteriskcentered
\textperiodcentered
\textbullet

\textregistered{} \texttrademark

更多的符号多由特定的宏包支持。参考文献 [15] 搜集了所有在 TEX 发行版中可用的符号,使用时需要留意每个符号所依赖的宏包。

2.3.8 LaTeX 标志

我们见到的所有错落有致的 LaTeX 标志都是以下命令输入的:

2.4 文字强调

强调文字的方法,要么是添加下划线等装饰物,要么是改变文字的字体。

LaTeX 定义了 \underline 命令用来为文字添加下划线:

An \underline{underlined} text.

\underline 命令生成下划线的样式比较机械,不同的单词可能生成高低各异的下划线,并且无法换行。 ulem 宏包解决了这一问题,它提供的 \uline 命令能够轻松生成自动换行的下划线:

An example of \uline{some
long and underlined words.}

\emph 命令用来将文字变为斜体以示强调。如果在本身已经用 \emph 命令强调的文字内部嵌套使用 \emph 命令,内部则使用直立体文字:

Some \emph{emphasized words,
including \emph{double-emphasized}
words},are shown here.

如果需要用其他字体表示强调,可参考后文的 5.1.1 小节。

2.5 断行和断页

LaTeX 将文字段落在合适的位置进行断行,尽可能做到每行的宽度一致,并且单词艰巨匀称。文字段落和公式、图表等内容从上到下顺序排布,并在合适的位置断页,分割成匀称的页面。在绝大多数时候,我们无需自己操心断行和断页。但偶尔会遇到需要手工调整的地方。

2.5.1 单词间距和断行

在西文排版实践中,断行的位置尽可能选取在两个单词之间,也就是用户在源文件中输入的“空格”。这个“空格”通常生成一个间距,它会根据行宽和上下文自动调整,文字密一些的地方,单词间距就略窄,反之略宽。

我们可以使用字符 ~ 在合适的位置插入一个不会断行的空格(高德纳称之为 tie,“带子”),通常用在英文人民、图表名称等场景:

Fig.~2a\\
Donale~E. Kunth

2.5.2 手动断行和断页

如果我们确实需要手动断行,可使用如下命令:

\\{length}
\newline

它们有两点区别:一是\ 可以带可选参数 {length},用于在换行处向下增加垂直间距(见 5.2.5 小节),而 \newline 不带可选参数;二是 \ 也在表格、公式等地方用于分行,而 \newline 只用于文本段落中。

断页的命令有两个:

\newpage or \clearpage

通常情况下两个命令都能起到另起一页的作用,但有一些区别:一是在双栏排版中 \newpage 只起到另起一栏但作用;二是涉及到浮动体的排版上行为不同。后文的 3.9 节以及 5.3.3 小节会更详细地介绍相关内容。

有时候我们不满足于 LaTeX 默认的断行和断页位置,需要进行微调,就要用以下命令告诉 LaTeX 哪些地方适合断页,哪些地方不适合:

\linebreak[n] \nolinebreak \pagebreak[n] \nopagebreak[n]

以上命令都带一个可选参数,用数字 [n] 代表合适/不合适的程度,取值范围为0-4,不带可选参数时,缺省为4。比如 \linebreak [3] 意味着此处在断行时优先考虑:\nopagebreak 或 \nopagebreak [4] 意味着禁止在此处断页。

以上命令适合给出优先考虑断行断页/禁止断行断页的位置,但不适合直接拿来断行或断页,使用 \newline 或 \newpage 等是更好的选择。

2.5.3 断词

如果 LaTeX 遇到了很长的英语单词,仅在单词之间的位置断行无法生成宽度均匀的行时,就要考虑从单词中间断开。对于绝大部分单词,LaTeX 能够找到合适的断词位置,在断开的行尾加上字符-。

如果一些单词没能自动断词,我们可以在单词内手动使用 - 命令指定断词的位置:

I think this is: su\-per\-cal\-%
i\-frag\-i\-lis\-tic\-ex\-pi\-%
al\-i\do\-cious.