-
Notifications
You must be signed in to change notification settings - Fork 407
LaTeX 模板开发最佳实践
-
模板通常设计为 LaTeX2e 文档类(
cls
文件),用户通过\documentclass[<options>]{<class>}
加载模板。文档类的基本构成,可以参考texdoc clsguide
和texdoc source2e
, sec. 66--68. -
内容与格式分离:文档中的标记应表达语义,控制具体的格式的代码应集中放在
cls
文件中。
Liam Huang 的这篇文章介绍了什么是内容与样式分离。 -
最小化:模板的主要目的,是为常见文档组件提供一套定制的样式。不要期待模板面面俱到,不常见的文档组件(例如伪代码排版)应由用户通过调用宏包自行实现。可参考
IEEEtran
的做法。 -
接口的一致性:尽可能与标准文档类保持一致的接口。
-
尽量通过调用常见的宏包实现样式定制。
- 常见的宏包用户多、使用广泛,维护长期且稳定、参考资料丰富,很少出现难以解决的宏包冲突。
-
了解所用宏包的依赖项,了解特定宏包组合的加载顺序要求。
-
不在模板和示例文档中,重复加载同一个宏包或同一个宏包的组件(例如 tikz library, minted library)。
-
集中加载宏包组件,不在模板中零散加载。
-
控制宏包使用数量(最小化原则)。
- 仅少数用户需要的、宏包加载后配置简单的功能,可考虑不依赖相关宏包。需要时用户自行加载即可。例如排版算法/伪代码、浮动体双语标题、页面水印等功能。如果要在用户调用某宏包后自动进行配置,可以使用
filehook
或ctexhook
。 - 功能重合度较高的宏包,若非必要,不同时使用。例如控制章节标题样式的宏包
ctexheading
和titlesec
,提供 if-else 功能的宏包ifthen
和etoolbox
等。
- 仅少数用户需要的、宏包加载后配置简单的功能,可考虑不依赖相关宏包。需要时用户自行加载即可。例如排版算法/伪代码、浮动体双语标题、页面水印等功能。如果要在用户调用某宏包后自动进行配置,可以使用
-
尽量避免手动重定义基础命令,例如
\chapter
、\l@section
。 -
尽量避免定义新命令以「抽象」基础命令,例如
\newcommand\myChapter[1]{\chapter{附录:#1}}
。新命令会增加用户的使用门槛;到社区寻求帮助,「抽象」基础命令的需求通常都有更好的实现方式。 -
尽量使用 latex2e 风格的命令,如 counter 相关的、length 相关的、h/vspace 相关的。若非必要,不使用 tex 风格的命令和赋值方式。若非必要,不混用两种风格的命令,如一会儿
\hspace
一会儿\hskip
。 -
在文档类文件中,使用
texdoc clsguide
中介绍的命令,例如\RequirePackage
而非\usepackage
。 -
了解空格的各种产生方式,注释源码中的多余空格。
-
不滥用
\nobreakspace
,即~
。 -
区分带参数与不带参数的命令,区分改变状态与制造输出的命令。
-
了解作用域、分组(grouping)和
\global
-
[进阶] 了解错误信息(error/warning/info)的写法,参考
texdoc source2e
, sec. 15(latex2e 风格)和texdoc interface3
, part XVII(latex3 风格)。 -
[进阶] 代码层面的兼容性检测(另见下文条目,文档层面的兼容性描述)
- 操作系统的检测,
texdoc interface3
, sec. XIV.5 提供了对unix
,windows
和unknown
的判断;texdoc ctex
, sec. 14.3.6 提供了对macOS
的判断。 - 引擎的检测,见
ifxetex
及相关宏包(latex2e 风格),或texdoc interface3
, sec. XIII.3 - 引擎版本的检测,见各引擎的文档,例如
texdoc xetex-reference
, sec. 9 - 格式版本的检测,参考这个 TeX.SX 回答
- 基础文档类和宏包版本的检测,见下一条
- 操作系统和引擎的识别和检测,可用于为不同组合设定不同配置。格式、文档类和宏包版本的检测,常用于指定最老兼容版本。
- 操作系统的检测,
-
[进阶] 文档类依赖项的最低版本控制
- 一个文档类可以依赖一个(基础)文档类和多个宏包。
- 加载依赖项时,可通过可选参数指定最低版本(此处的版本,是以
YYYY/MM/DD
格式表示的发布日期)
\LoadClass[<opions>]{<class>}[YYYY/MM/DD] \RequirePackage[<opions>]{<class>}[YYYY/MM/DD]
- 如果用户本地的版本早于最低版本,编译时会产生 warning。如果觉得 warning 的优先级不够,可以使用
texdoc source2e
, sec. 68.3 介绍的命令\@ifpackagelater
和\@ifclasslater
,配合手写错误信息,来产生 error。
- 如果有大段复制粘贴的代码,建议以注释形式说明来源,方便后续维护。
- 使用缩进。保持缩进风格统一,不将空格和 Tab 混用。建议每层缩进使用 2 个或 4 个空格,其中 2 个空格是 latex3 推荐使用的( 见
texdoc l3styleguide
)
-
除非必要,不使用 LaTeX 2.09 风格的字体切换命令,例如
\rm
,\bf
等 -
在切换字体之前,推荐使用
\normalfont
把字体恢复到\rmfamily
。类似的命令还有\normalsize
-
谨慎使用
\songti
、\heiti
等只作用于 CJK 文字的命令,它们不会修改西文字体。推荐使用\rmfamily
,\sffamily
等命令,使西文与中文字体的风格保持一致。 -
在了解它们的初始定义之前,不要直接修改
\large
,\small
等命令的定义 -
修改行距:推荐使用
setspace/zhlineskip
宏包和\linespread
,可以接受修改\baselinestretch
,一定不要直接修改\baselineskip
-
\linespread{...}
和\fontsize{...}{...}
后面一定要跟\selectfont
-
控制示例文档中字体和字号切换命令的使用频次。它们应该隐藏在模板内部,不应该被模板用户(频繁)直接使用。
模板应提供用户文档。用户文档的形式自由,推荐包含以下内容
-
问题的反馈方式,包括但不限于维护者的联系方式、模板的在线托管地址等。
建议推荐几个问答社区,方便用户寻求解答。 -
文档层面的兼容性描述(另见前文条目,代码层面的兼容性检测)
- 适用的操作系统。LaTeX 的跨平台性较好,操作系统主要带来的问题是预装中文字体不同。
- 适用的(TeX Live 及其衍生的)发行版版本。例如增加描述「经作者使用和用户反馈,可在 TeX Live 2018 及更新版本上运行。更早的版本没有测试。」。MikTeX 发行版可跨年度升级,没有此项问题。
- 适用的编译方式,包括引擎和编译选项(例如
-shell-escape
) - 因不同编辑器的支持情况不同,不建议仅通过写在
tex
文件开头的 magic comment 指定编译方式和选项。建议在用户文档中明确说明。 - 如果提供了操作系统相关的辅助编译工具,如
Makefile
,应特别说明
-
模板定义的新命令的用法,模板修改过的既有命令的新用法或新效果
-
使用模板应遵循的文件结构,通常包括子文件的默认路径、图片和其他文件的默认路径等
文件结构可以在用户文档里通过文字说明,也可以在(随模板一起分发的)示例文档里通过实践体现 -
如果使用了 CTAN 未收录的功能性宏包,建议提供获取方式,并在文档中特别说明。可选将这类依赖随模板一起分发
-
如果使用了操作系统不预装的字体,建议单独说明。如果该字体是免费可获取的,建议列出获取方式,并提示授权使用范围。
包含完整的模板源码和用户文档的文件或文件包,即是一份模板的发布。如果模板需要长期维护(功能和文档的增删改),模板应该使用版本号、更新日志来记录变化,同时考虑使用版本管理软件,例如 Git。
用 Git 管理 LaTeX 项目时,以下问题值得关注
- 管理哪些文件
- LaTeX 辅助文件,不管理。推荐这个适用于 LaTeX 项目的
.gitignore
模板 - 二进制文件,可以管理,控制更新频次(以控制模板项目的大小)
- 图片文件,尽可能使用
mwe
宏包提供的示例图片 - PDF 文件,例如用户文档或示例文档,只在发布新版时更新。如果在 GitHub 托管,可以考虑只管理生成 PDF 的源码,通过 Release 功能提供编译得到的文档。
- 图片文件,尽可能使用
- LaTeX 辅助文件,不管理。推荐这个适用于 LaTeX 项目的
- 每次提交,commit message 要言之有物。
反例:wangxianyu7/sdu_wh_latex/commits, mohuangrui/ucasthesis/commits