这是关于\(\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
2
\def\center{\trivlist \centering\item\relax}
\def\endcenter{\endtrivlist)

本质上是以一种非常底层的,类似 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
2
Hello, World
\bye

极简的\(\LaTeX\)例子

1
2
3
4
5
6
7
8
9
10
11
12
13
\documentclass{article}

\begin{document}

Hello, this is a simple \LaTeX{} document.
Here is an inline equation: $E=mc^2$, which is Einstein's famous equation.
And here is a displayed equation:

\[
\int_{0}^{\infty} e^{-x^2} \, dx = \frac{\sqrt{\pi}}{2}
\]

\end{document}

\(\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\)也是如此。

\(\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

\(\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 平台支持,其中的xelatexlualatex支持 Unicode 编码和中文,后者可以添加 Lua 脚本进行扩展,这几种也是目前最常见的编译器选项,无脑的选择如下:

  • 西文:pdflatex
  • 中文:xelatex
  • 中英文混合:xelatex

\(\TeX\)发行版

发行版就是对\(\TeX\)编译器,以及其他常用宏包,辅助工具的完整封装,使用者通常是下载一整个发行版,而非单独配置。常见的发行版包括:

  • Tex Live:目前唯一推荐的最主流的发行版,多平台支持,在 MaxOS 上是基于 Tex Live 的定制版本 MaxTex
  • MiKTex:只支持 Windows
  • CTex:在早期为了支持中文,基于 MiKTex 定制的一个 Windows 上的发行版,现在不推荐使用,同时不推荐的是 CJK 宏包,但是注意还有名为 ctex 的宏包,那个仍然推荐在中文使用

虽然某些发行版支持中文,但是为了兼容性考虑,所有的路径和文件名中都不要出现中文。

这些发行版自身都附带了一个简单的\(\LaTeX\)源代码编辑器 TeXworks,更专业的编辑器是 Tex Studio 和 WinEdt,也可以通过通用编辑器例如 VSCode 加上插件使用。发行版通常都提供了可以下载宏包的工具,尽量使用它们提供的工具来管理和下载宏包,而非手动下载。

\(\TeX\)中文支持

\(\LaTeX\)文档通常以声明一个文档类开头

1
\documentclass[⟨options⟩]{⟨class-name⟩}

常见的文档类包括:(篇幅从小到大)

  • atricle
  • report
  • book

有很多格式需求时可以自行定制一个文档类(*.cls),但是通常都不需要。此外还有 slides 幻灯片。例如

1
2
3
4
5
\documentclass{article}

\documentclass[12pt]{article}

\documentclass[11pt,twoside,a4paper]{article}

为了支持中文,目前在源文件中推荐两种处理方法:

  • 第一种方法是导入 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针对不同平台和不同编译器选择了不同的底层中文支持方案(CJK,xeCJK,luatexja等), 包括默认中文字体,中文标点,中文间空格的处理等细节, 这里关注Windows和Linux(包括本地的WSL2,以及远程的Overleaf平台)的默认字体,并且限于使用XeTeX编译,例如

  • Windows平台默认的宋体是SimSun
  • Linux平台默认的宋体是FandolSong

得到的pdf在标题中可以观察到明显的不同,这就是使用了不同的字体导致的。

如果平台上找得到相应的字体,也可以手动更改,例如使用下面的命令更改中文的正文字体

1
2
\setCJKmainfont{FandolSong}
\setCJKmainfont{SimSun}

在没有特殊需求时,不太需要关注或修改实际的中文字体,用默认的即可,对于最终提交的正式版采用Windows平台的SimSun字体。 一个值得注意的细节:对于中文字符后的空格,以及中文和西文字符之间的空格,XeLaTex会忽略,但是LuaLaTex不会忽略,但是会将连续空格只显示一个。

补充

latexmk

在复杂情况下,由于存在交叉引用和文献引用,仅仅执行一次编译是不够的,需要进行多次编译并且搭配 bibtex 编译,针对这种复杂的情况,除了简单重复编译,还有一种值得介绍的工具是 latexmk,可以理解为针对\(\LaTeX\)定制的 make,它基于 Perl 实现,另一种类似的处理多次编译的工具是 MikTex 的 textify,如果需要额外的个性化配置,可以在当前目录下添加.latexmkrc 或 latexmkrc 文件。(但是和 make 不同,即使没有配置文件,latexmk 也可以自动运行地很好)

latexmk 会根据源文件自动选择合适的编译命令,当然也可以具体指定。latexmk 会自动执行多次编译。编译完成后不退出,处于等待状态,监视源文件,一旦有更新,会实时编译,并刷新 PDF 阅读器,编译生成的所有文件会输出到指定的目录。

事实上,Overleaf 的编译命令就是基于 latexmk 的,例如latexmk -xelatex ...

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: 用于检查是否使用了过时的宏包或命令。