VS Code + HyperSnips + $\LaTeX$笔记速记
你是否想要在上课的时候随着老师讲课写出笔记?你是否钦慕电子笔记工整漂亮的公式?或者你只是想快点写 \(\LaTeX\) 公式?本教程将试着教你如何使用 VS Code + HyperSnips + \(\LaTeX\) 记数学笔记。
内容包括:
- TeX Live 在 Windows 或 Linux 下的安装。
- VS Code 的配置。
- HyperSnips 的配置,并详细解释为什么要这样配置。
我们的目标是在 VS Code 中达到与 Gilles Castel 相当的速度(与手写一样快)。
在用本教程方法之前,您应当注意:
- markdown 与 typst 也可以用来记笔记,并且远没有 \(\LaTeX\) 这样复杂。如果您的笔记没有「高度定制」的内容,请优先考虑它们。
- 本教程的配置内容相当繁琐,并且您(至少)需要 1-2 周的练习才能达到上课跟记笔记的速度。
- 本教程的配置相当私人化(部分配置基于我自己认为更舒服的习惯或感受),您可能需要根据自己的需求进行修改。
TeX Live 安装(Linux)
本节内容根据王然老师的教程对 Linux 的安装进行了修改。
若您是 Windows 或 macOS 用户,请参考他的教程。
请不要使用
sudo apt install texlive-full
,因为远挰的包并不一定是最新的,因此
tlmgr
会出错,并且它会导致本地环境相当混乱。因此,推荐通过
.iso
安装。
建议在 TUNA 下载镜像,你可以在主页右侧“获取下载链接”——“应用软件”——“TeX 排版系统”找到,或是在这个页面找到最新的镜像。
同时,执行以下命令安装必要的软件:
1 | sudo apt install fontconfig gedit vim -y |
下载后,进入下载目录(文件管理器找到位置,右键终端打开),挂载
.iso
文件,并执行 install-tl
。
1 | sudo mkdir /mnt/texlive |
点击 I
进行默认安装,然后等待安装完成。
安装完成后,执行
1 | sudo umount /mnt/texlive |
即可卸载镜像。
配置环境变量
接下来,我们需要配置环境变量。复制以下代码到终端中并执行(注意,要修改第 19 行的年份):
1 | # 检测当前用户的 shell |
此时,在终端中执行
tex --version
,若输出类似如下的内容,则说明安装成功:
1 | TeX 3.141592653 (TeX Live 2024) |
配置字体
接下来刷新处理字体缓存:
1 | year=2024 # 请替换为你的年份 |
tlmgr
配置
建议直接处理好 tlmgr
的设置:
1 | sudo visudo |
在打开的文件中找到 Defaults secure_path
,在引号最后加上
:/usr/local/texlive/2024/bin/x86_64-linux
,然后使用
Ctrl + S, Ctrl + X
退出。
对该命令的解释
sudoers
是一个配置文件,它规定了哪些用户可以以怎样的身份运行什么程序。sudoers
文件的位置在
/etc/sudoers
,但是不要直接编辑这个文件,因为这个文件的语法很复杂,而且一旦出错,就无法使用
sudo 命令了。visudo 是一个编辑 sudoers
文件的工具,它会检查语法错误,避免出现错误。所以,我们使用 visudo 来编辑
sudoers 文件。
在 PATH 变量环境中不同的路径之间用 :
分隔。
最后执行
1 | sudo tlmgr option repository ctan |
即可完成 TeX Live 的安装。
VS Code 配置
首先,安装 VS Code。
然后,安装以下插件(Ctrl + Shift + X
打开插件商店):
- LaTeX Workshop
- HyperSnips for Math
接下来,我们需要配置 VS Code 的设置。
Ctrl + Shift + P
打开命令面板,输入
首选项:打开用户设置(JSON)
,打开
settings.json
。
复制以下代码到 settings.json
:
1 | "latex-workshop.latex.autoBuild.run": "onSave", |
此时,你的 .tex
文件应该可以正常编译了。找个文件夹,新建一个 .tex
文件,输入以下内容:
1 | \documentclass{article} |
编译器的选择
当你不知道该用什么时选择 xelatex
配方。
LaTeX 是一个排版系统,而不是一个编程语言。因此,它需要一个编译器来将
.tex
文件编译成 .pdf
文件。常见的编译器有
pdflatex
, xelatex
,
lualatex
。我们安装的 TeX Live
包含了这三个编译器,以及一些其他的工具。
pdflatex
是旧的 TeX 语言的实现,并不支持 Unicode 字符和 OpenType 字体。但是,它的兼容性很好(可以使用一些老的包),因此在一些老的模板中仍然使用。xelatex
是基于 XeTeX 的实现,支持 Unicode 字符和 OpenType 字体。它是现在最常用的编译器。lualatex
是基于 LuaTeX 的实现,支持 Unicode 字符和 OpenType 字体,同时还支持 Lua 语言。它的速度比xelatex
快,但是在一些包的兼容性上不如xelatex
。
我们的配方还提供了 xelatex-minted
和
pdflatex-minted
,这两个配方支持 minted
包,这是一个用于代码高亮的包。该配方编译时多了
--shell-escape
参数,因为该包通过调用外部
pygments
程序来进行代码高亮。但是,该参数使得编译过程中可以执行外部程序,因此可能会有一些安全问题,因此平常不建议使用这两个配方。
配方中还有一些链配方,如
xelatex -> bibtex -> xelatex*2
,这种配方可以在编译时自动编译参考文献。这种配方在第一次编译时会生成
.aux
文件,第二次编译时会生成 .bbl
文件,第三次编译时会将参考文献插入到文档中。在没有参考文献的情况下这个配方会报错,因此在没有参考文献的情况下使用
xelatex
配方即可。
此外,本人没有用过 biblatex
,因此没有配置
biber
,如果你需要使用
biblatex
,请自行配置。
保存后编译,VS Code 下方栏应该出现一个
√
,表示编译成功,并生成了一个 .pdf
文件。焦点在 .pdf
文件上,按
Ctrl + Alt + V
,应该可以看到预览。
双向检索
双向检索是指在 PDF
中双击可以跳转到源文件,而在源文件中按快捷键可以跳转到
PDF。这个功能需要在编译时生成 .synctex.gz
文件,因此需要在编译时添加 -synctex=1
参数。
LaTeX workshop 默认的使用 Ctrl + Alt + J
进行
.tex
文件到 .pdf
文件的跳转,并且我们在上面的配置中将双击 PDF 文件作为 .pdf
文件到 .tex
文件的跳转。
编译纠错
若编译出错,VS Code 底部会出现一个 ×
。在
.tex
文件中,错误的行会被标记出来。但是,有时候错误信息并不明确,这时可以使用
Ctrl + Alt + X
打开 LaTeX Workshop
的侧边栏,选择 “查看日志消息” - “查看 LaTeX
编译日志”,可以找出错误的原因。
HyperSnips 配置
Ctrl + Shift + P
打开命令面板,输入
HyperSnips: Open Snippets Directory
,打开
snippets
文件夹。在其中新建 latex.hsnips
文件,并输入以下内容:
1 | global |
使用说明
代码片段的核心思想就是通过能够较快输入的字符(触发字符,最好短、并且不容易与其他字符冲突)来触发代码片段的生成,从而减少输入时间。
HyperSnips 的代码片段是通过正则表达式来匹配触发字符的,并且由 Orange X4 大佬开发的版本支持代码片段只在数学环境下触发。
每个代码片段的格式如下:
1 | snippet 触发字符 "代码片段描述" 触发条件 |
其中:
- 触发字符:触发代码片段的字符,可以是一个字符串,也可以是一个正则表达式。
- 代码片段描述:代码片段的描述,用于在代码片段提示框中显示。
- 触发条件:触发代码片段的条件,可以是
i
(在词语内部也会触发)、A
(自动展开)、m
(数学模式)。 - 代码片段内容:代码片段的具体内容,支持使用光标位置、传入参数、使用函数等。
光标位置是由 vscode-snippet 的语法来实现的,可以通过
${1}
、${2}
等来表示光标位置,${0}
表示最终的光标位置。
传入的参数是片段中类似 ``rv = m[1]``
这样的代码,其中
m[1]
表示第一个传入的参数,rv
表示返回的结果。
这里提供了一些常用的代码片段的速查表,可以根据自己的需求进行修改。代码现已经过编辑尽可能不冲突,并符合 LaTeX 的语法习惯。
代码片段速查表
触发方式 | 代码片段描述 | 说明 |
---|---|---|
lm | Inline Math | 生成行内数学公式,即 $...$ 。 |
eqt | Equation | 生成 equation 环境,即
\begin{equation} ... \end{equation} 。 |
eqs | Equation* | 生成 equation* 环境,即
\begin{equation*} ... \end{equation*} 。其为不编号的行间公式。 |
选中文本后按 // |
Fraction | 将选择的文本放在分子上,\frac{分子}{分母}
在数学环境中生成分式 |
输入一个变量名后按 / |
Fraction no () | 变量符合“数字 字母 (下滑线)数字”的格式,如 11x_{31} |
(内容)/ |
Fraction with () | 将括号内的文本放在分子上,分母为括号,即生成
\frac{括号内的内容}{} |
文字+hbar | Bar | 效果如 \(\overline{a}\)(Overline 的 上划线更长,适合长文本) |
文字+htd | Tilde | 效果如 \(\tilde{a}\) |
文字+bar | Bar | 效果如 \(\bar{a}\) (Bar 的 上划线更短,适合单字母) |
文字+hat | Hat | 效果如 \(\hat{a}\) |
文字+hvec | Vector postfix | 效果如 \(\vec{a}\) (Vector 的箭头更短) |
文字+rta | Vector postfix | 效果如 \(\overrightarrow{a}\) |
dot | Dot | 效果如 \(\dot{a}\) |
hdd | Ddot | 效果如 \(\ddot{a}\) |
hsq | Sqrt | 效果如 \(\sqrt{a}\)
(其中,\sqrt[n]{a} 为 n 次根号) |
dig | Degree | 效果如 \(a^{\circ}\) |
pow | Power | 效果如 \(a^{b}\) |
sb | Subscript | 效果如 \(a_{b}\) |
}xx(xx 为相同数字) | Auto subscript | 将相同数字的内容自动转换为下标,如 }11 变为
_{1} |
a2 |
Auto subscript | 将字母后跟的数字自动转换为下标,如 a1 变为
a_{1} |
a_{2}3 |
Auto subscript | 将字母后跟的两个数字自动转换为下标,如 a_{1}2 变为
a_{12} |
taa | Auto subscript 2 | 将字母后跟的相同小写字母自动转换为下标,如 aaa 变为
a_a |
希腊字母+aa(两个相同字母) | Auto subscript for greek letter | 将希腊字母后跟的小写字母自动转换为下标,如 \alphaaa
变为 \alpha_{a} |
txt | Text | 效果如 \(\text{a}\),用于普通文本 |
tit | Text it | 效果如 \(\textit{a}\),用于斜体文本 |
mbb | Mathbb | 效果如 \(\mathbb{A}\),用于黑板粗体字母 |
RR、NN、ZZ、QQ、CC | R、N、Z、Q、C | 数集符号 \(\mathbb{R N Z Q C}\),即黑板粗体字母的快速写法 |
文字 + bf 或 BF | Mathbf | 效果如 \(\mathbf{a}\),用于正体加粗 |
文字 + bm 或 BM | Mathbm | 形成 \bm{a} ( markdown 不含此效果) |
文字 + bs | Boldsymbol | 效果如 \(\boldsymbol{a}\),用于粗体符号 |
文字 + sf | Mathsf | 效果如 \(\mathsf{a}\),用于无衬线体 |
文字 + frak | Mathfrak | 效果如 \(\mathfrak{a}\),用于斯拉夫字体 |
文字 + cal | Mathcal | 效果如 \(\mathcal{A}\),用于花体字母。由于花体只支持大写字母,因而自动转大写 |
文字 + rm | Mathrm | 效果如 \(\mathrm{a}\),用于正体字母 |
文字 + opn | Operatorname | 效果如 \(\operatorname{a}\),用于定义算子(例,如默认无 \(\operatorname{rank}\) 算子,可使其以算子字体渲染) |
oo | infinity | 生成 \(\infty\) |
... | cdots | 生成 \(\cdots\),对应代码为
\codts 。 |
cdots; | vdots | 生成 \(\vdots\),对应代码为
\vdots 。即,先按 ... ,再按 ;
就等效输入 vdots |
vdots; | ddots | 生成 \(\ddots\),对应代码为
\ddots 。同上理。 |
12;; | 0, 1, 2, ..., n | 按n和n+1连续增加数字,生成
a_1 b_1, a_2 b_2, \ldots, a_n b_n ,其中 a
b n 可以分别修改。 |
12.. | 0, 1, 2, ..., n | 同上理,生成 a_1, a_2, \ldots, a_n |
12,, | 0, 1, 2 | 类似地,生成 a_1, a_2 |
<> | Diamond | 生成 \(\diamond\) |
+... 或 -... |
Smart cdots | 生成
\cdots ,用于表示省略号。若前面有空格,则保留空格。 |
,... |
Smart ldots | 生成
\ldots ,用于表示省略号。若前面有空格,则保留空格。 |
** | Dot multiply | 生成 \(\cdot\),用于表示点乘。 |
+- | pm | 生成 \(\pm\),用于表示正负号。 |
-+ | mp | 生成 \(\mp\),用于表示负正号。 |
xx | Cross | 生成 \(\times\),用于表示乘号。 |
eps | Epsilon | 生成 \(\epsilon\),用于表示希腊字母 epsilon。 |
veps | Varepsilon | 生成 \(\varepsilon\),用于表示希腊字母 varepsilon。 |
ell | Ell | 生成 \(\ell\),用于表示希腊字母 ell。 |
log | Log | 生成 \(\log\),用于表示对数函数。 |
bin | Binom | 生成 \(\binom{a}{b}\),用于表示二项式系数。 |
oth | Otherwise | 生成 \(\text{otherwise}\),用于表示其他情况。 |
star | Star | 生成 \(^{*}\),用于表示上标星号。 |
U | tocorret | 生成 \(\Upsilon\),用于表示希腊字母
Upsilon。此条是为了纠正由于打一半 psi 展开为
\psi 导致的错误。 |
u | tocorret | 生成 \(\upsilon\),用于表示希腊字母 upsilon。同上。 |
(空格)in | notin | 生成 \(\notin\),用于表示不属于。由上片段输入
not 会自动变为
\not 带空格的版本,因而加此条。 |
(空格)EE | notexists | 生成 \(\nexists\),用于表示不存在。由上片段输入
not 会自动变为
\not 带空格的版本,因而加此条。 |
inn | in | 生成 \(\in\),用于表示属于。 |
(空格)ot | lnot | 生成 \(\lnot\),用于表示逻辑非。 |
varGamma | varGamma | 生成 \(\varGamma\),用于表示希腊字母 varGamma。 |
\pii |
p_i | 生成 \(p_i\),用于表示下标 i 的
p。为 \pi 的纠正。 |
sse | Subseteq | 生成 \(\subseteq\),用于表示子集等于。 |
sqs | Sqs | 生成 \(\sqsubseteq\),用于表示平方子集等于。 |
tto | To | 生成 \(\to\),用于表示箭头符号。 |
-< | Leftrightarrow | 生成 \(\leftrightarrow\),用于表示双向箭头符号。 |
<- | Leftarrow | 生成 \(\leftarrow\),用于表示左箭头符号。 |
li | Limits | \sin\limits_{a}^{b} 生成如 \(\sin\limits_{a}^{b}\),用于表示上下限。 |
-> | To | 生成 \(\to\),用于表示箭头符号。 |
!> | Mapsto | 生成 \(\mapsto\),用于表示映射到符号。 |
=> | Implies | 生成 \(\implies\),用于表示蕴含符号。 |
=< | Implied by | 生成 \(\impliedby\),用于表示被蕴含符号。 |
iff | If and only if | 生成 \(\iff\),用于表示当且仅当符号。 |
EE | Exist | 生成 \(\exists\),用于表示存在符号。 |
AA | Forall | 生成 \(\forall\),用于表示全称量词符号。 |
bec | Because | 生成 \(\because\),用于表示因为符号。 |
thr | Therefore | 生成 \(\therefore\),用于表示所以符号。 |
>= | Greater than | 生成 \(\geqslant\),用于表示大于等于符号。 |
dis | Displaystyle | 生成
\displaystyle ,此命令加在行内的数学公式前,可以使其显示为行间公式(更高的版本)。 |
<= | Less than | 生成 \(\leqslant\),用于表示小于等于符号。 |
!= | No equals | 生成 \(\neq\),用于表示不等于符号。 |
== | Constant equals | 生成 \(\equiv\),用于表示恒等符号。 |
sim | Sim | 生成 \(\sim\),用于表示相似符号。 |
eq | Simeq | 生成 \(\simeq\),用于表示约等于符号。 |
~~ | Approx equals | 生成 \(\approx\),用于表示近似等于符号。 |
~= | Congruent equals | 生成 \(\cong\),用于表示全等符号。 |
>> | Much greater than | 生成 \(\gg\),用于表示远大于符号。 |
<< | Much less than | 生成 \(\ll\),用于表示远小于符号。 |
and | & | 生成 & ,用于表示对齐符号。 |
case | Cases | 生成 cases 环境,即
\begin{cases} ... \end{cases} 。 |
ali | Aligned | 生成 aligned 环境,即
\begin{aligned} ... \end{aligned} 。 |
ceil | Ceil | 生成
\left\lceil ... \right\rceil ,用于表示向上取整。 |
floor | Floor | 生成
\left\lfloor ... \right\rfloor ,用于表示向下取整。 |
set | Set | 生成 \{ ... \mid ... \} ,用于表示集合。 |
norm | Norm | 生成 \left\| ... \right\| ,用于表示范数。 |
abs | Absolute value | 生成
\left\lvert ... \right\rvert ,用于表示绝对值。 |
Vert | Verts | 生成
\left\Vert ... \right\Vert ,用于表示双竖线符号。 |
beg | Begin | 生成 \begin{ ,搭配 VS code
的自动补全功能,可以快速生成环境。 |
taylor | Taylor | 生成 \(\sum_{k=0}^{\infty} c_k (x-a)^k\),用于表示泰勒级数。 |
lim | Limit | 生成 \(\lim_{n \to \infty}\),用于表示极限。 |
sum | Sum | 生成 \(\sum_{min}^{max}\),用于表示求和。 |
SUM | Common sum | 生成 \(\sum\),用于表示求和符号。 |
prod | Product | 生成 \(\prod_{n=1}^{\infty}\),用于表示连乘。 |
part | Partial derivative | 生成 \(\frac{\partial V}{\partial x}\),用于表示偏导数。 |
ndiff | d/dx | 根据 n 生成 \(\frac{\mathrm{d}y}{\mathrm{d}x}\),用于表示导数。n
表示 n 次导。 |
dd | dd | 生成 \(\mathop{}\!\mathrm{d}\),用于表示微分符号。使用
\mathop{}\!\mathrm{d} 代替 \mathrm{d}
的好处是可以正确的显示微分号前的空格。 |
buu | Bigcup | 生成 \(\bigcup_{i \in I}\),用于表示大并集符号。 |
bnn | Bigcap | 生成 \(\bigcap_{i \in I}\),用于表示大交集符号。 |
dint | Integral | 生成 \(\int_{-\infty}^{\infty} \, \mathrm{d}x\),用于表示积分符号。 |
label | label | 生成形如 \label{randlabel:kgy0ntirtd}
的标签,用于交叉引用。标签中有 10 位随机字符。 |
代码片段补充说明
可以搜索中间的名称直接找到对应的代码片段,例如搜索
Fraction
就可以找到分式的代码片段。除了lm
、eqt
、eqs
三个片段,其余片段都按照在原文件中的顺序排列。自 710 行后部分不常用的片段,没有在表格中列出,可以自行查看。
支持自动为算符和希腊字母等添加反斜杠,由
integrate
、min|max|argmin|argmax|sup|inf
、function
、greek
、logic operator
、logic symbols
、math function
片段定义。其中,
min|max|argmin|argmax|sup|inf
一条片段在符号后自动上空格,这是考虑到这些符号通常后面会有空格,并且如果不加空格易触发其他片段。部分片段是为了纠正错误出现的,例如
U\psilon
、u\psilon
是由于打一半psi
展开为\psi
导致的错误。\(\LaTeX\) 的数学符号和环境非常多,这里只列出了一部分常用的片段,如果有其他需要,可以自行添加。
在 \(\LaTeX\) 中,
\left
和\right
用于生成自适应大小的括号,可以用于生成各种括号,如圆括号、方括号、大括号等。不过,其大小大于公式高度(括号稍低于公式符号会美观些),并且不能换行,因此提供了 big、Big、bigg、Bigg 四种大小的括号(大小依次增大,固定高度),其用法为:)big
,生成\bigl( \bigr)
。其余}
、]
、|
同理。如 \(\displaystyle\bigl( \frac{a}{b}\bigr)\)。)Big
,生成\Bigl( \Bigr)
。如 \(\displaystyle\Bigl( \sum_{min}^{max}\Bigr)\)。)bbig
,生成\biggl( \biggr)
。)BBig
,生成\Biggl( \Biggr)
。
问题
VS code 默认的补全提示是允许使用 Tab 或者 Enter 键进行选择的,但是在打大量公式时,Enter 键有时会导致换行,有时导致补全(取决于补全提示框是否加载出来),因此建议使用 Tab 键进行选择。关闭 Enter 键的选择功能可以在设置中搜索
editor.acceptSuggestionOnEnter
,将其设置为off
。但是 Tab 键本身也和代码片段的光标位置有冲突,还没有解决方案。由于不少片段需要在数学环境外触发,同时又出现在英文单词内(如
lm
、eqt
、eqs
等),因此在输入这些单词时可能会触发代码片段。这里没有解决方案,只能尽量不在.tex
文件中输入英文。输入法切换还有点麻烦的。有插件vscode-smart-ime可以解决这个问题,但由于 ibus 无法改切换输入法键,只能在 fcitx 下使用。