配置 LaTeX 公式自动补全

首先安装 HyperSnips - Visual Studio Marketplace 插件。

安装完成后,按下快捷键 Ctrl + Shift + P,输入命令 Open Snippets Directory,就可以打开一个文件夹。在该文件夹新建一个文件 markdown.hsnips

从下面这些 snips 中选择你需要的复制进去,或者自己写你需要的 snip(拉到文末教你怎么写)。

snips 来源:OrangeX4、自己写的

数学环境支持(必需

用于检测当前位置是否在数学公式内部。

此代码为全局代码,后面所有数学公式内的替换都依赖于此代码。

global
function math(context) {
    return context.scopes.some(s => s.includes("math"));
}
endglobal

分数线

功能是把斜杠 / 替换成分数 \frac{}{}。分为两类。一类是无括号分数:

1/ -> \frac{1}{}
a_1/ -> \frac{a_1}{}
a+b^2/ -> a+\frac{b^2}{}

context math(context)
snippet `((\d+)|(\d*)(\\)?([A-Za-z!]+)((\^|_)(\{\d+\}|\d))*)/` "Fraction no ()" iA
\frac{``rv = m[1]``}{$1}$0
endsnippet

对于上面的 a+b^2 这个例子,如果我们需要指定把 a+b^2 作为分子,那就需要添加括号。有括号分数:

(a+b^2)/ -> \frac{a+b^2}{}
((a+b^2))/ -> \frac{(a+b^2)}{}

context math(context)
snippet `[^\$]*\)/` "Fraction with ()" iA
``
    let str = m[0];
    str = str.slice(0, -1);
    let lastIndex = str.length - 1;

    let depth = 0;
    let i = str.length - 1;

    while (i > -1) {
        if (str[i] == ')') depth += 1;
        if (str[i] == '(') depth -= 1;
        if (depth == 0) break;
        i -= 1;
    }
    
    if (i == -1) rv = m[0];
    else{
        let results = str.slice(0, i) + "\\frac{" + str.slice(i+1, -1) + "}";
        results += "{$1}$0";
        rv = results;
    }
    ``
endsnippet

函数名和希腊字母自动加 \

在函数名(如 sin,cos,ln 等)和希腊字母(如 alpha 等)前面自动加入 \

eps -> \varepsilon (极限的 ε−δ 语言中的 ε)
delta -> \delta (极限的 ε−δ 语言中的 δ )
sin -> \sin
pi -> \pi (圆周率 π)

context math(context)
snippet eps "varepsilon" wA
\varepsilon
endsnippet

context math(context)
snippet `(?<=\b|\d+)(?<!\\)(sin|cos|arccot|cot|csc|ln|log|lg|exp|star|perp|arcsin|arccos|arctan|arccot|arccsc|arcsec|pi|zeta|oint|iiint|iint|int|ell|nabla|notin)` "function" wA
\\``rv = m[1]`` 
endsnippet

context math(context)
snippet `(?<=\b|\d+)(?<!\\)(mu|alpha|sigma|rho|beta|gamma|delta|zeta|eta|epsilon|theta|iota|kappa|vartheta|lambda|nu|pi|rho|tau|upsilon|varphi|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)` "greek" wA
\\``rv = m[1]`` 
endsnippet

关于极限

\limits (primitive command) Place limits over and under a large operator. This is the default position in display style.

\nolimits (primitive command) Place limits of a large operator as subscript and superscript expressions. This is the default position in text style.

\displaylimits (primitive command) Restore default placement for limits.

from Definition of \limits

简言之在 \lim\sum 等巨运算符后面再加个 \limits 会强制把运算范围放到巨运算符的上面和下面(在行内公式中默认是想上下标一样放在右上角和右下角)。例子:

\lim_{n \to \infty} \sqrt{n+1}-\sqrt{n} \(\lim_{n \to \infty} \sqrt{n+1}-\sqrt{n}\)

\lim\limits_{n \to \infty} \sqrt{n+1}-\sqrt{n} \(\lim\limits_{n \to \infty} \sqrt{n+1}-\sqrt{n}\)

\sum_{n=1}^{\infty} \frac{1}{n^2} \(\sum_{n=1}^{\infty} \frac{1}{n^2}\)

\sum\limits_{n \to \infty} \frac{1}{n^2} \(\sum\limits_{n=1}^{\infty} \frac{1}{n^2}\)

所以 snip 有两个版本

\limits 版:

context math(context)
snippet `(?<!\\)lim` "limit" wA
\lim\limits_{${1:n} \to ${2:\infty}} 
endsnippet

\limits 版:

context math(context)
snippet `(?<!\\)lim` "limit" wA
\lim_{${1:n} \to ${2:\infty}} 
endsnippet

:上面的例子中有两个占位符:${1:n}${2:\infty}。你可以Tab 快速跳到下一个占位符,这时你可以编辑该占位符或再次跳到下一个。冒号后面的字符串(如果有的话)是默认文本,例如 ${2:\infty} 这个位置的默认文本是 \infty。占位符的遍历顺序是按数字升序。

特殊的集合

\RR -> \mathbb{R}

context math(context)
snippet `\\([RQZNC]){2}` "set" iA
\mathbb{``rv=m[1]``}
endsnippet

自动加 \left \right

打完括号(...)[...]后再打一个空格,会自动在括号两边加 \left \right。例如:

(\frac{1}{x})Space -> \left(\frac{1}{x}\right)

context math(context)
snippet `^.*(?<!right)(\)) $` A
``
    let str = m[0];
    str = str.replace(/\$/g, "\\$");
    str = str.slice(0, -1);
    let lastIndex = str.length - 1;

    let depth = 0;
    let i = str.length - 1;

    while (i > -1) {
        if (str[i] == ')') depth += 1;
        if (str[i] == '(') depth -= 1;
        if (depth == 0) break;
        i -= 1;
    }
    
    if (i == -1) rv = m[0];
    else{
        let inside = str.slice(i+1, -1);
        if (/^[1-9]$/.test(inside)) rv = m[0];
        else {
            rv = str.slice(0, i) + "\\left(" + inside + "\\right)";
        }
    }
    ``
endsnippet

context math(context)
snippet `^.*(?<!right)(\]) $` A
``
    let str = m[0];
    str = str.replace(/\$/g, "\\$");
    str = str.slice(0, -1);
    let lastIndex = str.length - 1;

    let depth = 0;
    let i = str.length - 1;

    while (i > -1) {
        if (str[i] == ']') depth += 1;
        if (str[i] == '[') depth -= 1;
        if (depth == 0) break;
        i -= 1;
    }
    
    if (i == -1) rv = m[0];
    else{
        let inside = str.slice(i+1, -1);
        if (/^[1-9]$/.test(inside)) rv = m[0];
        else {
            rv = str.slice(0, i) + "\\left[" + inside + "\\right]";
        }
    }
    ``
endsnippet

其他各种各样的替换

以下内容抄自 OrangeX4 的 snips,需要的自取

# ==== Auto Capture Hat Operation ====
context math(context)
snippet `(\(?)(\\?[a-zA-Z]\w*)(\)?)(hbar|BAR)` "Bar" iA
\overline{``rv = m[1] + m[2] + m[3]``}
endsnippet

context math(context)
snippet `(\\?[a-zA-Z]\w*)(htd|TD)` "tilde" iA
\widetilde{``rv = m[1]``}
endsnippet

context math(context)
snippet `(\\?[a-zA-Z]\w*)(hat|HAT)` "hat" iA
\hat{``rv = m[1]``}
endsnippet

context math(context)
snippet `(\\?[a-zA-Z]\w*)(hvec)` "Vector postfix" iA
\vec{``rv = m[1]``}
endsnippet

context math(context)
snippet `(\\?[a-zA-Z]\w*)(rta)` "Vector postfix" iA
\overrightarrow{``rv = m[1]``}
endsnippet

context math(context)
snippet `(\\?[a-zA-Z]\w*)(hdot)` "dot" iA
\dot{``rv = m[1]``}
endsnippet

context math(context)
snippet `(\\?[a-zA-Z]\w*)(hddot)` "ddot" iA
\ddot{``rv = m[1]``}
endsnippet

# ===== Static Hat Operation ====

context math(context)
snippet hbar "bar" iA
\overline{$1}$0
endsnippet

context math(context)
snippet hat "hat" iA
\hat{$1}$0
endsnippet

context math(context)
snippet hsq "\sqrt{}" iA
\sqrt{${1}}$0
endsnippet

# == Superscript Operation ==

context math(context)
snippet invs "inverse" wA
^{-1}
endsnippet

priority 10000
context math(context)
snippet TR "inverse" iA
^{\mathsf{T}}
endsnippet

context math(context)
snippet CL "complement" wA
^{c}
endsnippet

context math(context)
snippet R+ "R0+" iA
R_0^+
endsnippet

context math(context)
snippet pow "power" iA
^{${1:2}}$0
endsnippet

# == Subscript Operation ==

context math(context)
snippet td "subscript" iA
_{${1}}$0
endsnippet

context math(context)
snippet `([A-Za-z])(\d)` "auto subscript" wA
`` rv = m[1] + "_" + m[2]``
endsnippet

priority 100
context math(context)
snippet `([A-Za-z])_(\d{2})` "auto subscript" wA
`` rv = m[1] + "_{" + m[2] + "}$0" ``
endsnippet

priority 100
context math(context)
snippet `([A-Za-z])S(\d)` "auto subscript" wA
`` rv = m[1] + "_{" + m[2] + "$1}$2"``
endsnippet

context math(context)
snippet `\b(?<!\\)([A-Za-z])([a-z])\2` "auto subscript 2" iA
`` rv = m[1] + "_" + m[2].substring(0, 1) ``
endsnippet

context math(context)
snippet `\b(?<!\\)([A-Za-z])S([a-z])\2` "auto subscript 2" iA
`` rv = m[1] + "_{" + m[2].substring(0, 1) + "$1}$2"``
endsnippet

# Custom: Add more greek letters
context math(context)
snippet `(\\mu|\\alpha|\\sigma|\\rho|\\beta|\\gamma|\\delta|\\zeta|\\eta|\\varepsilon|\\theta|\\iota|\\kappa|\\vartheta|\\lambda|\\nu|\\pi|\\rho|\\tau|\\upsilon|\\phi|\\chi|\\psi|\\omega|\\Gamma|\\Delta|\\Theta|\\Lambda|\\Xi|\\Pi|\\Sigma|\\Upsilon|\\Phi|\\Psi|\\Omega)([a-z])\2` "auto subscript for greek letter" iA
`` rv = m[1] + "_" + m[2].substring(0, 1) ``
endsnippet

context math(context)
snippet `(\\mu|\\alpha|\\sigma|\\rho|\\beta|\\gamma|\\delta|\\zeta|\\eta|\\varepsilon|\\theta|\\iota|\\kappa|\\vartheta|\\lambda|\\nu|\\pi|\\rho|\\tau|\\upsilon|\\phi|\\chi|\\psi|\\omega|\\Gamma|\\Delta|\\Theta|\\Lambda|\\Xi|\\Pi|\\Sigma|\\Upsilon|\\Phi|\\Psi|\\Omega)S([a-z])\2` "auto subscript for greek letter" iA
`` rv = m[1] + "_{${1:" + m[2].substring(0, 1) + "}}$2"``
endsnippet

# == Font Operation ==

# ==== Static Operation ====

context math(context)
snippet txt "text" iA
\text{$1}$0
endsnippet

context math(context)
snippet tit "text it" iA
\textit{$1}$0
endsnippet

snippet mcal "mathcal" im
\mathcal{$1}$0
endsnippet

context math(context)
snippet mbb "mathbb" iA
\mathbb{$1}$0
endsnippet

context math(context)
snippet mbf "mathbb" iA
\mathbf{$1}$0
endsnippet

context math(context)
snippet mbf "mathbm" iA
\mathbf{$1}$0
endsnippet

# ==== Dynamic Operation ====

priority 100
context math(context)
snippet `(\\?[a-zA-Z]\w*)(bf|BF)` "mathbf" iA
\mathbf{``rv = m[1]``}
endsnippet

priority 100
context math(context)
snippet `(\\?[a-zA-Z]\w*)(bm|BM)` "mathbm" iA
\bm{``rv = m[1]``}
endsnippet

priority 100
context math(context)
snippet `(\\?[a-zA-Z]\w*)(bs)` "boldsymbol" iA
\boldsymbol{``rv = m[1]``}
endsnippet

priority 100
context math(context)
snippet `(\\?[a-zA-Z]\w*)mcal` "mathcal" iA
\mathcal{``rv = m[1].toUpperCase() ``} $0
endsnippet

priority 100
context math(context)
snippet `(?<!\\)\b([a-zA-Z]+)rm` "mathrm" iA
\mathrm{``rv = m[1]``}
endsnippet

priority 100
context math(context)
snippet `(\\?[a-zA-Z]\w*)mbb` iA
\mathbb{``rv = m[1]``} $0
endsnippet


# == Auto Symbol ==

snippet oo "\infty" wAmm
\infty
endsnippet

context math(context)
snippet ... "cdots" iA
\cdots 
endsnippet

snippet <> "hokje" iA
\diamond 
endsnippet

# +... -> , \cdots
# -  ... -> , \cdots
# add a space if there already is one.
priority 101
snippet `(?<=[-+])\s*\.\.\.` "smart cdots" irA
 \cdots 
endsnippet

# It seems that \ldots is only used when , ..., 
# ,... -> , \ldots
# ,  ... -> , \ldots
priority 101
snippet `(?<=,)(\s*)\.\.\.` "smart ldots" irA
 \ldots 
endsnippet

context math(context)
snippet ** "dot multiply" iA
\cdot 
endsnippet

context math(context)
snippet xx "cross" iA
\times 
endsnippet



# ==== Space Symbol ====
context math(context)
snippet `(?<=\b|\d+)(?<!\\)(quad)` "ln" wA
\\``rv = m[1]``
endsnippet

# ==== Logic Symbol ====


context math(context)
snippet -> "to" iA
\to 
endsnippet

context math(context)
snippet !> "mapsto" iA
\mapsto 
endsnippet

context math(context)
snippet vdash "vdash" iA
\\vdash
endsnippet

context math(context)
snippet => "implies" iA
\implies
endsnippet

context math(context)
snippet =< "implied by" iA
\impliedby
endsnippet

context math(context)
snippet iff "if and only if" iA
\iff
endsnippet

context math(context)
snippet EE "exist" iA
\exists 
endsnippet


context math(context)
snippet AA "forall" iA
\forall 
endsnippet

context math(context)
snippet bec "because" iA
\because 
endsnippet

context math(context)
snippet thr "therefore" iA
\therefore 
endsnippet


# ==== Compare Symbol ====

context math(context)
snippet -- "setminus" iA
\setminus
endsnippet

context math(context)
snippet >= "greater than" iA
\geqslant $0
endsnippet

context math(context)
snippet dis "displaystyle" iA
\displaystyle 
endsnippet

context math(context)
snippet <= "less than" iA
\leqslant $0
endsnippet

context math(context)
snippet != "no equals" iA
\neq 
endsnippet

context math(context)
snippet == " constan equals" iA
\equiv 
endsnippet

context math(context)
context math(context)
snippet ~~ " Appro equals" iA
\thickapprox 
endsnippet

context math(context)
context math(context)
snippet ~= " Appro equals2" iA
\cong
endsnippet

context math(context)
snippet >> ">>" iA
\gg
endsnippet


context math(context)
snippet << "<<" iA
\ll
endsnippet

# == Auto Environment ==

# ==== Auto Math Mode ====

snippet lm "inline Math" wA
$${1}$$0
endsnippet

snippet dm "display Math" wA
$$
${1}
$$$0
endsnippet

# ==== Common Environment ====

context math(context)
snippet case "cases" wA
\begin{cases}
	$1 \\\\
\end{cases}
endsnippet

context math(context)
snippet ali "aligned" wA
\begin{aligned}
$1 \\\\
\end{aligned}
endsnippet

# == Auto Adaptive Close ==

context math(context)
snippet ceil "ceil" iA
\left\lceil $1 \right\rceil $0
endsnippet

context math(context)
snippet floor "floor" iA
\left\lfloor $1 \right\rfloor$0
endsnippet

priority 100
snippet @( "left( right)" Aim
\left( ${1} \right) $0
endsnippet

priority 100
snippet @| "left| right|" Aim
\left| ${1} \right| $0
endsnippet

priority 100
snippet @{ "left\{ right\}" Aim
\left\\{ ${1} \right\\} $0
endsnippet

priority 100
snippet @[ "left[ right]" Aim
\left[ ${1} \right] $0
endsnippet

priority 100
context math(context)
snippet @< "leftangle rightangle" iA
\left<${1} \right>$0
endsnippet

snippet ( "auto close ()" iA
(${1})
endsnippet

snippet { "auto close {}" iA
{${1}}
endsnippet

snippet [ "auto close []" iA
[${1}]
endsnippet

priority 200
context math(context)
snippet norm iA
\left\| ${1} \right\|_{$2}$3
endsnippet

# == Snippet ==

# ==== General Snippet ====

# ====== Lite Snippet ======

context math(context)
snippet tag "tag" iA
\tag{$1}
endsnippet

context math(context)
snippet xyb "Auto (x, y)" iA
(x, y)
endsnippet

context math(context)
snippet xyzb "Auto (x, y ,z)" iA
(x, y, z)
endsnippet

priority 100
context math(context)
snippet `\b([a-zA-Z])n(\d)` "x[n+1]" iA
``rv = m[1]``_{${1:n}+``rv = m[2]``}$0
endsnippet

# Unkown
context math(context)
snippet rij "mrij" iA
(${1:x}_${2:n})_{${3:$2} \\in ${4:N}}$0
endsnippet

priority 200
context math(context)
snippet abs "absolute value" iA
\left\vert ${1} \right\vert $0
endsnippet

snippet beg "begin{} / end{}" bA
\\begin{$1}
	$0
\\end{$1}
endsnippet

# ======== N Series ========

priority 100
context math(context)
snippet comma "comma" iA
${1:\\alpha}_1,${1:\\alpha}_2,\\cdots,${1:\\alpha}_${2:n}
endsnippet

priority 100
context math(context)
snippet plus "plus" iA
${1:k}_1${2:\\alpha}_1+${1:k}_2${2:\\alpha}_2+\\cdots+${1:k}_${3:n}${2:\\alpha}_${3:n}
endsnippet

context math(context)
snippet `\b([a-z])=n` "i=1,2,\cdots,n" wA
``rv = m[1]``=1,2,\cdots,n
endsnippet

# ======== Common Operator Snippet ========

context math(context)
snippet `(?<!\\)sum` "sum" wA
\sum\limits_{n=${1:1}}^{${2:\infty}} ${3:a_n z^n}
endsnippet

context math(context)
snippet taylor "taylor" wA
\sum\limits_{${1:k}=${2:0}}^{${3:\infty}} ${4:c_$1} (x-a)^$1 $0
endsnippet

context math(context)
snippet `(?<!\\)lim` "limit" wA
\lim\limits_{${1:n} \to ${2:\infty}} 
endsnippet

context math(context)
snippet `(?<!\\)prod` "product" wA
\prod_{${1:n=${2:1}}}^{${3:\infty}} ${4:${VISUAL}} $0
endsnippet

context math(context)
snippet `(?<!\\)part` "d/dx" wA
\frac{\partial ${1:V}}{\partial ${2:x}}$0
endsnippet

priority 100
context math(context)
snippet `(?<!\\)diff` "d/dx" wA
\frac{\mathrm{d}${1:y}}{\mathrm{d}${2:x}}$0
endsnippet

context math(context)
snippet buu "bigcup" wA
\bigcup_{${1:i \in ${2: I}}} $0
endsnippet

context math(context)
snippet bnn "bigcap" wA
\bigcap_{${1:i \in ${2: I}}} $0
endsnippet

priority 100
context math(context)
snippet dint "integral" wA
\int_{${1:-\infty}}^{${2:\infty}} ${3} ~\\mathrm{d}${4:x} $0
endsnippet

priority 200
context math(context)
snippet `c(o|n)?(l|n)?(b|c)?int` "s 	egral" wA
``
let final = "\\"; // init
let isO = m[1] == "o";
(isO) ? final += "o" : "" // o option
let b = 1;
let isL = m[2] == "l";
(m[3] == 'b') ? b = 2 : (m[3] == 'c') ? b = 3 : 1;
for (let i = 0; i < b - 1; i++) {
final += "i";
}
final += "int";
final += ((b >= 2) || (b != 1 && !isO && isL)) ? "\\limits" : "";
let r = (b == 3) ? "E" : (b == 1 && (isL || isO)) ? "C" : "R";
final += ((b >= 2) || isO || (b == 1 && isL)) ? "_{${1:" + r + "}}" : "_{${1:-\\infty}}^{${2:\\infty}}";
let x = (b == 2) ? "A" : (b == 3) ? "V" : (b == 1 && isL) ? "s" : "x";
final += " ${3} ~\\mathrm{d}${4:" + x + "} $0";
rv = final;
``
endsnippet

# Custom: Can add more defined operator
priority 100
context math(context)
snippet `(?<![\a-zA-Z])(rank|lcm|gcd)` "math function" wA
\\operatorname{``rv = m[1]``}
endsnippet

context math(context)
snippet `(?<![\a-zA-Z])arg(max|min)` "argmin/max" wA
\mathop{\arg\\``rv = m[1]``}
endsnippet

# ====== Big Snippet ======

context math(context)
snippet bigdef "Big function" iA
\begin{equation$6}
    \begin{aligned}
        $1\colon $2 &\longrightarrow $3 \\\\
                 $4 &\longmapsto $1($4) = $5
    \end{aligned}
\end{equation$6}$0
endsnippet

context math(context)
snippet bigmin "Optimization problem" iA
\begin{equation$4}
	\begin{aligned}
		\min &\quad ${1:f(x)}\\\\
		\text{s.t.} &\quad ${2:g(x)} \leq 0\\\\
					&\quad ${3:h(x)} = 0\\\\
	\end{aligned}
\end{equaiton$4}$0
endsnippet

context math(context)
snippet bigmax "Optimization problem" wA
\begin{equation$4}
	\begin{aligned}
		\max &\quad ${1:f(x)}\\\\
		\text{s.t.} &\quad ${2:g(x)} \leq 0\\\\
					&\quad ${3:h(x)} = 0\\\\
	\end{aligned}
\end{equation$4}$0
endsnippet

context math(context)
snippet deff "Definition of function" wA
$1\colon ${2:\\mathbb{R\}} \to ${3:\\mathbb{R\}}, ${4:x} \mapsto $0
endsnippet


context math(context)
snippet iid "independent and identical distribution" iA
\overset{\text{i.i.d.}}{\sim}
endsnippet

context math(context)
snippet defe "define equal" wA
\overset{\underset{\mathrm{def}}{}}{=}
endsnippet


# == Matrix ==

# ==== Static Matrix ====

snippet pmat "pmat" wm
\begin{pmatrix} 
    ${1: } 
\end{pmatrix} $0
endsnippet

snippet bmat "pmat" wm
\begin{bmatrix} 
    $1 
\end{bmatrix} $0
endsnippet

context math(context)
snippet vecC "column vector" iA
\begin{pmatrix} ${1:x}_1 \\\\ ${1:x}_2 \\\\ \vdots \\\\ ${1:x}_${2:n} \end{pmatrix}
endsnippet

context math(context)
snippet vecR "row vector" iA
\begin{pmatrix} ${1:x}_1, ${1:x}_2, \cdots, ${1:x}_${2:n} \end{pmatrix}$0
endsnippet

priority 300
context math(context)
snippet omis "omission" iA
\\begin{pmatrix}${1:1}&${2:1}&\\cdots&${4:1}\\\\${5:1}&${6:1}&\\cdots&${8:1}\\\\\\vdots&\\vdots&\\ddots&\\vdots\\\\${13:1}&${14:1}&\\cdots&${16:1}\\end{pmatrix}
endsnippet

priority 300
context math(context)
snippet submat "omission" iA
\\begin{pmatrix}
    ${1:a}_{11} & ${1:a}_{12} & \\cdots & ${1:a}_{1n} \\\\
    ${1:a}_{21} & ${1:a}_{22} & \\cdots & ${1:a}_{2n} \\\\
    \\vdots & \\vdots & \\ddots & \\vdots \\\\
    ${1:a}_{n1} & ${1:a}_{n2} & \\cdots & ${1:a}_{nn}
\\end{pmatrix}
endsnippet

priority 300
context math(context)
snippet subplusmat "omission" iA
\\begin{pmatrix}
    ${1:a}_{11}+{2:b}_{11} & ${1:a}_{12}+{2:b}_{12} & \\cdots & ${1:a}_{1n}+{2:b}_{1n} \\\\
    ${1:a}_{21}+{2:b}_{21} & ${1:a}_{22}+{2:b}_{22} & \\cdots & ${1:a}_{2n}+{2:b}_{2n} \\\\
    \\vdots & \\vdots & \\ddots & \\vdots \\\\
    ${1:a}_{n1}+{2:b}_{n1} & ${1:a}_{n2}+{2:b}_{n2} & \\cdots & ${1:a}_{nn}+{2:b}_{nn}
\\end{pmatrix}
endsnippet

context math(context)
snippet jacobi "jacobi" iA
\\begin{pmatrix}\\frac{\\partial ${1:f}_1}{\\partial ${2:x}_1}&\\frac{\\partial ${1:f}_1}{\\partial ${2:x}_2}&\\cdots&\\frac{\\partial ${1:f}_1}{\\partial ${2:x}_${3:n}}\\\\\\frac{\\partial ${1:f}_2}{\\partial ${2:x}_1}&\\frac{\\partial ${1:f}_2}{\\partial ${2:x}_2}&\\cdots&\\frac{\\partial ${1:f}_2}{\\partial ${2:x}_${3:n}}\\\\\\vdots&\\vdots&\\ddots&\\vdots\\\\\\frac{\\partial ${1:f}_${3:m}}{\\partial ${2:x}_1}&\\frac{\\partial ${1:f}_${3:m}}{\\partial ${2:x}_2}&\\cdots&\\frac{\\partial ${1:f}_${3:m}}{\\partial ${2:x}_${3:n}}\\end{pmatrix}
endsnippet

# ==== Dynamic Matrix ====

priority 300
context math(context)
snippet `(b|p|v)mata([1-9])` "bmatrix" iwA
\\begin{``rv = m[1]``matrix}``
	let len = m[2];
	let results = "";
	for (var i=0; i<len; i++){
		results += "$1 &".repeat(len-1) + " $1 \\\\\\\\";
	}
	rv = results;
``\\end{``rv = m[1]``matrix}$0
endsnippet

priority 300
context math(context)
snippet `(b|p|v)mat([1-9])` "bmatrix" iwA
\\begin{``rv = m[1]``matrix}``
	rv = gen_matrix(m[2],m[2]);
``\\end{``rv = m[1]``matrix}$0
endsnippet

priority 300
context math(context)
snippet `vec([1-9])` "col vector" iwA
\\begin{pmatrix}``
    rv = gen_matrix(m[1], 1);
``\\end{pmatrix}$0
endsnippet

priority 300
context math(context)
snippet `vecr([1-9])` "row vector" iwA
\\begin{pmatrix}``
    rv = gen_matrix(1, m[1]);
``\\end{pmatrix}$0
endsnippet


# == General ==

snippet \box "Box" 
``rv = '┌' + '─'.repeat(t[0].length + 2) + '┐'``
│ $1 │
``rv = '└' + '─'.repeat(t[0].length + 2) + '┘'``
endsnippet


priority 300
snippet `table(\d)(\d)` "create table with rows and columns" wA
``
rv = createTable(m[1], m[2]);
``
endsnippet

snip编写帮助

翻译自 HyperSnips 的 readme

Snippet 文件

Snippet 文件扩展名为.hsnips,该文件由两种块组成:全局块和 snippet 块。

全局块是 JavaScript 代码块,其代码在当前文件中定义的所有 snippet 之间共享。它们是用 global 关键字定义的,如下所示。

global
// JavaScript代码
endglobal

Snippet 块是 snippet 的定义。它们是用 snippet 关键字定义的,如下所示。

context expression
snippet trigger "description" flags
body
endsnippet

其中触发器必需的,描述和标志字段是可选的。

触发器 trigger

触发器可以是任何不含空格的字符序列,或由反斜线(`)包围的正则表达式。

标志 flags

标志字段是一连串的字符,用于修改 snippet 的行为,可用的标志有以下几种。

A自动扩展 snippet - 通常 snippet 在按下 Tab 键时被激活,如果使用A标志,snippet 将在其触发器匹配时自动激活,这对正则表达式 snippet 特别有用。

i: 字内扩展* - 默认情况下,一个 snippet 的触发器仅在触发器前面有空白字符时才会匹配。使用该选项后,无论前面的字符是否为空白字符,snippet 都会被触发。例如,一个 snippet 可以在一个单词的中间被触发。

w: 单词边界* - 使用该选项后,只有当触发器是一个单词边界的字符时,才会触发 snippet。例如,允许在触发器跟随标点符号的情况下进行扩展,而不扩展较大词的后缀。

b: 行首扩展* - 使用该选项后,只有触发器是该行的第一个单词时才会触发。换句话说,如果这一行直到触发器之前都只有空白,则展开。

M: 多行模式 - 默认情况下,正则表达式匹配将只匹配当前行的内容,当该选项被启用时,最后的hsnips.multiLineContext行将可用于匹配。

星号 * 的标志只影响非正则表达式触发器的 snippet。

主体部分 body

body 是在 snippet 展开时将替换触发器的文本,与 Visual Studio Code 通常的 snippet 一样,可以使用制表位 $1$2 等。

HyperSnips 的全部功能在使用 JavaScript 时发挥作用:您可以在 snippet 中包含由两个反引号(``)分隔的代码块,代码块将在 snippet 展开时或制表位($1$2等)处的文本改变时运行。

JavaScript 代码块

在代码块中,您可以访问一些特殊变量:

rv:你的代码块的返回值,这个变量的值会在 snippet 展开时替换代码块。
t:制表位内文本的数组,其顺序与在 snippet body 中定义的制表位顺序相同。您可以使用它来动态更改 snippet 内容。
m正则表达式触发器匹配组的数组,如果触发器不是正则表达式,则为空数组。
w:当前打开的工作区的 URI 字符串,如果没有工作区打开,则为空字符串。
path:当前文档的 URI 字符串。(无标题文档具有无标题的方案)

此外,在一个代码块中定义的每个变量都将在 snippet 的所有后续代码块中可用。

require 函数还可用于导入 NodeJS 模块。

上下文匹配

您可以在 snippet 块之前加入上下文行,它后跟任何 javascript 表达式,并且该 snippet 仅在上下文表达式的计算结果为 true 时可用。

在上下文表达式中,您可以使用上下文变量,它具有以下类型:

interface Context {
  scopes: string[];
}

此处,scopes 代表当前光标位置的 TextMate 范围,可以通过在 VSCode 中运行 Developer: Inspect Editor Tokens and Scopes 命令来查看。

例如,这里是一个自动的 LaTeX 片段,它只在数学块内扩展:

global
function math(context) {
    return context.scopes.some(s => s.includes("math"));
}
endglobal

context math(context)
snippet inv "inverse" Ai
^{-1}
endsnippet

例子

  • Simple snippet which greets you with the current date and time
snippet dategreeting "Gives you the current date!"
Hello from your hsnip at ``rv = new Date().toDateString()``!
endsnippet
  • 能在输入时够动态改变大小的文本框
snippet box "Box" A
``rv = '┌' + '─'.repeat(t[0].length + 2) + '┐'``
│ $1 │
``rv = '└' + '─'.repeat(t[0].length + 2) + '┘'``
endsnippet
  • 插入当前文件名
snippet filename "Current Filename"
``rv = require('path').basename(path)``
endsnippet
posted @ 2021-09-24 21:47  樱花赞  阅读(1567)  评论(0编辑  收藏  举报