HenryXiaoYang/realtime-tex · 上手攻略
- 仓库:HenryXiaoYang/realtime-tex
- 链接:https://github.com/HenryXiaoYang/realtime-tex
- 分类:engineering / academic-writing / latex
- 作者:spark
- 更新:2026-11-03
一、它是什么
rtex(Realtime TeX)是一个给编辑器用的实时排版库:当你敲键盘时,它只重新排版你正在编辑的那一段(paragraph),大约 1 毫秒就把结果交回编辑器绘制;整页的分页、浮动体、目录、参考文献则交给后台的完整编译去收敛。
关键卖点是精确:它跑的是 TeX Live 里未经修改的 LuaTeX,输出的换行位置、字形和位置与正常 LuaLaTeX 编译的结果一致到 1/65536 pt,导出的 PDF 与常规 LuaLaTeX 构建完全相同。它不是"用另一套引擎模仿 LaTeX",而是复用 LuaTeX 本身,只在段落粒度上做增量。
方法论来自 Clemens Lode 的论文《Real-Time LuaTeX: Recompiling Large Documents in 1 ms》(TUG 2026,预印本在 tug.org/tug2026/preprints/lode-realtime.pdf),仓库在 bench/upstream/ 里原样 vendored 了论文的 benchmark。
技术形态是 Rust 写的库(MIT 许可),提供三种接入方式:Rust crate rtex-core、C 库(include/rtex.h / librtex_core,任何有 C FFI 的语言都能用)、以及 rtex serve 子进程模式(stdin/stdout 走 JSON lines,适合脚本、原型和 JS 写的编辑器扩展)。仓库自己也附了一个完整的 host 实现——VS Code 扩展 realtime-tex-vsc-plugin。
截至 2026-11-03,最新 release 是 v0.0.6(2026-11-01 发布),README 明确写着:"它能跑,也测过了,但 API、C ABI 和 display-list 格式在 0.1 之前可能还会变。"
二、解决什么问题
LaTeX 的经典痛点是全量编译。哪怕你只改一个字,latexmk 也要从头跑一遍:加载 preamble、排版整篇、跑两三轮交叉引用、再出 PDF。仓库自己的 benchmark 显示,10 页文档一次完整 LuaLaTeX 跑要 0.52 s,100 页 0.91 s,300 页 1.69 s——而 Overleaf 每次重编译重复的就是这个全量过程。
另一个痛点是实时预览工具往往不精确。Typst 很快,但它有自己的标记语言,LaTeX 文档得重写,输出也不是真正的 LaTeX 排版结果。rtex 的取舍很清晰:只要 LaTeX 和真实 LuaLaTeX 输出,不要"差不多"。
它的解法是分工:段落级的、视觉上立即可见的内容走毫秒级的 live engine;页面级的、依赖全文状态的内容(分页、浮动体位置、目录、交叉引用编号)走后台完整编译,几秒后收敛。两者共用同一个已加载 preamble 的 LuaLaTeX 进程。
三、快速安装
最省事的路:装 VS Code 扩展
从 VS Code Marketplace 装 "Realtime TeX" 扩展;VSCodium / Cursor 等编辑器走 Open VSX。扩展会在首次使用时替你装好 rtex,必要时还会装一个最小 TeX Live。打开 .tex 文件,点编辑器标题栏的预览图标(或 Ctrl+Alt+V / macOS 上 Cmd+Alt+V)即可。Linux、macOS、Windows 原生支持,Windows 上会自动下载对应平台的预编译引擎。
手动装预编译包
每个 release 附五个平台的压缩包(另有 .sha256 与 SHA256SUMS):
rtex-x86_64-unknown-linux-gnu.tar.gz(4.9 MB)rtex-aarch64-unknown-linux-gnu.tar.gz(4.5 MB)rtex-x86_64-apple-darwin.tar.gz(4.7 MB)rtex-aarch64-apple-darwin.tar.gz(4.3 MB)rtex-x86_64-pc-windows-msvc.zip(4.6 MB)
curl -L https://github.com/HenryXiaoYang/realtime-tex/releases/latest/download/rtex-x86_64-unknown-linux-gnu.tar.gz | tar -xz
rtex-*/bin/rtex doctor # 检查 rtex 是否找到了自己的文件和你的 LuaLaTeX
从源码构建
需要 Rust 和带 LuaLaTeX 的 TeX Live:
git clone https://github.com/HenryXiaoYang/realtime-tex && cd realtime-tex
scripts/install-texlive.sh && source build/texlive.env
cargo build --release
install-texlive.sh 会往 build/texlive 装一个最小 TeX Live,约 15 分钟(Windows 上从 Git Bash 跑)。已有 TeX Live 或 MacTeX 也可以,直接把 RTEX_TEXLIVE_BIN 指向它的 bin 目录。
跑起来看看
# 造一个 10 页测试书,施加一次实时编辑,打印返回结果
target/release/rtex gen-book --pages 10 --out build/fx/book-10
target/release/rtex edit --project build/fx/book-10 --find "Baseline export" --text " (edited)"
# 校验实时输出与真实 PDF 是否一致,然后导出
target/release/rtex verify --project build/fx/book-10
target/release/rtex export --project build/fx/book-10 --out build/book-10.pdf --check
四、核心用法
作为库接入(三种方式,同一个 Session 后端)
Rust:
use rtex_core::{Edit, Event, Session, SessionConfig};
use std::time::Duration;
let cfg = SessionConfig::new("/path/to/project", "main.tex");
let session = Session::open(cfg)?;
// 用户在 main.tex 的第 1234 字节处输入了 " world"
let r = session.apply_edit("main.tex", Edit {
start_byte: 1234, end_byte: 1234, text: " world".into()
})?;
// r.routed 是 "fast" / "background" / "preamble";非 fast 时 r.reasons 说明原因
loop {
for ev in session.poll(Duration::from_millis(16)) {
match ev {
Event::ParagraphUpdate { .. } => { /* 重绘一个单元 */ }
Event::LayoutUpdate { .. } => { /* 替换页面 */ }
_ => {}
}
}
}
编辑是 UTF-8 文本里的字节区间替换;路径相对项目根。有整个 buffer 而不是 diff 时用 set_document(path, text)。两个调用都立即返回,结果以事件形式到达。
其他常用调用:request_layout()(立刻开一次后台编译而不是等 debounce)、pause_background(true/false)(暂停后台 pass 但保留实时更新)、export_pdf(path)(出干净 PDF)、spans(path)(看文件当前被切成哪些单元)、close()。
子进程模式:
rtex serve --project path/to/your/project # JSON lines on stdin/stdout
C 库(include/rtex.h)则适合 C、C++、Swift、Zig,以及 Python 通过 ctypes 调用。
你收到的是什么:不是 PDF,而是一串display list——来自字体文件的字形、精确到 1/65536 pt 的位置、线条、图像和颜色,可以直接画。遇到 display list 描述不了的东西的页面(TikZ 矢量图、\pdfliteral、从右到左文本、pdflscape 旋转页、图片缓存页)会被标为 degraded,rtex 会给你那一页的 PDF,host 从 PDF 画。
关键配置项(rtex serve 有对应的 flag):
| 项 | 默认 | 含义 |
|---|---|---|
--fast-budget-ms |
50 ms | 一个单元慢于此值连续三次,就退回等后台 pass |
debounce_ms |
300 ms | 停手多久后开始后台 pass |
max_passes |
5 | 一次 layout 最多几轮 pass,超了报 PassLimitReached |
compile_timeout_ms |
5 s | 实时编译超时即杀掉并重启引擎 |
pass_timeout_ms |
5 min | 后台/导出 lualatex 超时即杀掉,layout 报 Failed |
--eligibility |
probe |
probe 用比对验证未知命令;allowlist 只允许已知命令 |
--no-picture-cache |
开 | 复用上一轮 pass 里没变的 TikZ 图片 |
--math-owner-attribute |
无 | 打开数学公式命中测试元数据(选一个你文档没用的 LuaTeX attribute 号,如 65000) |
probe 模式是它最聪明的设计:默认模式下,任何形状上说得通的单元都能实时更新,即使用了 rtex 从没听过的命令。第一次编辑某个单元时,rtex 会把它的旧文本排一遍,跟页面上的结果逐字比对;完全一致才放行实时更新,不一致就说明理由、让它等后台 pass。
五、典型适用场景
- 写论文时改段落:300 页的 book,改一段 1.3–1.6 ms 出结果,页码/目录/引用编号几秒后跟上。
- 带复杂公式的稿件:
align、gather、multline、\label、\tag、行内与行间公式都实时更新。 - IEEE / ACM 模板:
IEEEkeywords、IEEEdescription、\subsubsection、\paragraph都在实时支持列表里。 - 编辑器作者:想做 LaTeX 实时预览的 IDE,直接用 C 库或 JSON-lines 协议接,别自己重写排版。
- 与 Typst 混合的工作流:已有 LaTeX 文档不想重写,但想要 Typst 那种手感——这正是 rtex 的定位。
六、坑与注意
- 只支持 LuaLaTeX。 pdfLaTeX 和 XeLaTeX 不支持,且要求 2021 年或更新的 LaTeX kernel(rtex 用到了 kernel 的段落与 shipout hook)。有大量 legacy pdfLaTeX 文档的团队要先确认。
- 字体是最大的性能开关。 benchmark 明确:fontspec 默认的 OpenType shaping(node 模式)下,11 行段落要 9.17 ms,而 TFM 字体只要 1.94 ms——差 4–5 倍。想快就改字体设置:
latex
\usepackage{fontspec}
\setmainfont{TeX Gyre Pagella}[Renderer=Basic] % 引擎原生整形
或经典方案 \usepackage[T1]{fontenc} + \usepackage{lmodern}。注意 Renderer=Basic 只适合拉丁、希腊、西里尔文;阿拉伯文、印度系等需要复杂整形的脚本仍需默认 renderer,能实时更新但更慢。
- 改 preamble 会重启实时引擎(约 1–2 s)。写在正文里的
\setlength、\renewcommand、\definecolor、\lstset等 setup 行也是同一条路径——rtex 把它们和 preamble 一起加载,改它们等于改 preamble。 - 编辑器看到的东西 ≠ 完整文档。 目录、列表环境、脚注正文、边注、
wrapfigure、跨列文本、引用编号都等后台 pass。这不是 bug,是设计。README 里有明确清单,跨页引用编号可能滞后一轮。 - probe 有一个已知盲区。 如果你给一个已验证过的段落加了一个旧文本没有的依赖(比如在第 2 页段落里敲
\thepage),该段会显示错误的数字直到下一次 layout 重新校验。 - TikZ 页面会退化。 矢量路径 display list 描述不了,含 TikZ 的页面改从上一轮的 PDF 画。好处是未改动的图片有缓存(111 页 120 图的文档,一轮 pass 从 45 s 降到 18 s),坏处是这类页面不是矢量实时的。
- 实时编译有 50 ms 预算上限。 超预算的单元(通常是正在编辑的大幅 TikZ)会被踢回后台路径,下一轮 layout 后才恢复。
- 引擎崩溃有熔断。 连续崩三次后,该单元被强制留在后台路径,直到 preamble 变化才恢复。
- 多文件项目有边界。
\input、\include、\subfile能跟踪,但用宏拼出来的文件名(\input{\chapterdir/x})、\includeonly和\import不会被跟踪。 - 参考文献工具有限。
biber、bibtex、makeindex会自动跑(imakeidx 的program=/options=会被采用),但xindy和makeglossaries不会自动运行。 - 性能数字的口径要说清楚。 rtex 报的是"段落级往返",不含绘制;Typst 和完整编译报的是"整个一致文档",所以数字不可直接横向相加。仓库自己在 benchmarks.md 里点明:"这个比较并不完全对等。"
- benchmark 数据有版本戳。 全部数字测于 2026-10-10、rtex 0.0.2、4 vCPU 云 VM(Intel Xeon @ 2.10 GHz)、TeX Live 2026,典型笔记本会更快。论文用的是 i7-1355U 笔记本,该 VM 排版慢约 1.3×。引这个数要带版本。
- API 还没稳定。 0.0.x 阶段,C ABI 和 display-list 格式都可能变,别急着绑死。
- 没有协作功能。 对比表里明写 rtex 协作 = 无;Typst 有网页实时协作,Overleaf 有实时协作/评论/历史/模板。
七、与同类对比
仓库自己的 benchmarks.md 给了同机对比(2026-10-10,VM 环境,文本为 A4 11pt、约五行一段的段落,编辑中间段 30 次):
| 页数 | rtex 每次编辑 (P95) | Typst 0.15.1 typst watch |
Typst 导出一页 | 完整 pdfLaTeX | 完整 LuaLaTeX |
|---|---|---|---|---|---|
| 10 | 1.6 ms (2.4) | 18 ms | 9 ms | 0.12 s | 0.52 s |
| 100 | 1.3 ms (1.7) | 146 ms | 47 ms | 0.25 s | 0.91 s |
| 300 | 1.3 ms (1.7) | 414 ms | 121 ms | 0.51 s | 1.69 s |
段落级的横向对比(README 表格):
| 段落 | 10 页 | 100 页 | 300 页 |
|---|---|---|---|
| 一行 | 0.50 ms | 0.48 ms | 0.61 ms |
| 四行 | 1.04 ms | 1.10 ms | 1.18 ms |
| 十行 | — | 2.39 ms | 1.94 ms |
| 列表/图/表/行间公式 | 1.4–1.9 ms | 1.5–1.7 ms | — |
核心结论:文档长度不重要,段落长度才重要。 300 页的书和 10 页的书一样快。
功能取舍三角:
| rtex | Typst | Overleaf | |
|---|---|---|---|
| 语言 | LaTeX(仅 LuaLaTeX),复用现有文档和宏包 | 自有标记,LaTeX 文档需重写 | LaTeX(pdf/Xe/Lua 皆可) |
| 输出 | 与 LuaLaTeX 完全一致 | Typst 自己的排版 | 真实 LaTeX 输出 |
| 输入时 | 段落立即精确,版面数秒后跟上 | 每次编译整个文档一致 | 每次重编译后一致 |
| 协作 | 无,本地 | 网页应用,实时协作 | 实时协作、评论、历史、模板 |
| 安装 | 本地 TeX Live + Rust(VS Code 扩展一键装) | 一个二进制或浏览器 | 浏览器 |
与论文原文对比:论文测得排版阶段 short 0.17 ms / medium 0.70 ms / long 1.99 ms,rtex 在这台更慢的 VM 上分别是 0.05 / 0.92 / 2.56 ms;论文报告的完整往返是短段 0.79 ms、中段 6.11 ms,rtex 实测 0.5–0.6 ms / 1.0–1.2 ms——差异主要在 TeX 之外的工作,rtex 走盒子并编码紧凑二进制 display list 只花 0.23 ms。
八、一句话推荐结论
如果你有大量 LaTeX 文档、又受不了每次全量编译的 1–2 秒,rtex 是目前唯一"既保持 LuaLaTeX 逐字节精确、又把段落反馈压到 1 毫秒级"的方案——先装 VS Code 扩展试十分钟,把字体切成 Renderer=Basic 或 TFM,体验会立刻明显不同;但请把它当成 0.0.x 的实验性库(API 未冻结),并且记住你看到的段落永远比最终排版"快半拍",目录和引用要等后台 pass。
本文基于 2026-11-03 抓取的仓库 README(main 分支)、docs/live-editing.md、docs/benchmarks.md、docs/embedding.md,以及 GitHub API 确认的 v0.0.6(2026-11-01 发布)与五个平台预编译包资产。性能数字均标注了原始测量日期(2026-10-10)、rtex 版本(0.0.2)与硬件(4 vCPU 云 VM),引用时建议一并保留。