本系列旨在详细介绍 LaTeX 的使用,主要内容参考自著名的 「The Not So Short A Introduction to LaTeX」(Version 6.3)。LaTeX 是一种排版系统,非常适用于生成高印刷质量的科技和数学类文档,其使用 TeX 作为格式化引擎。本介绍将分为以下几部分:
- 第一章介绍 LaTeX 文档的基本结构,包括一点 LaTeX 的发展史
- 第二章介绍排版文档的细节,包括大部分基本的 LaTeX 命令和环境
- 第三章解释如何使用 LaTeX 排版公式
- 第四章解释索引、参考文献生成以及关于创建 PDF 的要点
- 第五章介绍如何使用 LaTeX 创建图形
- 第六章介绍如何对 LaTeX 产生的标准文档格式进行自定义
1.1 LaTeX 发展简史
TeX 是由 Donald E. Knuth 创造的一种计算机程序,其目标是对文本和数学公式进行排版。我们今天使用的 TeX 于 1982 年发布,并在 1989 年进行了一些改进以支持 8 字节字符和多语言。TeX 的特点是非常的稳定,可以运行于不同种类的计算机上,并且几乎没有 bug。TeX 的版本号收敛于 ,现在为 3.141592653。TeX 的发音为 “Tech”,在 ASCII 环境下写作 「TeX」(即本文中的形式)。
LaTeX 通过一个预先定义好的专业页面设置,来帮助作者以较高的印刷质量排版并打印其工作。LaTeX 由 Leslie Lamport 编写,使用 TeX 作为其排版引擎。LaTeX 的发音为 “Lay-tech” 或 “Lah-tech”,在 ASCII 环境下写作 「LaTeX」。本文介绍的是整合了不同补丁的 LaTeX 2e 版本,发音为 ”Lay-tech two e“,写作 「LaTeX2e」。
1.2 LaTeX 概览
1.2.1 LaTeX 的作用
我们可以通过图书出版的过程来介绍 LaTeX 与 TeX 的作用。为了出版其作品,「作者」需要将手稿提交给一家出版公司,公司的一位「图书设计者」需要决定该文章的版式,例如栏宽、字体、缩进等。图书设计者需要在手稿中加入其说明,然后将添加完版式说明的手稿交给一位「排版者」,由他根据排版说明对文章进行实际的排版。
在 LaTeX 环境中,LaTeX 扮演了图书设计者的角色,TeX 则扮演了排版者的角色。不过 LaTeX 只是一个程序,并不能独立地决定文章的排版,因此作者需要提供更多的信息来描述其作品的逻辑结构,以帮助 LaTeX 进行排版设计,这些信息以 「LaTeX 命令」 的形式写入文章之中。
上述方式与 MS Word 或 LibreOffice 等现代化文字处理器中的「所见即所得」(WYSIWYG)方式存在着较大区别。在这些应用中,作者可以在向计算机输入文本的同时,交互式地指定文档的版式,并立即看到最终的排版效果。而使用 LaTeX 时,通常不能够在输入文本时看到最终的输出,需要基于 LaTeX 进行编译后才能预览输出效果。
1.2.2 优势与劣势
与普通文字处理器相比,LaTeX 具有如下「优势」:
- 可以生成更加专业的版式(注重可读性与可理解性)
- 数学公式的排版更加方便
- 用户可以通过简单易懂的命令指定文档的逻辑结构,而(几乎)不用接触实际的版式
- 可以轻松生成复杂的结构,例如脚注、参考文献、目录等
- 免费提供的大量第三方插件,用于各种各样的排印任务
- 鼓励作者去撰写结构化的文本(以迎合 LaTeX 的工作原理)
- LaTeX 的核心 TeX 几乎可以在任何硬件平台上运行
当然,LaTeX 也存在一些「劣势」,例如:
- 设计一个全新的版式比较困难且耗时(在已有版式上微调比较方便)
- 上手有一定难度(初始学习曲线较高)
- 很难撰写无结构的与未组织的文档
1.3 LaTeX 源文件
LaTeX 的输入是一个纯文本文件,其包括文档的内容本身,以及用于指导 LaTeX 排版的相关命令。下面将介绍 LaTeX 源文件中的几个重要元素。
1.3.1 空白字符
在 LaTeX 中,将空格键(blank)和制表符(tab)等空白字符视作相同的「空白」(space)。「多个连续的空白字符」等同于一个空白字符。每行开始的空白字符将被忽略,而单个换行符(回车)也将被视为空白距离。为了区分段落,LaTeX 使用一个「空行」来结束当前段落,如下图所示。注意多个空行会被视为一个空行。
1.3.2 特殊字符
下面这些字符是 LaTeX 的保留字符,它们或在 LaTeX 中有着特殊的意义,或不一定包含在所有的字库中。如果直接在文本中使用这些字符,其不会出现在排版结果中,还可能导致 LaTeX 做一些你不希望发生的事情。
代码语言:javascript复制# $ % ^ & _ { } ~
我们可以通过添加「反斜线」来使上述字符在文本中出现。
注意反斜杠符号本身不能通过添加反斜线得到,需要通过 textbackslash
命令得到,而 \
在 LaTeX 中表示「换行」(另起一行,与划分段落有区别)。其他的一些符号可以通过数学公式中的特殊命令或重音符号(如 u{o}
)得到。
1.3.3 LaTeX 命令
LaTeX 命令是「大小写敏感」的,并且有如下两种格式:
- 以一个反斜线
开始,接一个只包含「字母」的命令名。命令名后的任何非字母字符标志着该命令的结束
- 由一个反斜线和「一个」非字母字符组成
注意:很多命令存在「星号」变种,即在命令名后添加一个星号,使该命令起到与原命令不同的作用。
LaTeX 会忽略所有命令后面的空白字符,如果我们需要在命令后面添加一个空白,则需要使用一个空的大括号 {}
加一个空格,或是一个特殊的空白距离命令,如下图所示:
有些命令需要设置参数,通过在命令名后添加大括号 {}
实现,而有些命令则可以设置可选参数,通过在命令名后添加方括号 []
来实现:
command[optional parameter]{parameter}
1.3.4 注释
当 LaTeX 在处理源文件时,如果遇到一个「百分号」字符 %
,则会忽略当前行该字符之后的文本、分行符以及所有下一行开始的空白字符(默认换行会转化为一个空白)。我们可以利用该符号为文档添加注释,其不会出现在排版后的文档中。%
符号也可以用来分割较长的输入文本,该文本不允许有换行或空白。
对于较长的注释,可以使用 verbatim
包所提供的 comment
环境,通过在文档的序言部分添加命令 usepackage{verbatim}
实现。注意该命令在数学公式等复杂环境中不可用。
1.3.5 源文件结构
当 LaTeX 处理一个源文件时,其期望去遵循一个特定的结构,因此每个源文件都需要通过命令指定其类型:
代码语言:javascript复制documentclass{...}
该命令定义了所写文档的「类别」。之后我们可以继续添加改变文档样式的命令,或是载入包含新特性的宏包。载入宏包的命令为:
代码语言:javascript复制usepackage{...}
当所有的设置工作完成后,我们可以通过如下命令开始输入正文:
代码语言:javascript复制begin{document}
在 documentclass
和 begin{document}
之间的部分也被称为「序言」(preamble)。现在我们可以输入正文,并混合相关的 LaTeX 指令。在文档的最后,我们添加如下指令:
end{document}
来结束当前文档。该命令之后的内容将被忽略。下图给出了一个期刊论文的 LaTeX 源文件:
1.4 一个典型的命令行过程
本节将介绍在基于文本的系统下使用 LaTeX 处理源文件的过程。
- 创建 LaTeX 源文件。文件需要为 ASCII 编码(对于原始 LaTeX 来说),后缀名为
.tex
。 - 打开命令行,
cd
到源文件所在文件夹,执行如下命令来启动 LaTeX(这里选择的是 XeLaTeX 引擎),编译成功后会生成一个 pdf 文件(目录和引用可能需要多次编译):
xelatex foo.tex
1.5 文档布局
本节将详细介绍 LaTeX 源文件中的各部分内容。
1.5.1 文档类型
当处理一个源文件时,LaTeX 需要了解的首个信息就是文档的「类型」,通过 documentclass
命令来指定:
documentclass[options]{class}
其中 class
参数指定文档的类型,下表列出了本文所涉及的文档类型:
Class | 解释 |
---|---|
article | 文章类型,用于科学期刊、报告、技术文档等的排版 |
proc | 会议类型,基于文章类型构建 |
minimal | 极简类型,只有页码和基本字体 |
report | 报告类型,用于长报告、小型书籍、学位论文等的排版 |
book | 书籍类型,用于书籍排版 |
slides | 幻灯片类型,用于幻灯片排版 |
除此之外,LaTeX 2e 还提供了其他的文档类型,例如信件。option
参数可以用于定制特定文档类型的版式,多个选项需要用逗号隔开,下表列出了标准文档类最常用的一些选项:
Option | 解释 |
---|---|
10pt, 11pt, 12pt | 设置文档中主要字体的大小,默认为 10pt |
a4paper, letterpaper, … | 定义纸张的大小,默认为 letterpaper |
fleqn | 将数学公式左对齐,而不是中间对齐 |
leqno | 将数学公式的编号放在左侧,而非右侧 |
titlepage, notitlepage | 设置文档标题后是否另起一页,article 默认不起,book 和 report 则默认起 |
onecolumn, twocolumn | 指定排版方式为单列或双列 |
twoside, oneside | 指定排版方式为双面或单面(如页眉的差别),article 和 report 默认为单面,book 默认为双面,注意这一选项只会决定文档的式样,并不会通知打印机执行双面打印 |
landscape | 将版式改为横向排版 |
openright, openany | 定义新的章节是起始于右边页(针对双面排版而言)还是下一可用页。article 类型没有章节概念,report 默认为下一可用页,book 则默认为右边页 |
下面给出一个指定源文件文档类型的实例:
代码语言:javascript复制documentclass[11pt,twoside,a4paper]{article}
上述命令指定 LaTeX 用将文档排版为「文章」类型,字体大小为 「11」 磅,排版为适合在 「A4」 纸上「双面」打印的排版。
1.5.2 宏包
当我们在排版文档时,可能会发现有时候基本的 LaTeX 不能解决一些问题,例如插入图片、彩色文字或是源代码。这时我们需要通过「宏包」(package)来增强 LaTeX 的能力,调用宏包通过如下命令实现:
代码语言:javascript复制usepackage[options]{package}
其中 package
为宏包名,options
为触发宏包的特殊功能的关键词列表。该命令应该放置于文档的序言中。LaTeX 2e 的基本发行版本中预装了大量的宏包。我们也可以手动安装宏包甚至自定义宏包。
1.5.3 页面风格
LaTeX 支持三种预定义的页眉/页脚组合,称之为「页面风格」,通过如下命令定义:
代码语言:javascript复制pagestyle{style}
style
参数指定使用哪种页面风格,下表列举出了不同风格的具体区别。
Style | 解释 |
---|---|
plain | 默认风格,页眉为空,页脚为居中的页码 |
headings | 页眉由当前的章节标题和页码组成,页脚为空 |
empty | 页眉、页脚均为空 |
我们也可以通过如下命令来仅改变当前页面的风格:
代码语言:javascript复制thispagestyle{style}
此外,我们也可以自定义页眉和页脚,此处不作赘述。
1.6 各类 LaTeX 文件
在排版文档时,除了源文件外,我们还可能遇到各种具有不同的扩展名的文件。下表列出了部分使用 LaTeX 时可能会遇到的扩展名:
扩展名 | 解释 |
---|---|
.tex | LaTeX 源文件,通过 latex 命令编译(或其他特定编译器) |
.sty | LaTeX 宏包文件,通过 usepackage 加载(通过 ins 和 dtx 编译得到) |
.dtx | 文档化 TeX 文件,为宏包发布的主要格式,编译可得到宏包代码 |
.ins | 相应的 dtx 文件的安装文件,使用 LaTeX 对 ins 文件进行处理即可解包 dtx 文件 |
.cls | 定义文档样式的类文件,通过 documentclass 命令选择 |
.fd | 字体描述文件,用于向 LaTeX 描述新字体 |
下面这些文件则会在执行 LaTeX 编译后生成:
扩展名 | 解释 |
---|---|
.dvi | 设备无关文件,为经典 LaTeX 的编译结果,可以通过 DVI 预览器查看。一些特定的编译器会直接生成 pdf |
.log | 记录了上次编译运行时的详细信息 |
.toc | 存储所有的章节标题,会在下次编译运行时生成目录 |
.lof | 与 toc 类似,用于生成图片目录 |
.lot | 与 toc 类似,用于生成表格目录 |
.aux | 另一个用来向下次编译传递信息的辅助文件,例如交叉引用信息 |
.idx | 用来存储所有索引词条的文件,需要使用 makeindex 命令处理 |
.ind | 处理后的 idx 文件,可以在下次编译时整合进文档 |
.ilg | makeindex 命令产生的日志文件 |
1.7 大型项目
当处理大型文档时,我们可能需要把源文件分成多个部分。LaTeX 提供了几条命令来帮助你做到这一点:
代码语言:javascript复制include{filename}
在「正文」部分使用该命令可以插入另一个名为 filename.tex
的文件中的内容,注意 LaTeX 会另起一页来插入内容。
第二条命令可以在「序言」中使用,可以告诉 LaTeX 只读入某些特定的文件:
代码语言:javascript复制includeonly{filename,filename,…}
执行完该条命令后,在所有的 include
命令中,只有 includeonly
中列出的文件才会被执行。因为 include
命令引入的文件会另起一页,所以去除某些引入不会对整体排版产生影响。
有时我们可能不想另起一页,这时可以使用下述命令:
代码语言:javascript复制input{filename}
该命令只是简单地将指定文件包括进来,并没有其他限制。
另一方面,我们可以使用 syntonly
宏包来快速检查文档,该命令只会检查文档中命令的语法和使用,不会生成任何文件,速度很快,能够节省完整编译所需要的大量时间。使用方法如下:
usepackage{syntonly}
syntaxonly
想生成文件的话只需要把第二行注释掉即可。