惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Schneier on Security
Schneier on Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Attack and Defense Labs
Attack and Defense Labs
H
Hacker News: Front Page
Google DeepMind News
Google DeepMind News
雷峰网
雷峰网
C
CXSECURITY Database RSS Feed - CXSecurity.com
Cisco Talos Blog
Cisco Talos Blog
T
Tenable Blog
G
Google Developers Blog
A
About on SuperTechFans
The Cloudflare Blog
S
Securelist
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
C
Cisco Blogs
H
Hackread – Cybersecurity News, Data Breaches, AI and More
aimingoo的专栏
aimingoo的专栏
云风的 BLOG
云风的 BLOG
Forbes - Security
Forbes - Security
腾讯CDC
Application and Cybersecurity Blog
Application and Cybersecurity Blog
V
Vulnerabilities – Threatpost
IT之家
IT之家
博客园_首页
P
Proofpoint News Feed
P
Privacy & Cybersecurity Law Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Project Zero
Project Zero
月光博客
月光博客
NISL@THU
NISL@THU
爱范儿
爱范儿
S
Secure Thoughts
K
Kaspersky official blog
Security Latest
Security Latest
T
Tailwind CSS Blog
博客园 - Franky
D
Darknet – Hacking Tools, Hacker News & Cyber Security
TaoSecurity Blog
TaoSecurity Blog
The GitHub Blog
The GitHub Blog
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog RSS Feed
S
SegmentFault 最新的问题
H
Help Net Security
T
Tor Project blog
L
LINUX DO - 热门话题
S
Security @ Cisco Blogs
N
News and Events Feed by Topic
O
OpenAI News
S
Schneier on Security

Random Thoughts

LLM 训练与推理的基本理解 昨日的世界不再重来 Magic Brush - 画出你自己的产品宇宙 写在 AI Coding 奇点之后 尼泊尔布恩山小环线纪行 2025 投资组合年报 三十而笠 我的 8 年职业生涯回顾 我的颈椎病康复之旅 - 关于选择的故事 熊野古道中边路纪行 新加坡旅居三年再回首 高加索三国 - 阿塞拜疆行记 2024 投资组合年报 重新思考 Go:了解程序在线上是如何运行的 欧游散记 —— 环勃朗峰之旅 欧游散记 —— 特摩索斯古城 重新思考 Go:Channel 不是「消息队列」 重新思考 Go:Slice 只是「操作视图」 那一天,我决定踏出一步 True Story 少数价值 A Snapshot of Myself - 2021 RPC 漫谈: 连接问题 RPC 漫谈:序列化问题 RPC 漫谈: 限流问题 科学,技术与工程 Pond: Golang 通用对象池 Golang for-range 内部实现 Golang Interface 内部实现 真理的有限性 Golang rand 库锁竞争优化 Meaningless or Meaningful 分布式文件系统的演化 从动物森友会聊主机游戏联机机制 创业公司的文化 伊朗见闻录 NodeJS 内存泄漏检测与定位 设计实现高性能本地内存缓存 Travel Map Linux I/O 栈浅析 SSD 背后的奥秘 什么是真正的编程能力 沉默与反沉默的理由 命令行里的设计艺术 自由意志下的选择 学习思维方式而非学习观点 从程序到人 —— 情头配对助手的前世今生 即刻多端实时通信实践 朝鲜 —— 小国寡民的主体思想实践 使用 Surge 提升多网络环境下的流畅开发体验 Kafka 的设计与实践思考 欧游散记 —— 民主专制下的德国 欧游散记 —— 维也纳 欧游散记 —— 西班牙 欧游散记 —— 德国国会大厦 社会矛盾讨论统一框架的一种可能性 欧游散记 —— 伪君子布拉格 Lemon : Koa 风格的 Python 异步 Web 框架 Golang : Make Programming Happy Again Podcast 闲言碎语 Kubernetes 中使用 API Gateway 替代 Ingress ElasticSearch 最佳实践 blog.joway.io Presentations
一份其实好吃的 LaTeX 入门餐
Joway · 2018-05-13 · via Random Thoughts

最近在使用 LaTeX 写作,发现虽然这个「软件」使用简单,设计简约,但使用起来却并不是非常的容易,加上其生态非常芜杂,各种宏包和发行版层出不穷,中文世界鲜有文章系统地去讲他们之间的关系。这篇文章不会去介绍其基本用法,而是以一个更为宏观的角度,旨在厘清 TeX 排版系统的来龙去脉,以及其生态圈中各个项目的作用与关系。或有纰漏,还望雅正。

