- 文档
- 教程
【免费下载链接】vscode-docs
Public documentation for Visual Studio Code
代码片段(Snippets)是 VS Code 中用来快速输入重复代码模式的模板,例如循环、条件语句或一段完整的日志输出。本文以官方文档 docs/editing/userdefinedsnippets.md 为主体,系统讲解代码片段在内置、Marketplace 扩展、用户自定义三种来源下的使用方式,并深入剖析片段文件的 JSON 结构、prefix/body/description字段、占位符与 Tabstop 跳转机制、完整变量与变量转换语法,以及语言、项目、文件模式三种作用域控制手段。读完本文,你将能够独立编写、调试、共享和打包自己的代码片段,并把片段绑定到自定义键盘快捷键上。
什么是代码片段
代码片段是预先写好的、可复用的代码模板,用于加速"重复代码模式"的输入——比如for循环、if-else分支、函数定义或样板注释。在 VS Code 中,片段会以两种方式呈现:
- 混入 IntelliSense 建议列表:与普通补全建议一起出现,可通过触发智能提示的快捷键(
kb(editor.action.triggerSuggest))唤起; - 独立的片段选择器:在命令面板中运行Insert Snippet命令,可列出当前文件语言可用的全部片段。
此外 VS Code 还支持Tab 补全(tab-completion):在设置中启用"editor.tabCompletion": "on"后,输入片段的prefix(触发文本)并按下插入片段的快捷键(kb(insertSnippet),通常为 Tab),即可直接插入该片段。
代码片段的语法遵循 TextMate 片段语法,但有两个例外:"interpolated shell code"(插值 shell 代码)与\u转义均不支持。
使用内置代码片段
VS Code 为多种语言内置了开箱即用的代码片段,例如 JavaScript、TypeScript、Markdown 和 PHP。要查看某个语言当前可用的全部片段,可以:
- 打开命令面板(
kb(workbench.action.showCommands)); - 运行Insert Snippet命令;
- 在列表中查看当前文件语言对应的全部片段。
需要注意,这个列表不仅包含内置片段,还会混入你自己定义的用户片段,以及已安装扩展提供的片段。如果希望只看某一类来源,可以结合下文的作用域与隐藏机制来管理。
从 Marketplace 安装代码片段扩展
许多 VS Code 扩展都会随包附带代码片段(例如语言支持、框架工具类扩展)。查找这类扩展的方法是:
- 打开扩展视图(
kb(workbench.view.extensions)); - 在搜索框中输入过滤器
@category:"snippets"; - 浏览结果并安装你需要的扩展。
安装完成后,重启 VS Code,新片段即可生效。这种方式适合直接复用社区维护好的片段集合,而无需自己编写。
创建自己的代码片段
不依赖任何扩展,你可以直接在 VS Code 中定义自己的片段。操作路径如下:
- 菜单File>Preferences>Configure Snippets(即命令Snippets: Configure Snippets);
- 在弹出的下拉菜单中选择一种语言(按语言标识符区分,例如
javascript、typescript、python),片段只会在该语言文件中出现; - 或选择New Global Snippets file(新建全局代码片段文件),片段适用于所有语言;
- 也可以选择New Snippets file for '<folder-name>'...创建项目级片段文件(详见下文"项目片段作用域")。
选择后 VS Code 会自动创建/刷新对应的片段 JSON 文件,你只需写入内容即可。片段文件以 JSON 编写、支持 C 风格注释(//、/* */),并且可以定义不限数量的片段。
以下是一个针对 JavaScript 的for循环片段示例(位于用户片段文件Code/User/snippets/javascript.json):
// in file 'Code/User/snippets/javascript.json' { "For Loop": { "prefix": [ "for", "for-const" ], "body": [ "for (const ${2:element} of ${1:array}) {", "\t$0", "}" ], "description": "A for loop." } }各字段含义如下:
- 片段名(此例为
"For Loop"):片段在列表中的显示名称。如果未提供description,片段名会直接显示在 IntelliSense 中; prefix:一个或多个触发词。当输入这些文本时片段会出现在 IntelliSense 中。匹配采用子串匹配,因此本例中fc也能匹配到for-const;body:一行或多行内容,插入时会被拼接为多行文本。其中的换行与嵌入制表符会根据插入位置的上下文自动格式化缩进;description:可选的描述文本,由 IntelliSense 显示,帮助区分同名片段。
示例body中包含三个占位符(按遍历顺序):${1:array}、${2:element}和$0。插入片段后,你可以用跳转到下一个占位符的快捷键(kb(jumpToNextSnippetPlaceholder),默认 Tab)快速在占位符间移动并编辑。冒号:后的字符串是默认文本,例如${2:element}中的element。占位符的遍历顺序按编号从小到大,从1开始;$0是可选的特殊位置,总是最后访问,到达后退出片段模式并将光标停在指定位置。
文件模板片段
如果某个片段的本意是填充或替换整个文件的内容(例如新建文件时的样板模板),可以为其添加isFileTemplate属性:
{ "My File Template": { "prefix": "template-name", "body": [ "# ${1:title}", "", "${0}" ], "isFileTemplate": true } }标记为文件模板的片段,会在你于新文件或已有文件中运行Snippets: Fill File with Snippet命令时,出现在一个专门的下拉列表中,方便按模板一键生成文件内容。
代码片段作用域
片段是有作用域的,VS Code 只会建议与当前上下文相关的片段。作用域可以从两个维度控制:
- 语言:片段适用于哪些语言(可能是全部语言);
- 项目:片段适用于哪些项目(通常适用于全部项目)。
此外还有更细粒度的文件模式控制(include/exclude)。
语言片段作用域
每个片段都会根据其定义位置,被限定到一个、多个或全部(全局)语言:
- 单语言片段:定义在某个特定语言的片段文件中(例如
javascript.json),可通过Snippets: Configure Snippets按语言标识符访问。这类片段仅在编辑该语言文件时可用; - 多语言 / 全局片段:定义在"全局"片段文件中(JSON 文件,后缀为
.code-snippets),同样通过Snippets: Configure Snippets访问。在全局片段文件中,片段定义可以增加一个可选的scope属性,取值为一个或多个语言标识符,从而将片段限制到指定语言;如果省略scope,则该全局片段对所有语言可用。
大多数用户自定义片段是单语言的,因此通常定义在语言专属片段文件中。若需多语言共享或全局可用,则使用.code-snippets文件配合scope。
项目片段作用域
你还可以将全局片段文件(.code-snippets)限定到某个项目。项目级片段通过Snippets: Configure Snippets下拉菜单中的New Snippets file for '<folder-name>'...创建,存放于项目根目录的.vscode文件夹中。项目片段适合与参与该项目的所有开发者共享(配合版本控制提交),其行为与全局片段类似,也可以通过scope属性限定到特定语言。
文件模式作用域
include与exclude两个可选属性可以进一步控制片段出现的位置,它们同时适用于语言专属片段文件和全局片段文件,并可与scope属性组合以实现更精确的控制:
include:一个 glob 模式或 glob 模式数组,指定片段应出现在哪些文件中;exclude:一个 glob 模式或 glob 模式数组,指定片段不应出现在哪些文件中。
模式匹配规则如下:
- 仅文件名模式(例如
*.test.ts):仅基于文件名匹配,与文件在项目中的位置无关; - 基于路径的模式(例如
**/*.test.ts或**/dist/**):匹配完整文件路径; - 若某个文件同时命中
include与exclude,exclude优先; - 若两者都未指定,则片段根据
scope属性出现在所有适用文件中。
示例:测试片段(仅出现在 TypeScript 测试文件中):
{ "Test Block": { "prefix": "test", "body": [ "test('${1:description}', () => {", "\t${0}", "});" ], "description": "Insert a test block", "scope": "typescript", "include": ["**/*.test.ts", "**/*.spec.ts"] } }示例:排除目录(出现在所有 JavaScript 文件中,但排除dist与node_modules目录):
{ "Console Log": { "prefix": "log", "body": "console.log(${0});", "description": "Insert console.log", "scope": "javascript", "exclude": ["**/dist/**", "**/node_modules/**"] } }示例:配置文件片段(使用仅文件名模式,仅出现在travis.yml中):
{ "Travis CI Node": { "prefix": "travis-node", "body": [ "language: node_js", "node_js:", " - ${1:18}" ], "description": "Travis CI Node.js configuration", "scope": "yaml", "include": ["travis.yml"] } }合理使用include/exclude可以显著减少 IntelliSense 中的干扰项,让片段只在其真正相关的文件中出现。
代码片段语法详解
片段的body可以使用多种特殊结构来控制光标位置与插入文本,其核心语法遵循 TextMate 片段规范(去掉不支持的 shell 插值与\u)。
Tabstops(制表位)
使用$1、$2指定光标位置,数字表示访问顺序;$0表示最终光标位置。同一 Tabstop 的多次出现是关联同步的——编辑其中一个,其余位置会同步更新。
{ "Print": { "prefix": "print", "body": "console.log($1)$0" } }Placeholders(占位符)
占位符是带默认值的 Tabstop,语法为${1:foo}。插入片段时默认文本会被选中,方便直接输入替换。占位符支持嵌套,例如${1:another ${2:placeholder}}。
Choice(选项)
占位符的值可以是可选项列表,语法为用管道符|包围、逗号分隔的枚举,例如${1|one,two,three|}。片段插入并选中该占位符时,VS Code 会提示用户在候选项中挑选一个。
Variables(变量)
使用$name或${name:default}可插入变量的值:
- 变量未设置时,插入其default值(若提供)或空字符串;
- 变量未知(名字未定义)时,插入变量名本身并将其转换为占位符。
可用变量分为以下几类。
文档与光标相关变量:
| 变量 | 含义 |
|---|---|
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 | 当前文档的完整文件路径 |
RELATIVE_FILEPATH | 相对于打开的工作区或文件夹的当前文档路径 |
CLIPBOARD | 剪贴板内容 |
WORKSPACE_NAME | 打开的工作区或文件夹的名称 |
WORKSPACE_FOLDER | 打开的工作区或文件夹的路径 |
CURSOR_INDEX | 基于 0 的光标编号 |
CURSOR_NUMBER | 基于 1 的光标编号 |
当前日期与时间变量:
| 变量 | 含义 |
|---|---|
CURRENT_YEAR | 当前年份 |
CURRENT_YEAR_SHORT | 当前年份的后两位 |
CURRENT_MONTH | 两位数字的月份(如02) |
CURRENT_MONTH_NAME | 月份完整名称(如July) |
CURRENT_MONTH_NAME_SHORT | 月份简称(如Jul) |
CURRENT_DATE | 两位数字的当月日期(如08) |
CURRENT_DAY_NAME | 星期完整名称(如Monday) |
CURRENT_DAY_NAME_SHORT | 星期简称(如Mon) |
CURRENT_HOUR | 24 小时制当前小时 |
CURRENT_MINUTE | 两位数字的当前分钟 |
CURRENT_SECOND | 两位数字的当前秒 |
CURRENT_MILLISECOND | 三位数字的当前毫秒(如078) |
CURRENT_SECONDS_UNIX | 自 Unix 纪元以来的秒数 |
CURRENT_MILLISECONDS_UNIX | 自 Unix 纪元以来的毫秒数 |
CURRENT_TIMEZONE_OFFSET | 当前 UTC 时区偏移,格式+HH:MM或-HH:MM(如-07:00) |
CURRENT_TIMEZONE_NAME | 当前时区的 IANA 名称(如America/Los_Angeles) |
随机值变量:
| 变量 | 含义 |
|---|---|
RANDOM | 6 位随机十进制数字 |
RANDOM_HEX | 6 位随机十六进制数字 |
UUID | 一个 Version 4 UUID |
行注释 / 块注释变量(自动匹配当前语言):
| 变量 | 示例输出 |
|---|---|
BLOCK_COMMENT_START | PHP 中为/*,HTML 中为<!-- |
BLOCK_COMMENT_END | PHP 中为*/,HTML 中为--> |
LINE_COMMENT | PHP 中为// |
下面的片段会在 JavaScript 文件中插入/* Hello World */,在 HTML 文件中插入<!-- Hello World -->:
{ "hello": { "scope": "javascript,html", "prefix": "hello", "body": "$BLOCK_COMMENT_START Hello World $BLOCK_COMMENT_END" } }变量转换(Variable transforms)
转换允许在插入前修改变量的值。一个转换由三部分组成:
- 正则表达式:与变量值匹配(变量无法解析时匹配空字符串);
- 格式字符串:引用正则的匹配分组,支持条件插入与简单改写;
- 选项:传递给正则表达式的选项(如
g、i等)。
以下示例取出当前文件名并去掉扩展名,将foo.txt转换为foo:
${TM_FILENAME/(.*)\\..+$/$1/} | | | | | | | |-> no options | | | | | |-> references the contents of the first | | capture group | | | |-> regex to capture everything before | the final `.suffix` | |-> resolves to the filename占位符转换(Placeholder-Transform)
与变量转换类似,占位符转换允许在跳转到下一个 Tabstop 时改写占位符中已插入的文本:插入的文本与正则表达式匹配,匹配结果(取决于选项)被替换为指定的替换格式文本。每个占位符出现处都可以基于第一个占位符的值独立定义自己的转换,其格式与变量转换完全相同。
转换示例
下面的示例以双引号形式展示(即片段 body 中的真实写法),以说明某些字符需要双重转义。转换作用于文件名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-9a-z]//gi}" | example123456TESTjs | 删除所有非字母数字字符 |
文法(Grammar)
片段语法可用下面的 EBNF(扩展巴科斯范式)完整描述。使用反斜杠\可以转义$、}和\。在 choice 元素内部,反斜杠还可转义逗号与管道符。只有必须转义的字符才需要转义:因此在这些结构中$不应转义;在 choice 结构内部$与}都不应转义。
any ::= tabstop | placeholder | choice | variable | text tabstop ::= '$' int | '${' int '}' | '${' int transform '}' placeholder ::= '${' int ':' any '}' choice ::= '${' int '|' text (',' text)* '|}' variable ::= '$' var | '${' var '}' | '${' var ':' any '}' | '${' var transform '}' transform ::= '/' regex '/' (format | text)+ '/' options format ::= '$' int | '${' int '}' | '${' int ':' '/upcase' | '/downcase' | '/capitalize' | '/camelcase' | '/pascalcase' | '/snakecase' | '/kebabcase' '}' | '${' int ':+' if '}' | '${' int ':?' if ':' else '}' | '${' int ':-' else '}' | '${' int ':' else '}' regex ::= JavaScript Regular Expression value (ctor-string) options ::= JavaScript Regular Expression option (ctor-options) var ::= [_a-zA-Z] [_a-zA-Z0-9]* int ::= [0-9]+ text ::= .* if ::= text else ::= text从该文法可以看出,format中除了引用分组编号外,还内置了upcase、downcase、capitalize、camelcase、pascalcase、snakecase、kebabcase等大小写/命名风格转换,以及:+(存在时插入)、:?(条件二选一)、:-(缺省值)等条件格式。
使用 TextMate 代码片段
如果手头已有现成的 TextMate 片段(.tmSnippets文件),也可以直接用于 VS Code。推荐的方式是将它们打包为扩展,具体流程见 API 文档中的 TextMate 片段章节。打包后,VS Code 会负责将.tmSnippets转换为自身的片段格式并加载。
将片段打包为扩展进行共享
除了给自己使用,片段还可以打包成扩展上传到扩展市场与团队或社区共享。完整的操作流程记录在 api/language-extensions/snippet-guide.md 中,核心步骤如下:
- 先用Snippets: Configure User Snippets命令创建并测试你的片段;
- 满意后,把整个 JSON 片段文件复制到扩展目录中(例如
snippets.json); - 在扩展的
package.json中通过contributes.snippets贡献点声明片段文件:
{ "contributes": { "snippets": [ { "language": "javascript", "path": "./snippets.json" } ] } }其中language为语言标识符,path为片段文件的相对路径,文件内容即本文介绍的 VS Code 片段 JSON 格式。
- 提示:在
package.json中加入以下配置,将扩展标记为"代码片段类"扩展,便于在市场上被@category:"snippets"检索到:
{ "categories": ["Snippets"] }此外,也可以使用yo code扩展生成器(New Code Snippets选项)直接指向一个包含多个.tmSnippets文件的文件夹,生成器会将其打包为 VS Code 片段扩展,同时支持 Sublime 片段(.sublime-snippets)。生成结果包含两个文件:扩展清单package.json和转换后的snippets.json:
. ├── snippets // VS Code integration │ └── snippets.json // The JSON file w/ the snippets └── package.json // extension's manifest将生成的snippets文件夹复制到.vscode/extensions下的新目录并重启 VS Code 即可生效。
为代码片段分配键盘快捷键
你可以通过自定义键盘快捷键直接插入指定片段。打开keybindings.json(命令Preferences: Open Keyboard Shortcuts File),添加一条将"snippet"作为额外参数传给editor.action.insertSnippet的键绑定:
{ "key": "cmd+k 1", "command": "editor.action.insertSnippet", "when": "editorTextFocus", "args": { "snippet": "console.log($1)$0" } }这样按下该快捷键时会直接执行Insert Snippet命令,但不再弹出选择列表,而是插入args.snippet中定义的片段文本。键绑定与普通快捷键一样,由键盘组合、命令 ID 和可选的 when clause 上下文(控制快捷键何时生效)组成。
除了内联定义片段,还可以通过langId与name参数引用已有片段:langId指定片段所属语言,name指定片段名称。下面的示例会在按下快捷键时插入csharp语言中名为myFavSnippet的片段:
{ "key": "cmd+k 1", "command": "editor.action.insertSnippet", "when": "editorTextFocus", "args": { "langId": "csharp", "name": "myFavSnippet" } }值得注意的是,jumpToNextSnippetPlaceholder(跳转到下一个占位符)默认绑定在 Tab 键上,并可通过keybindings.json调整或移除,相关说明见 docs/configure/keybindings.md。
常见问题
如何在插入的脚本中放入一个变量?
如果希望片段插入后保留$variable形式的字面文本,需要转义$,使其不会被片段展开阶段解析为变量。例如:
"VariableSnippet":{ "prefix": "_Var", "body": "\\$MyVar = 2", "description": "A basic snippet that places a variable into script with the $ prefix" }插入结果为:
$MyVar = 2如何从 IntelliSense 中移除某个片段?
可以隐藏特定片段,使其不再出现在 IntelliSense(补全列表)中:在Insert Snippet命令的下拉列表中,点击片段条目右侧的Hide from IntelliSense按钮即可。隐藏后,你仍可通过Insert Snippet命令选择该片段,但它不会出现在 IntelliSense 建议中。
下一步
- 命令行界面:VS Code 提供丰富的命令行接口,可打开/比较文件、安装扩展;
- 扩展 API:了解扩展 VS Code 的更多方式;
- Snippet Guide:学习如何将片段打包为扩展,在 VS Code 中使用。
- 文档
- 教程
【免费下载链接】vscode-docs
Public documentation for Visual Studio Code
相关推荐
10分钟掌握Visual Studio Code代码片段:自定义模板与智能触发全指南
10分钟掌握Visual Studio Code代码片段:自定义模板与智能触发全指南 Visual Studio Code(VS Code)作为最受欢迎的代码编
开发工具代码编辑器如何高效使用Atom代码片段:自定义语言模板与动态变量完全指南
如何高效使用Atom代码片段:自定义语言模板与动态变量完全指南 Atom作为一款高度可定制的文本编辑器,其代码片段(Snippets)功能能显著提升开发效率。本
代码编辑器桌面应用开发工具Onivim 2 代码片段(Snippets)完整指南:补全、占位符导航与自定义
Onivim 2 代码片段(Snippets)完整指南:补全、占位符导航与自定义 代码片段(Snippets)是文本模板,用于简化常见源码块的输入,尤其适合那些
开发工具代码编辑器桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考