在VSCode里写LaTeX,最上头的不是编译报错,而是一遍遍敲那些又长又没法少的指令。\begin{figure}开头,\includegraphics、\caption、\label四五行排下来,手先麻了;要是导言区里还躺着自己定义的一堆\newcommand,写到一半不是忘了名字,就是得回头翻文件复制粘贴。这个问题说到底就一句:让VSCode的自动补全认识自定义指令。这篇我就把这件事彻底讲透,包括VSCode+LaTeX的补全机制、三条能走的配置路线、以及我踩过之后才明白的坑。适合所有用VSCode写LaTeX的人,不管你写论文、记笔记还是做模板,看完基本都能直接抄配置。
1. 先弄懂:VSCode里LaTeX补全到底是谁在工作
1.1 LaTeX Workshop 才是真正的补全主力
很多人装了VSCode后问“为什么没有补全”,十有八九是少装了一个插件:LaTeX Workshop。VSCode本身对LaTeX的命令补全几乎等于零,它只知道这是一堆文本文件。你需要用到的编译、预览、语法高亮,还有命令补全,基本都来自LaTeX Workshop这一个插件。你可以把它理解成VSCode里的LaTeX全能管家。
之前有个同学问我说插图时一直手敲,为什么不开补全,我说你搜来搜去不如下个插件。装好LaTeX Workshop之后,输入\be会提示\begin,输入\fra会提示\frac,这就是它内置的IntelliSense模块在干活。先把这个前提确认了,后面所有配置才有意义。
1.2 默认能补全什么,不能补全什么
LaTeX Workshop默认的补全范围其实相当大:标准LaTeX命令、常用环境、宏包名、交叉引用label、参考文献条目,还有\input这类文件路径。它甚至能做“上下文敏感”补全,比如在\ref{后面只提示带label的条目,在\cite{后面只提示bib里的key。
但它有一个明显盲区:它默认不关心你这篇文档里自定义的\newcommand。它内置的是一个通用LaTeX命令库,不是你的个人宏库。你写了\newcommand{\mycmd}[1]{...}之后,正常情况下输入\my也能补出\mycmd,但这里有附加条件,我在3.3节细说。如果你想要的不只是“补全已有命令”,而是“输入几个缩写字符,自动展开成一大段自定义模板”,那默认能力就更不够了,必须手动配置。
1.3 触发机制:什么情况下才弹提示
VSCode的补全提示默认在输入某些触发字符时弹出。LaTeX Workshop又把触发字符限定为\和@等。也就是说,你输入反斜杠、再输入几个字母,建议列表会自动弹出来;如果你输入普通字母,它不会主动蹦出来。这是很多用户觉得“没补全”的原因之一。
想让普通字母也能触发自定义命令,需要调整VSCode的editor.quickSuggestions,把other设为on,这样输入R时才会冒出一堆推荐。这个配置我放到3.4节具体讲,因为它不见得适合所有人。
2. 两条需求,三个方案,怎么选
2.1 先分清你要的是命令补全还是模板补全
动手配置之前,先想清楚一件事:你说的“自动补全自定义指令”,到底是哪一种需求?
- 第一种是命令级补全。我定义了一个
\abs宏,希望输入\abs之后能快速插入\left|...\right|;或者输入\R直接输出\mathbb{R}。这种本质上是“给命令名一个快捷方式”。 - 第二种是模板级补全。我写一个figure环境要五条命令,希望能输入
fig或者\fig之后,一次性把整个框架插进去,光标停在图片路径位置,按Tab跳到下一处。这种本质上是“给一段LaTeX模板一个快捷触发器”。
这两件事看着像,其实是两套工具干的活。命令级补全用LaTeX Workshop自身的配置就够,模板级补全更适合用HyperSnips或VSCode自带snippets。
2.2 三个方案横向对比
下面是我实际用下来对三个方案的理解,不吹不黑:
| 方案 | 上手难度 | 能补命令 | 能补多行模板 | 支持Tab跳转 | 适合谁 |
|---|---|---|---|---|---|
| LaTeX Workshop intellisense.commands | 低 | 强 | 弱,基本单行 | 支持简单$1、$2 | 只想给几个宏加快捷输入 |
| VSCode 自带 snippets | 中 | 弱,与LaTeX无感 | 强 | 支持 | 需要环境模板,又不想装新插件 |
| HyperSnips | 中高 | 强,任意匹配 | 强 | 支持 | 想要高度自定义,输入越少越好 |
这三个方案可以并存,互不冲突。我尤其推荐把HyperSnips也装上的原因,是它有一种独门绝技:正则表达式触发。你可以规定“只有输入\fr且后面跟空格时才展开”,或者“在数学环境内才触发某个缩写”,这是另外两个方案做不到的。
2.3 我常用的组合
我现在的配置是:LaTeX Workshop负责所有命令宏的补全,HyperSnips负责环境和常用模板,VSCode自带的snippets只用来存一些不常改的全局模板,比如投稿期刊的导言区。
说白了,命令类的东西放LaTeX Workshop里管理,因为它是LaTeX干活的主力,定义上去就生效;模板类的东西放HyperSnips里,因为它可以写很强的触发规则,不会误伤正文。这个分工让我写了半年多论文都没有再为补全烦恼过。
3. 实操:在LaTeX Workshop里配置自定义指令补全
3.1 打开配置文件
配置LaTeX Workshop不需要改插件源码,只需要改VSCode的settings.json。按Ctrl+Shift+P,输入Open User Settings (JSON),回车,就打开了用户配置文件。如果只想在当前项目里生效,就在项目根目录建.vscode/settings.json。
注意,用户配置影响所有项目,工作区配置只影响当前项目。我建议先配置到工作区,测试正常后再搬到用户区,这样就算JSON写错了,也不会把其他项目一起带崩。实际上VSCode对JSON语法错误会给出提示,但语法正确的“逻辑错误”才是排查起来最费劲的。
3.2 用 intellisense.commands 手动注册命令
这是对标题最直接的回答。LaTeX Workshop留了一个接口:latex-workshop.intellisense.commands,专门用来注册自定义命令补全。在settings.json里加一个数组,每一条就是一个命令。
"latex-workshop.intellisense.commands": [ { "name": "R", "detail": "实数集", "documentation": "\\mathbb{R}", "snippet": "\\mathbb{R}" } ]解释一下各字段:
name:提示列表里显示的名字,也是匹配词。比如输入R后回车,就把snippet内容插进去。detail:提示列表里的灰色说明文字,可以写中文解释。documentation:光标悬停在补全项上时显示的详细说明。snippet:实际插入文档的内容,支持$1、$2这种光标跳转占位符。
多配几个看看:
"latex-workshop.intellisense.commands": [ { "name": "R", "detail": "实数集", "documentation": "数学模式下的实数集写法", "snippet": "\\mathbb{R}" }, { "name": "abs", "detail": "绝对值", "documentation": "自动生成 \\left|...\\right|", "snippet": "\\left| $1 \\right|" }, { "name": "pdv", "detail": "偏导数", "documentation": "\\frac{\\partial #1}{\\partial #2} 形式的偏导数", "snippet": "\\frac{\\partial $1}{\\partial $2}" } ]这里要特别提醒一点:snippet里的反斜杠在JSON字符串里必须写成\\,否则解析会出问题。我第一次写的时候直接填了\mathbb{R},结果配置后毫无反应,排查了半天才发现是JSON转义问题。
还有一个核心技巧:name不一定要和最终命令名一致。你想实现“输入部分字符就补全”,完全可以这么写:
{ "name": "mc", "detail": "展开为我自定义的 \\mycmd", "documentation": "输入 \\mc 后展开成 \\mycmd{...}", "snippet": "\\mycmd{$1}" }这样在文档里输入\mc,提示列表里出现mc,回车后直接插入\mycmd{...},光标停在花括号里。这就严格实现了一个缩写到长命令的映射,比必须记住全名舒服多了。
3.3 让文档里的 \newcommand 自动进入补全列表
如果不想在settings.json里一个个注册,而是希望LaTeX Workshop自动识别文档里用\newcommand定义的所有命令,这事它默认就会做,只是稳定性没有手动注册那么高。具体来说,LaTeX Workshop在打开文档、保存、编译时会扫描.tex文件里的宏定义,把\newcommand{\foo}{...}、\renewcommand、\providecommand、\def等定义的命令加入补全列表。
但有三个前提条件:
- 宏定义要写在文档导言区,也就是
\documentclass之后、\begin{document}之前。写在正文里的宏经常扫不到。 - 如果宏定义放在单独的
.sty文件里,必须能被当前文档通过\usepackage或\input引用到,插件才会去扫描那个文件。 - 刚新增的宏,补全列表不会立刻刷新。需要手动编译一次,快捷键通常是
Ctrl+Alt+B,或者执行Developer: Reload Window重载窗口。
这里还有一个小坑:用\makeatletter和\makeatother包起来、包含@符号的私有命令,LaTeX Workshop有时候识别不了。我有一次把一堆内部宏定义在\makeatletter里面,结果补全里一个都看不见。后来改成\newcommand,或者在latex-workshop.intellisense.commands里手动补上,才彻底解决。
如果希望每次输入时都能及时更新,可以开启latex-workshop.intellisense.update.aggressive.enabled并设为true。开启后插件会更积极地重新扫描文档,代价是消耗一点性能,文档特别大的时候会有明显卡顿。我建议只在文档撰写中后期、需要频繁更新宏时临时打开,平时保持默认就好。
3.4 顺手调优触发体验
配置完命令后,会遇到一个体验问题:输入普通字母如R时,如果不加反斜杠,VSCode默认不弹提示,因为LaTeX Workshop的默认触发字符是\。想让不带反斜杠的单词也能触发,需要在VSCode设置中开启普通字符的快速建议:
"editor.quickSuggestions": { "other": "on", "comments": "off", "strings": "off" }不过实测下来,我建议不要全局开启。因为R这种单字母提示会特别泛滥,满屏都是推荐。更稳妥的做法是:保持默认触发规则,写命令时开头就输入\,提示自然出现;只有对某几个高频缩写,才用HyperSnips那种“不带反斜杠也能触发”的方案。
还有一个细节:输入\后弹出的提示列表里,既有内置命令又有自定义命令,如果觉得太乱,可以在设置里关掉一部分内置补全源。比如latex-workshop.intellisense.package.enabled控制是否扫描宏包命令,latex-workshop.intellisense.option.enabled控制选项类补全。我通常保留unused.enabled开启,因为提示未使用宏包这个功能平时挺有用。
4. 进阶玩法:用HyperSnips实现“少输入、多输出”
4.1 HyperSnips能解决什么问题
如果你觉得前面的配置都只是“补全命令”,还不过瘾,希望“输入fr就得到整个分式,输入fig就建好整个图片环境”,那就要上HyperSnips了。HyperSnips是VSCode里的Snippets增强插件,思路是从Vim的UltiSnips迁移过来的。它的核心是让你编写.hsnips文件,用固定字符串或正则表达式定义触发器,触发器一旦命中,自动把模板内容插入文档。
和VSCode自带snippets相比,HyperSnips的优势有两点:一是触发规则更灵活,支持正则;二是它可以做“无感知触发”——不弹提示列表,输入完直接展开。这在日常写作中比“弹出提示再按回车”顺滑得多。
4.2 创建并编写 .hsnips 文件
安装HyperSnips插件后,按Ctrl+Shift+P执行HyperSnips: Open Snippets File,选择latex语言,它会创建或打开一个latex.hsnips文件。如果你同时写article和beamer,都算tex系,可以在同一个文件里配置,或者再开一个tex.hsnips。
.hsnips文件的基本语法:
snippet "触发器" "描述" "选项" 展开内容 endsnippet一个最简单的例子:
snippet "\\R" "实数集" A \mathbb{R} endsnippet这段配置的意思是:在文档中输入\R,立刻展开成\mathbb{R}。A表示自动展开,不需要按Tab或回车确认。如果去掉A,则还需要按一次Tab才展开。我个人喜欢保留A,效率更高。
文件保存后立即生效,一般不需要重载窗口。唯一的例外是你改了文件命名,比如从latex.hsnips换到tex.hsnips,那需要重载一次窗口让它重新识别。
4.3 实战案例:从单命令到复杂模板
先来个单命令,解决高频数学符号。注意占位符我统一用$1、${1}这套和VSCode一致的写法,避免混乱。
snippet "\\abs" "绝对值" A \left| $1 \right| endsnippet输入\abs后,内容插入,光标停在$1的位置,输入内容后按Tab跳到$2。如果只有$1,一跳就结束。
再来复杂模板。写论文时最常用的一张图流程是figure环境加一行includegraphics,我配置成这样:
snippet "\\fig" "figure环境" A \begin{figure}[htbp] \centering \includegraphics[width=0.8\linewidth]{$1} \caption{$2} \label{fig:$3} \end{figure} endsnippet输入\fig后,上面五段内容一次性插入,光标停在$1也就是图片路径处,填完路径按Tab跳到$2写标题,再到$3写label。全程不用动鼠标,体验非常顺滑。
类似的模板可以无限堆:eq对应equation环境、tm对应定理环境、code对应lstlisting。这就是模板级补全的威力。
4.4 正则和数学环境的进阶技巧
HyperSnips最强大的是正则触发器。可以把一个模式写成触发器,让它匹配固定模式下的任意内容。比如:
snippet `\frac(\w)` "分式快捷方式" A \frac{$1}{} endsnippet这里用了反引号包围正则,\frac(任意单词字符),当你输入\frac x时,会展开成\frac{x}{}。但我实测这种正则容易误触发,比如文中已有\frac{\partial x}{\partial y}时,它可能再套一层。保险的做法是尽量用更严格的正则,或者给触发器加单词边界。
如果你只想在数学环境下才触发某些缩写,HyperSnips可以通过context做条件判断。大致思路是在.hsnips文件里声明数学环境上下文,后面的snippet就只在数学模式内生效。具体语法会跟随插件版本略有差异,建议先看一眼插件的README确认。这个能力很实用,它能在正文里避免输入某些缩写时被莫名展开,但进了公式就随心所欲。
5. 常见问题与排查实录
5.1 配置了不生效,先查这三点
遇到配置不生效,我基本按这个顺序排查。第一是JSON语法,settings.json里如果有肉眼看不出的逗号缺失或引号配对错误,配置就是废的。把光标放到文件任意位置看有没有红色波浪线,基本能排除。第二是键名拼写错误,latex-workshop.intellisense.commands这个键名很长,很容易少写一个s或者把intellisense拼错。第三是没有重载窗口,JSON配置保存后理论上会立即生效,但我在某些VSCode版本上遇到过不重载不刷新的情况,执行Developer: Reload Window往往就通了。
5.2 为什么我的 \newcommand 没有出现在提示里
宏定义在导言区吗?在导言区的话,手动触发一次编译了吗?如果这两点都满足还是不出现,建议直接往latex-workshop.intellisense.commands里显式注册。尤其是那些带@符号、在\makeatletter里定义的命令,别费劲排查了,直接手动加。另外,如果你的.sty文件和主文档不在同一目录,记得检查文件是否真的被\usepackage引入了。LaTeX Workshop不会去扫磁盘上所有的.sty,它只扫当前文档及其依赖。
5.3 HyperSnips不触发?大概率是这些原因
HyperSnips配置文件必须放在正确位置并且命名正确。如果打开的是.tex文件但VSCode右下角显示的语言不是latex,辣么HyperSnips的latex snippets就不会生效,先把语言切换对。还有一种情况是正则触发器写错了,可以先试一个最简单的固定字符串snippet,比如输入zzz展开成test,确认插件整体工作后再叠加规则。最后,触发器如果和LaTeX Workshop的补全撞了,比如两边都定义了\fig,可能会弹出两个提示,这时保留一个就好。
5.4 补全列表太乱或误触发怎么办
补全列表乱,根源在于触发源太多。解决办法是关掉或调低LaTeX Workshop里用不到的补全类型,比如宏包命令、环境选项。误触发的典型场景是:在普通正文里输入一个本该只在公式里用的缩写,结果一下子就展开了。对策有两种:一是给缩写加上触发后缀,比如要求后面跟一个空格或特殊字符再展开;二是使用HyperSnips的数学环境上下文,只在数学模式内触发。经过这两步调整,误触发基本能压到最低。
5.5 问题速查表
再给一张表,遇到问题时直接对号入座:
| 现象 | 可能原因 | 快速处理 |
|---|---|---|
输入\没有任何提示 | LaTeX Workshop未安装或触发设置被关闭 | 安装插件;检查latex-workshop.intellisense.triggerCharacters |
| 自定义命令提示不出现 | JSON配置语法错误;name与输入不一致 | 检查转义;确认name是实际输入的词 |
文档里\newcommand定义的命令不提示 | 未编译索引;宏定义在正文或\makeatletter内 | 编译一次;改到导言区;手动注册 |
输入\my匹配不到\mycmd | 内置命令太多,模糊匹配优先级不高 | 用intellisense.commands显式映射缩写 |
| HyperSnips不展开 | 当前文件语言不对;正则出错;未保存 | 确认.tex语言;试zzz;检查正则 |
| 普通字母不触发提示 | editor.quickSuggestions.other为off | 按需开启,或改用HyperSnips直接展开 |
| 误触发或弹窗满天飞 | 触发源过多,或缩写太短 | 关闭不必要补全源;增加触发上下文 |
这些坑我基本都踩过一遍,写出来就当帮你省时间了。
最后再分享一点实际心得。最初我图省事,把大量宏定义堆在导言区,指望LaTeX Workshop把它们全部自动识别。后来发现,识别归识别,但“短触发”这件事还得靠手动注册。尤其是\R这种单字母命令,LaTeX Workshop不会在输入\R时就乖乖展开成\mathbb{R},很多时候你要么在提示列表里翻找,要么回车都轮不到它。后来我把最常用的十几个宏全部用intellisense.commands注册了一次,又把figure、table这些环境模板交给HyperSnips,补全体验才算彻底稳下来。建议你也按这个思路动手试一遍,配置不复杂,一次调通之后,每天写LaTeX能省下不少手指。