LaTeX 基本概念
这是关于\(\LaTeX\)基础概念的笔记,不涉及具体的\(\LaTeX\)语法细节,而是从宏观层面,包括历史和命令行用法等,来进一步理解 \(\TeX\) 和 \(\LaTeX\)。
\(\TeX\)语言
\(\TeX\)排版系统是 Knuth
发明的一种宏语言,提供了几百个类似\def
的基础指令用于排版,主要解决的是自动断行,以及公式布局等排版问题。\(\TeX\)语言的版本在升级到 3.0
之后,主版本号就不再发生变动,而是以 3.1,3.14,3.141
的形式在更新时不断接近 pi,这体现了\(\TeX\)语言的稳定性。
关于排版系统的基本介绍,有一篇博客可以参考: 排版引擎纵谈:程序员的视角
\(\TeX\)语言并不适合直接使用:
- 最早设计时不支持非 ASCII 编码,更不要说 Unicode 字符和中文支持等
- 字体需要额外配置,不能利用系统现有的字体
- 原始的几百个基础指令太繁琐又太简陋,需要考虑很多细节
后续有很多基于\(\TeX\)基本指令封装的宏集,让使用者可以忽略很多细节,例如在 \(\LaTeX\) 格式中的 center 环境是如下编写的(在 latex.ltx 文件中)
1 | \def\center{\trivlist \centering\item\relax} |
本质上是以一种非常底层的,类似 C 的宏的形式进行的指令扩展。典型的包括:
- \(\text{plain}\,\TeX\):发明者 Knuth 提供的一套极简的\(\TeX\)的宏
- \(\LaTeX\):使用最为广泛的一套宏,对科技文档的排版更加友好,它的当前版本为\(\LaTeX2_\varepsilon\),含义为尚未达到第三版
- \(\text{AMS}\,\TeX\):AMS 提供的一套宏集,可以在\(\LaTeX\)中导入相关的宏包进行等效使用
- \(\text{ConText}\):相比于\(\LaTeX\),更加自由灵活,也更复杂
- ...
这些宏集非常全面,被称为格式,例如\(\LaTeX\)格式,在各种主流格式的基础上,仍然支持使用宏进行进一步的扩展,这些在\(\LaTeX\)中称为宏包 package,在\(\text{ConText}\)中称为模块 module,扩展包只提供了一部分功能,因此只适合在某个格式的基础上进行使用。
极简的\(\text{plain}\,\TeX\)例子
1 | Hello, World |
极简的\(\LaTeX\)例子
1 | \documentclass{article} |
\(\TeX\)语言和\(\LaTeX\)格式的关系就像早期的 C 和 C++ 的关系,那时候 C++只是 C with class,C++之父在实现时只是做了一个转换:C++代码先经过处理将面向对象的部分改写为 C 的合法代码,然后传递给 C 的编译器。
\(\TeX\)编译器
\(\TeX\)语言只是规定了源文件的语法规范,相当于 C++11 之类的语法标准,但是具体通过源文件获得输出(dvi,ps,pdf 格式)还需要依赖编译器,就像 C/C++有多种主流编译器实现(gcc/msvc/clang),\(\TeX\)也是如此。 而且和 C++ 一样,对相同的源代码使用不同编译器编译,完全可能得到不同的输出,有时还会出现某个编译器编译失败的情况。
\(\TeX\)语言的实现最早是由发明者 Knuth 写的一个\(\TeX\)编译器(又称为\(\TeX\)引擎),后续又有很多或继承或独立的实现,典型的\(\TeX\)编译器包括:(这里为了区分,对于编译器和编译命令不再采用斜体)
- (Knuth)TeX:发明者 Knuth 的原版\(\TeX\)编译器,现在几乎不使用
- \(\varepsilon\)-TeX:相比于原始 Tex 提供了扩展功能,是事实上的标准\(\TeX\)编译器,后面的几个编译器都是基于它开发的
- pdfTeX:西文期刊论文的排版最常用的,支持直接生成 pdf,默认只支持西文字符,项目开发者已经转向了 LuaTeX
- XeTeX:支持 Unicode,支持直接调用系统字体的编译器,中文排版时最建议使用
- pTeX:主要是日本人开发的,包括后续改进的 p 系列\(\TeX\)编译器
- LuaTeX:支持 Lua 扩展,原生支持 Unicode 和系统字体的编译器,作为 pdfTeX 的正统后继者,仍然在开发中,并没有广泛采用,中文排版也可以使用(但是速度相比 XeTex 慢不少)
\(\TeX\)编译器支持接收不同的源文件格式作为输入,例如\(\text{plain}\,\TeX\)或\(\LaTeX\),需要使用参数指定。\(\TeX\)编译器在早期设计时的输出为 dvi 文件或 ps 文件,如果需要 pdf 文件还需要进行一次转换,现代的主流编译器都可以直接产生这三种输出文件(pdf,dvi,ps),建议输出 pdf 文件。
在命令行直接使用\(\TeX\)编译器时,可以使用选项指明源文件的格式和输出文件格式,例如调用 pdftex 编译\(\LaTeX\)格式的源文件,要求输出为 pdf
1 | pdftex -fmt=latex -out-format=pdf main.tex |
如果不使用-fmt
选项,源文件可能会被视作\(\text{plain}\,\TeX\)格式,如下的命令在编译时会出现错误,无法识别源文件中相关的命令
1 | pdftex main.tex |
使用 pdflatex 则默认指定\(\LaTeX\)格式,直接编译即可,输出的是 pdf 文件
1 | pdflatex main.tex |
注意:这些编译命令主要适配的是Linux,在Windows上有很多潜在问题,比如不支持
.\main.tex
的写法,必须使用Linux风格的文件分隔符./main.tex
。因为宏通常以\
开头,使用\
可能产生很多问题。文件名和路径名最好不要含有中文。
不同编译器产生的 pdf
文件只是内容看起来一样,实际有很多区别,例如一些排版细节,pdf
文件的实际大小也可能有很大差异。
可以通过查看PDF的属性中的PDF Producer
来检查实际采用的编译器,例如(版本号可能不同)
pdfTeX-1.40.25
对应pdftex
xdvipdfmx (20220710)
对应xetex
LuaTeX-1.16.0
对应luatex
\(\TeX\)编译命令
将编译器和输入源文件格式,输出文件格式组合,就可以得到不同的具体编译命令:(通常直接使用的是某个编译命令而非编译器)
etex
:pdfTex 编译器,输入\(\text{plain}\,\TeX\)格式,输出 dvi 文件latex
:pdfTex 编译器,输入\(\LaTeX\)格式,输出 dvi 文件pdftex
:pdfTex 编译器,输入\(\text{plain}\,\TeX\)格式,输出 pdf 文件pdflatex
:pdfTex 编译器,输入\(\LaTeX\)格式,输出 pdf 文件xetex
:XeTex 编译器,输入\(\text{plain}\,\TeX\)格式,输出 pdf 文件xelatex
:XeTex 编译器,输入\(\LaTeX\)格式,输出 pdf 文件luatex
:LuaTex 编译器,输入\(\text{plain}\,\TeX\)格式,输出 pdf 文件lualatex
:LuaTex 编译器,输入\(\LaTeX\)格式,输出 pdf 文件
(参考 lshort-zh-cn 教程)
这几种就是目前最常见的编译器选项,显然*latex
编译命令都是默认支持\(\LaTeX\)格式的,并且都被 Overleaf
平台支持, 其中的xelatex
和lualatex
支持 Unicode
编码和中文,后者支持添加 Lua
脚本进行扩展,但是测试发现lualatex
编译明显偏慢。
关于Unicode编码的补充:有时可能从别的地方复制得到一些和常用字符很相似的Unicode字符,这可能直接导致
pdflatex
编译失败,xelatex
和lualatex
更可能因为无法显示字符而将其忽略掉。
推荐的编译器选择如下:
- 西文:
pdflatex
(考虑到期刊论文排版的要求) - 中文和中英文混合:
xelatex
有的编译软件(例如TeXworks等)支持通过源文件头部的魔法注释指定采用的编译器(还支持提供其它信息),例如
1 |
|
\(\TeX\)发行版
发行版就是对\(\TeX\)编译器,以及其他常用宏包,辅助工具的完整封装,使用者通常是下载一整个发行版,而非单独配置。常见的发行版包括:
- Tex Live:目前唯一推荐的最主流的发行版,多平台支持,在 MacOS 上是基于 Tex Live 的定制版本 MaxTex
- MiKTex:只支持 Windows
- CTex:在早期为了支持中文,基于 MiKTex 定制的一个 Windows 上的发行版,现在不推荐使用,同时不推荐的是CJK宏包。(注意还有名为 ctex 的宏包,和这里的发行版不是一回事)
这些发行版自身都附带了一个简单朴素的\(\LaTeX\)编辑器 TeXworks,更专业的\(\LaTeX\)编辑器是 Tex Studio 和 WinEdt, 也可以使用通用编辑器例如 vim/nvim 和 VSCode 加上 LaTeX 插件进行使用。
发行版通常都提供了管理宏包的工具,尽量使用它们提供的工具来下载和管理宏包,而非手动下载。 就像Anaconda之于Python, \(\TeX\)发行版已经自带了数千个常用或不常用的宏包,我们通常都不需要考虑宏包的下载更新等细节。 如果希望使用更新的发行版,推荐的做法不是升级,而是直接卸载旧版,然后安装新版。
在Windows上安装Tex Live时,如果用户主目录含有中文,或者安装位置含有中文,都可能导致安装失败。 因为主目录更改非常麻烦,可选的解决办法是在安装时重定义相关环境变量,使Tex Live绕开主目录。
\(\LaTeX\) 文档类
\(\LaTeX\)源代码通常以声明一个文档类开头
1 | \documentclass[⟨options⟩]{⟨class-name⟩} |
常见的文档类包括:(篇幅从小到大)
- atricle
- report
- book
使用例如
1 | \documentclass{article} |
此外还有 beamer 这种特殊的幻灯片形式的文档类。
如果有很多定制的格式需求,可以自行定制一个文档类(*.cls
),自行设置各种排版细节,但是通常都是不需要的。
\(\LaTeX\)中文支持
ctex宏包是当前推荐的中文支持方案,它针对不同平台和不同编译器选择了不同的底层中文支持方案(CJK,xeCJK,luatexja等),让使用者可以忽略这些底层细节。
为了使用ctex支持中文,在源文件中有两种处理方法:
第一种方法是导入 ctex 宏包(注意不是 CTex 发行版)
1
2
3\documentclass{article}
\usepackage[UTF8]{ctex}第二种方法是使用中文文档类:ctex 直接将 article 等基本文档类和 ctex 宏包以及其他宏包进行组合,并且进行了很多适合中文文档的细节调整(例如中文标点,中文间空格的处理等),提供 ctexart,ctexrep,ctexbook,ctexbeamer等中文文档类,导入时可以指定 UTF-8 编码也可以省略(默认就是UTF-8编码,并且对于XeLaTex和LuaLaTex是强制UTF-8编码)
1
2
3\documentclass{ctexart}
\documentclass[UTF8]{ctexart}
两种方法并不等价,有很多细微区别,建议选择方式为:
- 轻度使用中文(即中英文混用)建议使用第一种;
- 重度使用中文(即纯中文文档)则建议使用第二种。
此外,还需要保证:
- 源代码使用 UTF-8 编码保存
- 使用 xelatex(或 lualatex)编译
虽然 ctex 宏包和文档类保留了对 GBK 编码以及
pdflatex
编译命令的兼容,但并不推荐这样做。
在不同的编译器之间,实际有很多细微的差异,例如关于中文空格处理的细节: 对于中文字符后的空格,以及中文和西文字符之间的空格,XeLaTex 会直接忽略,但是 LuaLaTex 不会忽略,但是对于连续空格只显示一个。
除了编译器的差异,在不同的平台之间也有很多细微的差异(只考虑xelatex),例如默认使用的中文字体:
- Windows平台默认的宋体是SimSun
- Linux平台(包括Overleaf等在线平台)默认的宋体是FandolSong
对于不同平台得到的pdf,实际上在中文标题中就可以观察到明显的差异,这就是使用了不同的字体导致的。
如果平台上安装了相应的中文字体,也可以手动更改,例如使用下面的命令更改中文的正文字体
1
2\setCJKmainfont{FandolSong}
\setCJKmainfont{SimSun}
在没有特殊需求时,不太需要关注或修改实际的中文字体,用默认的即可,对于最终提交的正式版采用Windows平台的SimSun字体更符合相应的规范。
补充
MathJax/KaTex
在网页上也有渲染数学公式的需求,而网页的排版系统主要是基于 HTML+CSS+JS 的,和 Tex 的排版功能是不同的,一个最明显的不同是,网页的排版通常没有分页和首行缩进的需求。
在涉及到数学公式的部分,网页上的渲染实现是调用符合 Tex 规范的 JS 引擎,例如 MathJax 或 KaTex,通过导入这些开源脚本来支持在网页上嵌入 LaTeX、MathML 或 AsciiMath 标记,并将其渲染为数学公式,其中 KaTex 更加轻量级,但是对复杂公式渲染效果还是 MathJax 更好。
至于 Markdown,只是简化的 HTML,使得样式和文本进一步分离,适合快速完成在网页中呈现的文档,例如博客等,对它的渲染还是转换为 HTML+CSS+JS 的,因此在 Markdown 中也可以使用一些 HTML 语句,Markdown 对 Tex/LaTex 的支持也是继承自 HTML+CSS+JS 的。
文件类型
在\(\LaTeX{}\)使用过程中,通常需要如下文件:(以及插入的图片文件)
- .tex 源文件
- .bib 参考文献
对于高度个性化定制的情形,还需要如下文件:
- .cls 文档类文件,要求文档类名称和文件名一致
- .sty 宏包文件,要求宏包名称和文件名一致
- .bst 参考文献格式模板(Bibtex)
- .bbx, .cbx 参考文献格式和引用格式模板(Biblatex)
在编译过程中还产生了很多乱七八糟的辅助文件/缓存文件,其中绝大部分都是可以在编译完成后删除的:
- .aux 交叉引用和标签的辅助文件,可用于下一次编译
- .log 编译日志,可以用来调试
- .toc 目录信息文件,用于生成目录
- .lof 图表信息文件,用于生成图表目录
- .lot 表格信息文件,用于生成表格目录
- .out hyperref输出文件,记录书签和超链接等,用于生成PDF
- .cpt 脚注文件,记录了脚注信息
- .fdb_latexmk 记录了latexmk在编译过程中生成的文件及其依赖关系
- .fls 日志文件,记录了编译过程中生成的所有文件,以及它们的依赖关系
- .xdv XeTex产生的二进制文件,用于转换为PDF
- .synctex.gz (重要)源文件和PDF之间的双向索引
- .run.xml 参考文件需要的数据
- .bbl 参考文献记录文件
- .blg 参考文献日志
- .bcf 参考文件相关信息
常见宏包
- 中文支持
- ctex: 中文支持宏包
- 数学相关宏包
- amsmath: 提供数学环境和命令,是数学排版的基础。
- amssymb: 提供丰富的数学符号。
- amsfonts: 包含各种数学字体。
- amsthm: 支持定义数学定理环境。
- mathrsfs: 提供特殊的数学花体字母。
- 数学符号和公式排版宏包
- bm: 提供在数学中使用粗体命令。
- mathtools: 对 amsmath 的扩展,增强数学公式排版功能。
- 图片和图表相关宏包
- graphicx: 插入图片的核心宏包。
- caption: 定制浮动体标题。
- subcaption: 支持在一个浮动体中放置多个子图。
- tikz: 创建矢量图形。
- float: 提供更多浮动体位置控制选项。
- 文档格式和排版相关宏包
- fancyhdr: 定制页眉页脚。
- footmisc: 控制脚注样式。
- titlesec: 定制章节标题格式。
- titletoc: 定制目录格式。
- indentfirst: 使每一章节的第一个段落也缩进。
- geometry: 调整页面布局和页边距。
- 文档链接、交叉引用和代码块相关宏包
- hyperref: 添加超链接、交叉引用和书签。
- cleveref: 提供更智能的交叉引用。
- listings: 用于插入代码环境。
- algorithm2e: 用于插入算法环境。
- 表格相关宏包
- array: 提供扩展的表格环境。
- booktabs: 创建高质量表格的命令。
- longtable: 允许创建跨页的长表格。
- tabularx: 提供可伸缩的表格环境。
- multirow,multicol: 创建表格中的多行和多列单元格。
- threeparttable: 提供表格注释功能。
- enumitem: 定制列表环境。
- 其他宏包
- xcolor: 用于设置颜色。
- framed: 设置底色。
- braket: 用于重定义括号。
- anyfontsize: 允许使用任意大小的字体。
- nag: 用于检查是否使用了过时的宏包或命令。