TeXShop 于 2000 年 7 月 23 日发布到互联网上,比 Mac OS X 10.0 上市还早了八个月。俄勒冈大学的数学家 Richard Koch 为一个当时尚未正式存在的操作系统写了一个 LaTeX 前端,而这一赌押对了:二十六年后,MacTeX 装进 /Applications/TeX/ 的编辑器依然是 TeXShop,依然免费,依然是 GPLv2,依然只跑在 macOS 上。本页要讲的正是这段历史留下的东西——那个引擎弹出菜单背后其实只是一个装着 shell 脚本的文件夹、用来逐文件锁定设置的 % !TEX 行、⌘ 点击的 SyncTeX——以及 TeXShop 不再是合适工具的那条界线。
为什么 TeXShop 预览的是 PDF 而不是 DVI
因为 macOS 本身就是用 PDF 绘制屏幕的。1996 年底 Apple 收购 NeXT 之后,NeXTSTEP 的 Display PostScript 被弃用,Mac 的绘图层 Quartz 改建在 PDF 之上——用 Koch 自己的话说,这让 PDF 成了系统的根基,既容易生成,又几乎不费力就能显示。写一个 DVI 预览器要花好几个月,而 PDF 预览器几乎是白送的。他当时又恰好发现了 pdfTeX(那时还是 0.14 版),它能不经 dvips 直接把 .tex 变成 .pdf。于是 TeXShop 的整个形态——一个源码窗口、旁边一个预览窗口、中间夹着 pdflatex——其实是从 Apple 关于「屏幕上怎么画矩形」的一个决定里掉出来的。
最早的公开版本发布于 2000 年 7 月,那时 Mac OS X 还是公开测试版,而它带着一个并非 Koch 之过的惊人缺陷:当时 Apple 的 PDF 代码还读不了嵌入字体,于是用 Times 排的正文显示得漂漂亮亮,每一个公式却都变成一块空白的矩形。而那恰恰是数学家最需要的部分。2000 年的开发者大会上,Koch 拿着最新的测试版赶回旅馆装上、运行 TeXShop,发现字体依旧不见踪影;Apple 直到 2001 年 3 月的正式版才修好它。2002 年,TeXShop 1.19 拿下了 Apple Design Award——奖项所属的类别是开源「移植」,这让 Mac 上的 TeX 邮件列表颇为困惑,因为 TeXShop 从来就不是任何东西的移植。后来 XeTeX 的作者 Jonathan Kew 想让 Windows 和 Linux 上的 TeX 也这么平易近人时,他明言以「Dick Koch 那个获奖的 TeXShop」为范本——那就是 TeXworks。
安装 TeXShop:它包含在 MacTeX 里
不必单独去找 TeXShop 的安装包——MacTeX 会一并带来。MacTeX-2026 内含 TeX Live 2026,把发行版本体装在 /usr/local/texlive/2026/,把五个图形界面程序——TeXShop、TeX Live Utility、LaTeXiT、BibDesk 和 hintView——放进 /Applications/TeX/。它要求 macOS 11 Big Sur 以上,在 Intel 与 Apple 芯片上都原生运行。下文一切的前提是:TeXShop 本身不含任何 TeX。它只是一个前端,每次排版不过是去调用 /Library/TeX/texbin 里的 pdflatex、lualatex 或 latexmk。删掉 TeXShop,你在终端里的 TeX 照样能用;删掉 /usr/local/texlive/,TeXShop 连一行都排不出来。
这两半各走各的更新节奏,很多人在这里绊倒。宏包更新由同一文件夹里的 TeX Live Utility 负责:打开它,它会列出自你上次运行以来 CTAN 上变动过的一切。TeXShop 本体则从俄勒冈大学 Koch 的页面单独更新。当前的 5.57(2025 年 10 月)要求 macOS 10.13 High Sierra 以上,一直可用到 Tahoe。针对 macOS 26 Tahoe,TUG 另有一个附加安装包,它不是替换 5.57,而是在旁边再装一份 TeXShop 5.58;5.58 就是同一个程序在 Tahoe 上重新编译的结果,而这正是让一个应用获得 Apple Liquid Glass 外观的方式。/usr/local/texlive/ 下可以并存多个年份的 TeX Live,用哪一个由 TeX Live Utility 的 Configure 菜单决定。
Typeset 按钮、⌘T 与引擎弹出菜单
⌘T 会先保存文件再排版;真正决定跑什么的,是 Typeset 按钮旁边那个弹出菜单(工具栏上标为 Program)。这些菜单项并没有写死在程序里。TeXShop 读取 ~/Library/TeXShop/Engines/ 文件夹,为它找到的每一个 .engine 文件列出一个条目,而所谓 .engine 文件,不过是一段以 $1 接收文件名的简短 shell 脚本。随附的 LuaLaTeX.engine 一共只有四行。这就是关于 TeXShop 最有用的一条事实:凡是你能在终端里敲出来的命令,都能放进那个菜单。菜单 TeXShop → Open ~/Library/TeXShop 可以直接打开这个文件夹。
#!/bin/tcsh
set path= ($path /Library/TeX/texbin /usr/texbin /usr/local/bin)
lualatex -file-line-error -synctex=1 "$1"这段脚本里的两个选项都有其道理,你自己写引擎时也应当照抄。-synctex=1 会生成 .synctex.gz 文件,正是它让后文的 ⌘ 点击能双向工作。-file-line-error 改变了报错的形状:不再是 TeX 传统的 l.42,而是 ./main.tex:42: Undefined control sequence.——有文件名和行号,就能跳过去。TeXShop 内建的 LaTeX 命令本身就带上了这两个(pdflatex --file-line-error --synctex=1),所以默认值相当合理;反倒是自制引擎最容易悄悄丢掉同步能力。新文档默认用哪个引擎,取决于你上一次的选择;在没有指定引擎名时走哪条路线(pdfTeX、TeX + DVI,还是自制脚本),则由首选项 → Typeset → Default Command 决定。
| 菜单项 | 实际运行的命令 | 什么时候选它 |
|---|---|---|
LaTeX | pdflatex --file-line-error --synctex=1(内建) | 默认项;以拉丁字母为主的文档够用 |
XeLaTeX | xelatex -file-line-error -synctex=1 | 通过 fontspec 使用系统字体,多文种混排 |
LuaLaTeX | lualatex -file-line-error -synctex=1 | 系统字体加上 Lua;新的日文文档首选 |
pdflatexmk | latexmk -pdf(驱动 pdfLaTeX) | 含参考文献、索引或交叉引用的文档;按一次即可完成 |
lualatexmk / xelatexmk | latexmk -pdf(驱动 LuaLaTeX / XeLaTeX) | 在 Lua 或 Xe 路线上获得同样的自动重跑 |
latexmk | latex → dvips → ps2pdf | 依赖 EPS 插图或 PSTricks 的旧稿 |
为什么排版一次不够:pdflatexmk 与「需要重跑」的警告
如果控制台最后一行是 LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.,那就说明屏幕上的 PDF 落后了一轮。LaTeX 在第一遍把标签、页码和目录写进 .aux 与 .toc,第二遍再读回来;所以有交叉引用的文档本来就需要跑两遍,有参考文献的还要在中间插一次 bibtex 或 biber。连按三次 ⌘T 确实管用,但数遍数不该是人干的活:latexmk 会比对辅助文件,恰好按需要的次数重跑,索引与文献处理也一并包办。
TeXShop 随附了这些引擎,却默认把它们关着,所以这是一次性的两分钟设置。打开 ~/Library/TeXShop/Engines/Inactive/Latexmk/,把 pdflatexmk.engine——或者 lualatexmk.engine、xelatexmk.engine——向上移两层到 ~/Library/TeXShop/Engines/,重启 TeXShop,名字就会出现在 Program 弹出菜单里。想先试试再决定也有捷径:菜单项 Typeset with Alternate Engine 会运行首选项 → Engine → Alternate Engine 里填的那个引擎,而该栏出厂就写着 pdflatexmk。当构建变得古怪——.aux 陈旧、标签死活解析不出来——按住 Option,Typeset 就会变成 Trash Aux & Typeset(⌥⌘T),先扔掉中间文件再重排。
% !TEX 行:root、TS-program 与 encoding
文件可以自带设置,而在合作项目里就应该这么做。把一行 % !TEX 放在文档开头二十行之内,TeXShop 就会读它;LaTeX 则视而不见,因为 % 之后的一切都是注释。这种不对称正是全部诀窍:文件自己告诉编辑器该怎么编译,于是传到合作者的机器上,指令也随之带走。常用的其实只有三条。
| 指示行 | 写法示例 | 作用 |
|---|---|---|
% !TEX root | % !TEX root = ../thesis.tex | 指定主文件。放在每个章节文件顶部后,在章节里按 ⌘T 也会编译整篇论文,SyncTeX 也才找得到回程 |
% !TEX TS-program | % !TEX TS-program = lualatexmk | 指定引擎,取值是 Engines/ 里去掉 .engine 的文件名。% !TEX program 是同义写法。优先于弹出菜单的选择 |
% !TEX encoding | % !TEX encoding = UTF-8 Unicode | 指定本文档的字符编码,仅对该文件覆盖首选项里的默认值 |
% !TEX root = ../thesis.tex
% !TEX TS-program = lualatexmk
% !TEX encoding = UTF-8 Unicode
% This chapter has no preamble of its own.
% Pressing Typeset here builds ../thesis.tex instead.
\chapter{Method}
\label{chap:method}三条里能救你一个下午的是 root。把论文拆成章节后,若没有这一行就在 chapter3.tex 里按 ⌘T,TeX 会开始读一个没有 \documentclass 的文件,读到第一句正文便撞上 ! LaTeX Error: Missing \begin{document}.。这里的路径是相对于章节文件本身的,所以放在 chapters/ 下的章节要用 ../thesis.tex 指回去。同一行也在告诉 SyncTeX:从 PDF 上 ⌘ 点击时该落到哪一章的哪一行。拆分文档的那一刻就该加上,而不是等出问题再去找。
编码:.tex 文件为什么会乱码,或者干脆打不开
自 TeXShop 4.00 起,出厂默认就是 Unicode (UTF-8),对今天新写的东西这就是正确答案;设置位置在首选项 → Source → Encoding。文本文件不带任何说明自身编码的头部,所以 TeXShop 猜不出来,也刻意不去猜。当文件不是合法的 UTF-8 时——西欧合作者用 IsoLatin9 写变元音,实验室档案里翻出来的旧稿——解码就会失败,TeXShop 会询问是否用回退编码 IsoLatin9 重新打开,这个回退值是固定的、不可配置。接受它,去看 \usepackage[...]{inputenc} 那一行弄清文件到底是什么编码,不保存直接关闭,再从 Open 对话框里选对编码重新打开;然后补上一行 % !TEX encoding,下一个人就不必再走一遍。
TeXShop 的日文支持正是沿着这条路来的,也是这个程序历史上最好的故事。在 Mac OS 9 时代,日文字体把反斜杠画成日元符号,而日文键盘上的日元键敲出来的是反斜杠字节,于是 \section 与 ¥section 是同一串字节,TeX 毫无察觉。后来 Unicode 把两个字符分了家,键盘开始输出真正的日元符号,日本的 TeX 便以接受 ¥ 作为 TeX 转义字符来应对——被落下的是 TeXShop。Koch 写道,他听说日本用户有麻烦大约一年之后,銭谷誠司(Seiji Zenitani) 才把原因解释和代码一并寄来;日文本地化也出自他手。銭谷又把他引荐给数学家 宍倉光広(Mitsuhiro Shishikura),后者送来了对日元问题更干净的修正,顺带还写了预览窗口的放大镜和宏编辑器。这两个名字至今仍与寺田侑祐(Yusuke Terada)、园部功(Isao Sonobe)一同列在 TeXShop 页面的致谢里。
中日韩文档:LuaLaTeX,还是 upLaTeX + dvipdfmx
如果是今天从零开始的文档,在 Program 弹出菜单里选 LuaLaTeX,事情就结束了。它原生读 UTF-8,能直接调用 Mac 上已装的字体,配合 luatexja 宏包或 ltjsarticle 之类的文档类,不需要额外机关就能排日文。中文和韩文对应的位置上是 XeLaTeX 加 xeCJK 或 ctex。这里唯一要避开的路是 pdflatex:pdfTeX 诞生于还无法方便取用 Unicode 字体的年代,硬要用它处理中日韩文,就得回到老式 CJK 宏包和预先转换字体的世界——今天没人会主动选这条路。
另一条路是 upLaTeX 加 dvipdfmx,这是日本出版业沿用数十年的组合,也是从课题组继承来的模板通常默认的那一套。TeXShop 为此专门备了一个复选框:首选项 → Engine → pTeX support (for Japan) 会把内建命令切换到 pTeX 系;~/Library/TeXShop/Engines/Inactive/Latexmk/ 里还有一个 dvipdfmxmk.engine,用来让 latexmk 驱动这条路线。自己写的话一行就够,而这一行正好说明了各部件如何衔接:ptex2pdf 是 TeX Live 附带的脚本,它先跑 TeX,再做 DVI 到 PDF 的转换;-l 表示走 LaTeX 而非 plain,-u 选用支持 Unicode 的 upTeX,-ot 则把附加选项转交给引擎本身。
#!/bin/sh
# a hand-written engine: upLaTeX, then dvipdfmx, with SyncTeX enabled
ptex2pdf -u -l -ot "-synctex=1 -file-line-error" "$1"这个选择比看上去要重,因为回头的代价并不低。为 upLaTeX 写的文档类(jsarticle、ujarticle)在 LuaLaTeX 下编译不过,反过来也一样,课题组论文模板里一半的宏同样如此。开头就决定一次;如果继承来的模板已经指名了引擎,就照着走,别在截稿前一周才想迁移。而让这个决定在别人的 Mac 上依然生效的,正是主文件开头那行 % !TEX TS-program。
SyncTeX:⌘ 点击在源码与 PDF 之间跳转
操作就是 ⌘ 点击,仅此而已。在预览窗口里 ⌘ 点击某个词,源码窗口就跳到生成它的那一行(反向搜索);在源码里 ⌘ 点击某一行,预览就滚到对应位置(正向搜索)。TeXShop 从 2.18 版起支持 SyncTeX,而所有标准引擎都会传 -synctex=1,所以开箱即用——每次排版后 PDF 旁边出现的 .synctex.gz 就是证据。万一失灵,查三件事:上次编辑之后是否至少排过一次版;自制引擎是不是把 -synctex=1 丢了;以及首选项 → Typeset → Sync Method 是否选在 SyncTeX 而不是老式的 pdfsync 上。
真正让工作方式改变的是校对环节。读 PDF、发现一句写坏了、再回到源码里在三百行中肉眼寻找——这整个循环消失了,你只需 ⌘ 点击那句话,然后开始改。不过在多文件项目里,只有每个子文件都带着自己的 % !TEX root 行,跳转才会落到正确的位置;没有它,TeXShop 并不知道这一页出自哪个主文件,点击就落空了。这和让你能在章节里按 ⌘T 的是同一行——所以拆分文档的那一刻就值得加上。
TeXShop,还是 TeXworks、TeXstudio、VS Code
TeXShop 胜在初学者真正需要的那一点——没有什么要配置的:装上 MacTeX,打开文件,按 ⌘T,就结束了。熟悉之后它也相当好用:Esc 键触发的命令补全、可以写成 AppleScript 的宏、可编辑的主题;而引擎文件夹意味着它不会因为「没听说过这条命令」就拒绝执行。它的限制同样清楚:没有项目侧边栏,没有内建版本控制,没有边打边编译,而且在非 Mac 机器上根本跑不起来。
- 只用 Mac、独自写作、不想在配置上花时间:TeXShop 就是默认答案,Program 弹出菜单加上
% !TEX行几乎足够。 - 在 Windows 或 Linux 上也要同样的手感:TeXworks 以 TeXShop 为范本,几乎可以原样迁移。
- 想在一个窗口里拥有结构浏览、符号面板和文献管理:TeXstudio 或 Texmaker。
- 本来就在有 Git、LSP 和终端的编辑器里写作:VS Code 加 LaTeX Workshop,底下仍然是 MacTeX。
- 合作者不肯安装任何东西:用 Overleaf 作为共享场所,把 TeXShop 留作本地定稿之用。