Skip to content

Latest commit

 

History

93 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LaTeX-Fmt

命令行 LaTeX 代码格式化工具,提供代码美化与规范化能力。

核心原则:绝不因格式化导致原本能编译的代码无法编译,绝不因格式化导致原本的样式在格式化后出现差异。

遇到不确定的情况,宁保留原样,也不随意修改。

快速开始

构建

环境要求:C++17、CMake 3.16+。

mkdir build && cd build
cmake ..
make -j$(nproc)

生成的可执行文件为 build/latex-fmt

安装

# 方式一:在项目根目录执行
cmake --install build                     # 安装到默认位置(/usr/local)
cmake --install build --prefix /usr/local # 显式指定安装路径

# 方式二:在 build 目录内执行
cd build && make install                  # 使用 Makefile 安装

# 安装到用户本地目录(无需 root 权限)
cmake --install build --prefix ~/.local
make install DESTDIR=~/.local             # 或从 build 目录执行

基本使用

# 从标准输入读取,格式化到标准输出
latex-fmt < input.tex > output.tex

# 格式化文件并输出到标准输出
latex-fmt paper.tex

# 原地格式化
latex-fmt -i paper.tex

# 输出到指定文件
latex-fmt -o out.tex paper.tex

# Markdown 转 LaTeX 并格式化
latex-fmt --md < input.md > output.tex

功能特性

以下格式化规则可通过命令行参数控制开启或关闭

规则 说明
数学定界符统一 \(...\)$...$\[...\]$$...$$(行内/行间公式样式可通过 --inline-math-style / --display-math-style 配置)
花括号补全 \frac12\frac{1}{2}\sqrt3\sqrt{3}(仅限已知命令);数学模式上下标简写 x_ax_{a}x^2x^{2}
去冗余空白 文本模式多个空格压缩为 1 个;数学模式保留空格
缩进与换行 \begin/\end 层级自动缩进(默认每层 2 空格)
表格与公式对齐 表格(tabular/tblr 等)和数学环境(align/matrix/cases)中按 & 纵向对齐单元格,\hline 等分隔线独立成行
CJK-English 间距 中文与英文/数字之间自动添加空格
注释规范化 %comment% comment
行尾空格清除 每行末尾空格全部删除
空白行处理 纯空白行变为空行;连续多空行压缩为 1 个
行间公式独立 $$...$$ 自动独立成行并缩进(输出样式可通过 --display-math-style 切换为 \[...\] / \begin{equation} / \begin{equation*}
错误恢复 不匹配的花括号、缺失 \end 时不会崩溃,尽力恢复
方括号智能处理 数学模式中 [/] 视为普通字符;仅在命令/环境可选参数位置检查配对
长行警告与自动换行 --max-line-width=N 警告超长行;--wrap / --wrap-paragraphs 自动折行
语法检查 --syntax-check 检查环境/花括号/数学定界符配对,报告位置
语法修复 --syntax-fix 基于语法检查结果自动补全缺失的 } ] $ $$ \end
删除公式编号 --remove-tags 删除 \tag{...}\tag*{...} 命令
Markdown 转换 --md 将 Markdown 输入转换为 LaTeX 代码并格式化
列表项换行 --item-newline\item 内容放在独立行,--item-newline-threshold=N 设置触发换行的最小字符数

可配置参数

所有规则均可通过命令行或配置文件单独控制

参数 默认值 说明
--indent-width=N 2 缩进宽度(空格数)
--no-cjk-spacing / --cjk-spacing 开启 CJK 与 ASCII 字符间自动插入空格
--no-brace-completion / --brace-completion 开启 单字符参数自动补全花括号
--no-comment-normalize / --comment-normalize 开启 %comment% comment
--no-blank-line-compress / --blank-line-compress 开启 连续多空行压缩为 1 个
--keep-trailing-spaces / --remove-trailing-spaces 删除 是否保留行尾空格
--no-display-math-format / --display-math-format 开启 $$...$$ 独立成行
--no-math-unify / --math-unify 开启 是否统一数学公式的定界符
--no-math-trim / --math-trim 开启 是否修剪数学环境中的多余空格($ 定界符与内容之间、{} 内前后空格)
--display-math-style=S dollar 行间公式输出样式:dollar$$...$$)、bracket\[...\])、equationequation*
--inline-math-style=S dollar 行内公式输出样式:dollar$...$)、bracket\(...\)
--max-line-width=N 0(关闭) 当 N > 0 时,超长行触发警告
--wrap 关闭 配合 --max-line-width 自动折行
--wrap-paragraphs 关闭 纯文本段落长行自动折行
--syntax-check 关闭 格式化前检查语法错误(环境/括号/数学定界符配对)
--syntax-fix 关闭 自动补全缺失的 } ] $ \end 等定界符
--remove-tags 关闭 删除公式中的 \tag{...} / \tag*{...} 命令
--context-chars=N 10 --syntax-check 错误信息中显示的前后文字数
--item-newline 关闭 \item 内容放在独立行并缩进
--item-newline-threshold=N 0 \item 内容超过 N 个字符时才换行(0 = 始终换行)