标题致敬 Liam Huang 老师很流行的一篇文章 《一份其实很短的 LaTeX 入门文档》

什么是 Tex

TeX 是高德纳教授在70年代末编写 The Art of Computer Programming 时,对当时的计算机排版技术感到无法忍受,因而决定自己开发一个高质量的计算机排版系统 TeX 。

TeX 的版本号有别于当下流行的 x.x.x,而是以圆周率 π 的形式。当前的版本号是 3.14159265 ,所以下一个版本是 3.141592653 。最终无限收敛到 π ,代表了 TeX 不断追求完美的理想。而事实上 TeX 也的确堪称「完美」,高德纳甚至曾悬赏任何发现 Bug 的人,每一个漏洞的奖励金额从2.56美元开始,之后每发现一个 Bug 都会翻倍,直至327.68美元封顶。

TeX 的输出文件被称为 DVI(Device Independent) 文件,DVI 可以作为一种界面描述的中间格式,通过它可以再进而转换成 PDF 格式。

为了区分概念,我们应当将高德纳写的 TeX 软件分为 TeX 语法 和 TeX 编译器。虽然高德纳自己写了一个 TeX 编译器,但其它人依旧可以在不同平台自己编程实现 TeX 语法的编译器。为了保持语法的稳定,TeX 有一组严格的测试文件,如果测试文件文件的输出结果不同于预定的结果,那么这个排版系统就不能够被称为「TeX」。这些不同的 TeX 编译器我们都称之为 「 TeX 引擎」。

TeX 目前(2018年)有如下几个编译引擎:

  1. TeX : 高德纳最早开发的官方实现,只能编译成DVI格式。
  2. pdfTeX : 支持直接编译成 PDF 格式。
  3. XeTeX : 支持 Unicode 编码和直接访问操作系统字体。
  4. LuaTeX : Lua 实现的 TeX 编译器。

虽然 Tex 出于向下兼容考虑要求了所有编译器都需要能够编译历史上所有符合标准的 Tex 文件,但并不意味着它不能增加新的功能。TeX 作为一门「宏语言」,能够使用宏定义出新的语法,甚至能够覆盖原先的语法。要理解这一点必须要先理解什么是「宏编程」。

什么是宏编程

要理解为什么宏如此强大,甚至强大到可以自己定义语法,我们可以来看一个例子 。

我们假设我们写了一门新的语言 「D」,它的语法如下 :

# compare:
"a" == "b" # false
"a" == "a" # true

# do .. while
do {
} while(bool)

# io
print("...")

# macro
define TYPE_NAME(params, ...) ......

乍一看宏(macro) 的用法非常像函数,但和函数有着本质区别的是,宏是一个编译时的字符串替换,而函数是运行时的一段可执行代码。例如:

define PLUS(a, b) a + b

int c = PLUS(1, 2)

这段代码在预处理的时候就会被替换成

我们可以发现这门语言中并不存在 if 语法,也不存在循环,但是通过宏我们能够为他定义出 if 和 for 语法。例如:

define IF(condition, instruction) do { instruction } while (condition)

define FOR(count, instruction) int __for_count__ = 0; do { __for_count__++ ; instruction } while ( __for_count__ < count )

利用宏我们完全可以扩展出一门新的语法结构,我们命名为 「D+」。「D+」严格意义上并不能算一个新的语言,只是称之为一个宏集。并且由于其只是在编译时做了字符串替换,所以依旧是可以用D的编译器编译的。

回到主题上来,TeX 就像是这里的 D 语言,LaTeX 就是「D+」宏集。LaTeX 本身也都是用 TeX 编译器来实现编译的。

宏集和宏包

宏集和宏包其实是一堆 TeX 指令集合,宏集以 .cls 结尾,宏包以 .sty 结尾。宏集需要以 \documentclass{...} 来加载,且一个文档一般只使用一个documentclass。而宏包是以\usepackage{...},无使用限制。

正式因为这个区别,所以一般宏集是一个完整的文档格式模板(也称之为「格式format」),比如武汉大学的论文模板 \documentclass{whucls}。而宏集比较灵活,例如你临时需要一些宏包来定义一些特殊字体就可以按需加载宏包。

LaTeX 就是一种 TeX 宏集,它内嵌了许多常用文档格式,例如 : article、report、book、letter等。使用方式很简单,在 .tex 文件最开头加上 \documentclass{article} 即可。

LaTeX 内建了许多新的指令,只需要对相应的段落内容予以其在文档中的「类型」即可使 LaTeX 自动为你排版。例如以下这段文档:

\documentclass{article}
    \title{TITLE XXXXXX}
    \author{XXX}
    \date{\today}

    \begin{document}
    \clearpage\maketitle

    ....

    \section{XXXXX}
    ...

    \section{XXXXX}
        \subsection{XXX}
        ...

        \subsection{XXX}

    \section{XXXXX}
    ...

    \end{document}

这里的 title、section、subsection 都是预先定义的 LaTeX 宏,在宏中已经定义好了样式。当然如果你需要在 LaTeX 宏集的基础上做自己的修改,你也可以基于 LaTeX 宏集做一个单独的宏包。

为什么要使用 LaTeX

我把上面这种写作方式称之为「面向对象写作」。这种设计的优点在于其逻辑完全与实际需求场景相吻合。例如我们在写论文的时候都会拿到一个论文格式规范清单,上面详细规定了什么样的内容需要以什么样的样式来书写。而我们一般使用 Word 时候的方式却是针对所有内容单独一点点地去设立样式。(当然目前 Word 也开始支持这种面向对象赋予格式,但远远没有 LaTeX 那么彻底。)

打个比方,LaTeX 相当于带 class 的 CSS , 而 Word 是裸写<div style="">。LaTeX 使得作者可以全身心地投入到写作之中,而无需去关心样式,当需要调整排版样式的时候,也仅仅只需修改类型的样式而非文档本身即可。

中文支持

关于中文支持网上说法非常过时和混乱。这里做一个统一的说明。

历史上中文支持方案有 CCT、CJK、xeCJK 三种。CCT 目前已经过时,推荐使用 xeCJK 。

但支持中文并不意味着就完成了中文化,我们还需要考虑到中文文档在不同文档类型、文本内容类型中的字体、字号等排版上的设计,同时还有不同系统字体系统不同的困扰。另外由于 LaTeX 在上述需求中完全是以英文视角在进行设计,所以回到中文世界我们需要一套完全不同的宏集合以支持完整的中文化需求。

目前中文世界有一个流行的宏集叫做 CTeX。与 LaTeX 一样,CTeX 也支持 ctexart(article)、ctexrep(report)、ctexbook(book)等文档类。同样使用如下方式引入:

严格来讲,CTeX 是一个内含多种程序和文件的软件包套装。但上文讲的 CTeX 指的仅仅其中的宏集/宏包部分。网络上针对 CTeX 的批评很多时候是针对其套装里的GUI和其它软件而言,其实和它的宏集没什么关系。

CTeX 宏集帮助我们处理好了各种中文排版问题,和操作系统问题,所以一般都推荐直接使用它,不需要额外的任何定义即可实现中文支持。

\documentclass[12pt, UTF8]{ctexart}

  \begin{document}
  \end{document}

虽然理论上当你使用 CTeX 写作时,应当称该文档使用 CTeX 完成,但事实上极少会有人这么去说,包括许多说自己在用 TeX 写作的人其实用的也都是 LaTeX 。这种语言上的错误用法大多是因为这个生态其实已经够复杂了,没必要再把人与人之间的交流弄复杂。所以大家统一称这个生态为 LaTeX 。

编辑器

非计算机专业的人往往会出于一些软件使用习惯,将编译器和编辑器等同来看。相当一部分时候编译器也的确顺带着编译器一起被整合成一个软件。但其实即使是系统自带的文本查看工具也可以称之为编辑器。网上主流的TeX编辑器有: TeX Live 、MiKTeX、CTeX 套件。为方便用户使用,这些软件在安装过程中按自动安装上各个主流的 TeX 编译器版本。当然你也可以使用任意其它编辑器诸如 VS Code 、Atom 、Vim ,使用他们的插件或者手动编译即可。

我的 LaTeX 工作方式

我个人比较喜欢的是 xelatex 编译器 + VS Code 的编写方式。

选择 xelatex 是因为它使用 unicode 编码直接支持中文。而 VS Code 的 LaTeX 插件支持每次保存文件自动编译,同时 Mac 的PDF查看程序每当文件发生变化的时候会自动刷新,从而实现了即写即看、所见即所得的写作体验。

我长期使用 Markdown 方式写作,即便是用 LaTeX 我们依然可以维持这个方式,方式很简单,markdown 的文档结构是完全能够被映射到 latex 的文档结构上的,利用这个方式可以写一个 parser 就能够实现这种批量转换了。我之后可能会考虑写一个工具来做这个事情。

一些 LaTeX 模板

  • latex-template-zh : 我用来写中文文章的模板库,在 ctex 基础上加了一些行间距之类的,使其更加适用于互联网文章的排版。
  • latex-resume-template : 我的 LaTeX 简历模板。