VSCode Snippets 使用指南
我们在写代码的过程中,常常会遇到一些固定的代码结构,形如输入一串console.log
或者输入for
的结构甚至是编写redux
的reducers
等等。反复写这些代码结构,不仅枯燥无聊,也会觉得效率不够高。那么有没有什么办法可以解决这个问题呢?让写代码的过程更畅快点呢?
VSCode
中的自定义Snippets
功能就是为了解决这类问题的。你可以预先编写好一系列代码结构,然后在使用的时候,仅仅需要输入一个关键字,VSCode
的智能提示功能就会提醒让你完善代码结构的输入过程,如:
一、Snippets文件介绍
Snippets
文件是一个JSON
文件,但支持C语言风格的注释(即//
),在Snippets
中可以编写无限条规则,如下是一个示例的Snippets
文件,它实现了for
结构代码的快速填充:
{ "For Loop": { "prefix": ["for", "for-const"], "body": [ "for (const ${2:element} of ${1:array}) {", "\t$0", "}" ], "description": "A for loop" }}
之后,在代码文件里输入for
时,VSCode
就会帮我们创建如下的结构代码:
for (const element of array) { }
并且,光标最开始在array
位置,按下Tab键
之后跳到element
位置,再按下Tab键
之后跳到语句主体的位置
二、编写规则
规则的语法结构如果用TypeScript
描述的话,大概是这样子的:
interface SnippetRule { prefix: string[]; body: string[]; scope?: string; description?: string;}interface SnippetRules { [ruleName: string]: SnippetRule;}
解释如下:
- 规则名称:
ruleName
是规则的名称,当SnippetRule
中没有提供description
时,读取ruleName
作为description
- 触发关键词:
prefix
定义了触发智能提示的关键词,是可以支持多个触发关键词的。触发关键词支持部分截取匹配,比如prefix
中定义了for-const
这个关键词,但是当用户输入fc
的时候,也能够触发Snippet
智能提示 - 填充代码内容:
body
定义了生成的代码内容,数组的每一项代表生成的代码的每一行,在body
中可以声明占位符
来定义插值,如此当代码结构生成完毕后,用户可以通过Tab键
切换来替换插值内容 - 作用范围,
Snippet
的作用范围可以是编程语言
级别,也可以是项目
级别- 单语言范围: 当定义单一语言作为作用范围时,
Snippet
只会作用于这一语言。这种一般是通过修改偏好设置(Code > Preference > User Snippets)选择特定语言实现的,VSCode
会生成语言.json
文件来记录规则(如javascript.json
) - 多语言范围: 当定义针对多个语言的作用范围时,需要启用规则中的
scope
字段指定。如果希望多语言范围是全局性的,则通过修改偏好设置(Code > Preference > User Snippets),选择New Global Snippets file
创建,VSCode
会生成.code-snippets
后缀的文件来记录规则,如果.code-snippets
文件规则中的scope
没有给定,那么就作用于全部的语言 - 项目范围: 可以只为特定项目定义
Snippets
,只要在项目结构下的.vscode
目录中创建.code-snippets
结尾的规则文件即可。可以借由偏好设置来帮助生成规则文件(Code > Preference > User Snippets > New Snippets file for …)
- 单语言范围: 当定义单一语言作为作用范围时,
三、占位符
body
中可以支持一系列的占位符,从而控制光标和被插入的文本,如下是占位符支持的全部语法:
1、Tab占位符
Tab占位符的语法格式是:
'$' int
使用 Tab占位符
,就能够控制光标在一段 snippet
内部移动,可以使用 $1, $2
来指定光标位置。终止符中的数值,表示光标在 Tab键
按下后光标切换的顺序,从小到大。但是 $0
有着特殊的含义,它表示的是光标最后停留的位置。一个 Tab占位符
是可以多次使用的,那么在输入的时候,就会被关联在一起同步更新
2、命名占位符
命名占位符的语法格式是:
E: '${' int ':' string E* '}'
它和 Tab占位符
的功能总体上一样,不同的是,它默认情况下会带上一串指定的字符串作为占位符。并且它是支持嵌套的,如:
${1:a ${2:b}}
这样子光标能够实现在内部切换的效果
3、可选占位符
可选占位符的语法格式是:
Choice: string (',' string)* E: '${' int '|' Choice '|}'
它能够实现指定字符串之间选择插入作为占位符的功能,如:${1|a,b,c,d|}
:
4、变量占位符
变量占位符的语法格式是:
'$' variableName或'${' variableName ':' defaultValue '}'
当一个 variableName
对应的值取不到的时候,如果有设置默认值(defaultValue
)的话,默认值会被插入,否则就会插入空字符串。以下的这些变量都是可用的:
TM_SELECTED_TEXT
当前选中的文本(未选中时是空字符串)TM_CURRENT_LINE
当前行的内容TM_CURRENT_WORD
光标选中的单词内容(未选中时是空字符串)TM_LINE_INDEX
代码所插入的行号(以0为基准索引)TM_LINE_NUMBER
代码所插入的行号(以1为基准索引)TM_FILENAME
当前文档的文件名TM_FILENAME_BASE
当前文档的文件名(不带后缀)TM_DIRECTORY
当前文档所在的目录TM_FILEPATH
当前文档所在的完整目录CLIPBOARD
当前剪贴板的内容WORKSPACE_NAME
打开的工作区或者目录的名称
如果要插入当前的日期和时间的话:
CURRENT_YEAR
当前年CURRENT_YEAR_SHORT
当前年(两位数形式)CURRENT_MONTH
两位数形式的当前月 (如:'02')CURRENT_MONTH_NAME
完整的当前月份名称 (如:'July')CURRENT_MONTH_NAME_SHORT
简写的当前月份名称 (如:'Jul')CURRENT_DATE
当前日期CURRENT_DAY_NAME
当前天的名称 (如:'Monday')CURRENT_DAY_NAME_SHORT
当前天名称的简写形式 (如:'Mon')CURRENT_HOUR
当前时的24小时形式CURRENT_MINUTE
当前分钟CURRENT_SECOND
当前秒CURRENT_SECONDS_UNIX
自Unix元年的秒数值
还可以通过如下这些变量,插入时会跟随当前语言而变:
BLOCK_COMMENT_START
块级注释开头(如在PHP里会输出:/*
,在HTML里会输出:<!--
)BLOCK_COMMENT_END
块级注释结尾(如在PHP里会输出:*/
,在HTML里会输出:-->
)LINE_COMMENT
行级注释(如在PHP里会输出://
)
5、转换
变量转换
变量转化能够让你在变量的值被插入之前,得到一个修改插入值的机会,一次变量转换是由下面这三部分组成的:
1、用来匹配变量值的正则表达式
2、格式化的字符串,用来引用从正则表达式中捕获的分组,格式化字符串可以做条件插入和简单的修改,其语法格式描述如下:
format ::= '$' int | '${' int '}' | '${' int ':' '/upcase' | '/downcase' | '/capitalize' '}' | '${' int ':+' if '}' | '${' int ':?' if ':' else '}' | '${' int ':-' else '}' | '${' int ':' else '}'
3、传递给正则表达式的选项
下面这个例子,能够插入一个值,这个值是去掉了后缀的文件名:
因此,假如当前文件名是foo.txt
,则插入后的值就是foo
占位符转化
占位符转化和变量转化类似,不同的是,它读取的不是变量解析后的值,而是用户输入后的值,并且会在按下 Tab键
切换到下一个占位符之前,完成这个转化工作。如:
${1/(.*)\\..+$/$1/}
一些例子
在转化中,运用的正则表达式是字符串化的,而不是正则字面量,因此也需要像在 JS
里用字符串形式的正则表达式那样,对双斜杠进行转义。下面以 TM_FILENAME
解析为 example-123.456-TEST.js
为例子:
"${TM_FILENAME/[\\.]/_/}"
:输出:example-123_456-TEST.js
"${TM_FILENAME/[\\.-]/_/g}"
:输出:example_123_456_TEST_js
"${TM_FILENAME/(.*)/${1:/upcase}/}"
:输出:EXAMPLE-123.456-TEST.JS
"${TM_FILENAME/[^0-9^a-z]//gi}"
:输出:example123456TESTjs
四、绑定快捷键的Snippets
可以创建自定义的快捷键来插入特定的 Snippets
,方法是打开 keybindings.json
文件(Preference > Keyboard Shortcuts > 左上角 Open Keyboard Shortcuts
图标),然后可以加入 snippet
作为额外的参数,如:
{ "key": "cmd+l cmd+g", "command": "editor.action.insertSnippet", "when": "editorTextFocus", "args": { "snippet": "console.log($1)$0" }}
那么,当按下组合键时,相应的内容就会被插入进来了。而其实我们也可以不使用内联的 snippet
,通过制定 语言名称
和 snippet名称
,我们就可以使用已存在的 snippet
,如下:
{ "key": "cmd+l cmd+g", "command": "editor.action.insertSnippet", "when": "editorTextFocus", "args": { "langId": "javascript", "name": "log" }}