使用指南

检查、diff 与修复模式

# 检查是否需要格式化(CI 用,有变更时退出码为 1)
latex-fmt --check paper.tex

# 显示 unified diff 差异
latex-fmt --diff paper.tex

调整格式化参数

# 缩进宽度设为 4
latex-fmt --indent-width=4 paper.tex

# 关闭 CJK-ASCII 自动空格
latex-fmt --no-cjk-spacing paper.tex

# 长行自动折行(行宽 80)
latex-fmt --max-line-width=80 --wrap-paragraphs paper.tex

# 行间公式输出为 \begin{equation}...\end{equation}
latex-fmt --display-math-style=equation paper.tex

# 关闭数学公式空格修剪(保留 $...$ 和 {} 内空格)
latex-fmt --no-math-trim paper.tex

# 组合多项参数
latex-fmt --indent-width=4 --no-cjk-spacing --quiet paper.tex

递归处理

# 原地格式化目录下所有 .tex 文件
latex-fmt -r -i project/

# 递归检查目录
latex-fmt -r --check project/

# 递归显示 diff
latex-fmt -r --diff project/

Markdown 转换

通过 --md 选项,可将 Markdown 文本转换为 LaTeX 代码并自动格式化:

# 从 Markdown 文件转换
latex-fmt --md input.md -o output.tex

# 从标准输入读取 Markdown
cat README.md | latex-fmt --md > readme.tex

# 配合其他格式化参数使用
latex-fmt --md --indent-width=4 notes.md

当前支持的 Markdown 语法:

语法 Markdown LaTeX
标题 # Title \section{Title}
加粗 **bold** \textbf{bold}
斜体 *italic* \textit{italic}
行内代码 `code` \texttt{code}
代码块 ```...``` \begin{verbatim}...\end{verbatim}
链接 [text](url) \href{url}{text}
无序列表 - item \begin{itemize} \item item \end{itemize}
有序列表 1. item \begin{enumerate} \item item \end{enumerate}
引用 > quote \begin{quote}quote\end{quote}
行内公式 $E=mc^2$ 原样保留(不转义内部字符)
行间公式 $$...$$ 原样保留(内容不做转义)

注意:公式中的 &\\_# 等 LaTeX 特殊字符不会被转义,$...$$$...$$ 支持跨多行。$$ 单独成行时视为行间公式,前方无空行时视为内联闭合定界符。

语法检查与智能修复

--syntax-check 在格式化前对文档进行基本语法校验,--syntax-fix 能自动修复检测到的缺失定界符问题。

# 仅检查语法(不格式化),有错误时退出码为 1
latex-fmt --syntax-check paper.tex

# 自动修复缺失的定界符并格式化
latex-fmt --syntax-fix paper.tex

# 调整错误上下文显示字符数(默认 10)
latex-fmt --syntax-check --context-chars=20 paper.tex

检测和修复覆盖范围:

问题类型 示例 --syntax-check --syntax-fix
未关闭环境 \begin{document} 缺少 \end{document} 报错 插入 \end{document}
未关闭行内公式 $x+y 缺少闭合 $ 报错 插入 $
未关闭行间公式 $$x+y 缺少闭合 $$ 报错 插入 $$
未关闭花括号 \textbf{Bold 缺少 } 报错 插入 }
未关闭方括号(命令可选参数) \sqrt[3{2} 缺少 ] 报错 智能插入 ]
多余闭合定界符 }text 多余 } 报错 插入 { 配对
环境名缺括号 \begin{equation} 报错 自动识别

关于方括号[ / ] 仅在紧跟在已注册命令或环境名后时视为可选参数分隔符。在数学模式($...$ / $$...$$)和普通文本中,[] 是普通的字面字符,不需要成对出现。例如张量记号 \delta^{[a_1}_{a_1} 中的 [ 不会触发语法错误。

注意--syntax-check 仅报告错误不修改文件。--syntax-fix 会修改源文件内容后再格式化。两者均默认关闭,适用于信任文档能正常编译的场景。

删除公式编号

使用 --remove-tags 可以删除从其他文档粘贴过来的公式中带有的 \tag{...} 编号,避免原文编号与新文档冲突:

# 删除所有 \tag{...} 和 \tag*{...} 命令
latex-fmt --remove-tags paper.tex

支持 \tag{}\tag*{} 两种形式,适用于行间公式($$...$$)和各数学环境(equationalign 等)。

其他选项

# 抑制警告输出
latex-fmt --quiet paper.tex

# 指定自定义配置文件
latex-fmt --config-file=/path/to/.latexfmtrc paper.tex

配置文件

latex-fmt 支持 .latexfmtrc 配置文件,按以下优先级查找(后找到的覆盖先找到的):

  1. ~/.latexfmtrc(全局配置)
  2. ./.latexfmtrc(项目目录配置)
  3. --config-file=<path> 指定的文件(最高优先级)

命令行参数始终覆盖配置文件中的设置。

配置文件格式为 key = value# 开头的行为注释:

# .latexfmtrc 示例
indent_width = 4
max_line_width = 80
cjk_spacing = false
wrap_paragraphs = true

# 布尔值支持: true / false / 1 / 0 / yes / no / on / off
brace_completion = true
comment_normalize = true

# 行间公式输出样式: dollar / bracket / equation / equation*
display_math_style = bracket

# 行内公式输出样式: dollar / bracket
inline_math_style = dollar

# 其他格式化选项
blank_line_compress = true
trailing_whitespace_remove = true
display_math_format = true
math_delimiter_unify = true
math_trim_spaces = true
wrap = false
remove_tags = false
context_chars = 10

# 列表项换行: true/false; 换行阈值: 字符数 (0 = 始终换行)
item_newline = false
item_newline_threshold = 0

项目结构

latex-fmt/
├── src/
│   ├── core/              # 基础类型与配置
│   │   ├── config.h       # FormatConfig 配置结构体
│   │   ├── registry.h     # 命令/环境签名注册表
│   │   ├── char_category.h# 字符分类工具
│   │   ├── unicode_width.h# UTF-8 解码与字符宽度
│   │   ├── source_location.h
│   │   ├── syntax_check.h  # 语法检查器
│   │   └── syntax_fix.h    # 语法修复器
│   ├── parse/             # 词法与语法分析
│   │   ├── ast.h          # AST 节点定义
│   │   ├── lexer.h        # 词法分析器 → Token 流
│   │   └── parser.h       # 递归下降解析器 → AST
│   ├── format/            # 格式化引擎
│   │   ├── visitor.h      # AST Visitor,生成格式化输出
│   │   └── math_aligner.h # 表格与数学环境列对齐算法
│   ├── md/                # Markdown 转 LaTeX 转换
│   │   └── md_converter.h # Markdown → LaTeX 转换器
│   ├── utils/             # CLI 工具函数
│   │   ├── io.h           # 文件读写
│   │   ├── diff.h         # unified diff 生成
│   │   └── wrap.h         # 行自动换行
│   └── main.cpp           # CLI 入口
├── tests/
│   └── snapshots/         # 快照测试(.tex 输入 + .expected.tex 预期)
├── scripts/
│   └── setup.sh           # 下载并安装 Catch2
├── external/              # 第三方依赖(gitignore,由脚本生成)
└── CMakeLists.txt

运行测试

# 首次运行需安装 Catch2
./scripts/setup.sh

# 构建并运行测试
cd build
cmake .. -DBUILD_TESTS=ON
make -j$(nproc)
ctest

技术栈

  • 语言:C++17
  • 构建:CMake 3.16+
  • 测试:Catch2 v3(可选)
  • 依赖:无外部运行时依赖

支持的命令与环境

以下列出已注册的所有命令和环境。未列出的命令不会被修改,原样保留。

命令

文本格式

\textbf \textit \emph \texttt \textsf \textrm \textsc \textup \textnormal — 各 1 个必选参数,支持花括号补全。

数学常用

命令 参数格式 说明
\frac {2} 分数
\sqrt [1]{1} 根号(可选根指数)
\binom {2} 二项式系数

分隔符尺寸

\left \right — 动态尺寸分隔符,其后接定界符(如 ( [ \{ \langle 等),需成对出现。

命令组 示例 说明
\bigl \Bigl \biggl \Biggl \bigl( ... \bigr) 左侧定尺寸分隔符
\bigr \Bigr \biggr \Biggr \Bigl[ ... \Bigr] 右侧定尺寸分隔符
\big \Big \bigg \Bigg \big| ... \big| 中性定尺寸分隔符

分隔符可以是:. [ ] \{ \} ( ) \| \langle \rangle \lfloor \rfloor \lceil \rceil

数学修饰

命令 参数格式 说明
\stackrel \overset \underset {2} 上下堆叠
\substack {1} 多行下标
\text \operatorname {1} 数学模式中的文本
\tag \tag* {1} 公式编号

\notag \nonumber \limits \nolimits \displaylimits \displaystyle \textstyle \scriptstyle \scriptscriptstyle \smash \mathclap \mathrlap \mathllap \dd — 无参数命令。

自定义命令

\DeclareMathOperator {2}\newcommand \renewcommand \providecommand \newenvironment \renewenvironment(参数按独立 Group 解析)、\ensuremath {1}

文档结构

\section \subsection \subsubsection \paragraph \subparagraph \title \author \date — 各 1 个必选参数,支持花括号补全。

交叉引用

\label \ref \pageref \eqref {1}\cite [1]{1}

包与文档类

\usepackage [1]{1}\documentclass [1]{1}

浮动体与图形

\caption {1}\includegraphics [1]{1}

列表

\item [1](可选方括号参数)。

无参数命令

\maketitle \tableofcontents \newpage \clearpage \centering \raggedright \raggedleft \noindent \indent \newline \linebreak \pagebreak \hfill \vfill \hrulefill \dotfill \smallskip \medskip \bigskip \par \today \appendix \baselineskip

宏包扩展命令

caption / subcaption

\captionsetup {1}\subcaption {1}(支持花括号补全)。

graphicx / xcolor

\graphicspath {1}\DeclareGraphicsExtensions {1}\includesvg [1]{1}\color [1]{1}\textcolor [1]{1}\colorbox [1]{1}\pagecolor {1}\definecolor {3}

bm

\bm {1}(支持花括号补全)。

mhchem

\ce {1}(化学式)、\pu {1}(物理单位)。

physics / braket / derivative
命令 参数格式 说明
\abs \norm \qty \order {1} 绝对值 / 范数 / 括号 / 阶
\mqty {1} 矩阵
\eval \comm \dv \pdv \odv \derivative {2} 求值 / 对易子 / 导数
\ket \bra {1} 右矢 / 左矢
\braket {2} 内积
\set {1} 集合
\Bra \Ket {1} 大尺寸矢
\dd 微分算子
extarrows

\xleftrightarrow \xlongequal \xLongrightarrow {1}

gensymb

\degree \celsius \micro \perthousand \ohm(无参数)。

algorithm2e

\KwIn \KwOut \KwData \KwResult \For \While \If \Else \ElseIf \Return \SetKw \SetAlgoLined \LinesNumbered \BlankLine(无参数)、\SetKwInOut {2}\tcp {1}

enumitem

\setlist {1}\newlist {3}\setenumerate \setitemize \setdescription(无参数)。

lipsum / zhlipsum

\lipsum [1](英文盲文)、\zhlipsum [1](中文盲文)。

Article / Book 文档类

\part / \part* [1]{1} / {1}\chapter / \chapter* [1]{1} / {1}\thanks {1}\frontmatter \mainmatter \backmatter \listoffigures \listoftables \pagestyle \pagenumbering(无参数)。

Beamer 文档类
命令 参数格式 说明
\frametitle \framesubtitle {1} 帧标题/副标题
\usetheme \usecolortheme \usefonttheme \useinnertheme \useoutertheme {1} 主题设置
\titlegraphic \logo {1} 标题图/徽标
\institute \alert \structure {1} 单位/高亮/结构色文字(花括号补全)
\onslide {1} 叠层可见范围
\only \uncover \visible \invisible {2} 叠层条件显示
\pause \titlepage 暂停/标题页
\insertsectionhead \insertsubsectionhead 插入当前节/子节标题

表格分隔线

\hline [1]\toprule \midrule \bottomrule \cmidrule — 表格横线命令,格式化时自动独立成行。

环境

数学环境

环境 对齐策略 说明
align / align* aligned alignedat flalign / flalign* split & 交替对齐 多行公式对齐
gather / gather* gathered equation / equation* multline / multline* 居中/单行/长公式
pmatrix bmatrix Bmatrix vmatrix Vmatrix matrix smallmatrix 矩阵等宽列 各类矩阵
cases dcases 分支对齐 分段函数

列表环境

itemize(无序) enumerate(有序) description(描述)。

原样输出

verbatim lstlisting minted — 内容不做格式化处理。

内联原样输出

\verb|...|\verb*|...| — 内联逐字命令,内容原样保留不做任何格式化处理。\verb* 将空格显示为可见字符。分隔符可选用除 * 外的任意非字母字符(如 |!+ 等)。

表格环境

环境 对齐策略 说明
tabular tabularx tblr longtblr talltblr & 等宽列 + 分隔线独立行 表格单元格对齐

浮动体与子环境

figure / figure* table / table* subfigure subtable

算法环境

algorithm function

Beamer 环境

frame columns column block exampleblock alertblock overlayarea overprint

Article / Book 环境

abstract

其他环境

center flushleft flushright quote quotation tikzpicture

License

「随君所想,成君所愿」

About

一个命令行 LaTeX 代码格式化工具,实现代码的美化和规范化

Resources

Stars

10 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages