Visual Studio Code 中的代码片段
代码片段是模板,可让您更轻松地输入重复的代码模式,例如循环或条件语句。
在 Visual Studio Code 中,代码片段会出现在 IntelliSense (⌃Space (Windows、Linux Ctrl+Space)) 中,与其他建议混杂在一起,也会出现在专门的代码片段选择器中(命令面板中的插入代码片段)。还支持制表符补全:启用 "editor.tabCompletion": "on"
,键入代码片段前缀(触发文本),然后按 Tab 插入代码片段。
代码片段语法遵循 TextMate 代码片段语法,但有以下例外:“内插 shell 代码”和 \u
的使用;两者均不受支持。
内置代码片段
VS Code 针对许多语言(例如:JavaScript、TypeScript、Markdown 和 PHP)内置了代码片段。
您可以通过在命令面板中运行插入代码片段命令来查看语言的可用代码片段列表,以获取当前文件语言的代码片段列表。但是,请记住,此列表还包括您定义的任何用户代码片段,以及您已安装的扩展提供的任何代码片段。
从市场安装代码片段
VS Code Marketplace 上的许多扩展都包含代码片段。您可以使用 @category:"snippets"
筛选器在扩展视图 (⇧⌘X (Windows、Linux Ctrl+Shift+X)) 中搜索包含代码片段的扩展。
如果您找到要使用的扩展,请安装它,然后重新启动 VS Code,新的代码片段将可用。
创建您自己的代码片段
您可以轻松定义自己的代码片段,而无需任何扩展。要创建或编辑您自己的代码片段,请在文件 > 首选项下选择配置代码片段,然后选择代码片段应出现的语言(通过语言标识符),或者选择新建全局代码片段文件选项,如果它们应出现在所有语言中。VS Code 会为您管理底层代码片段文件的创建和刷新。
代码片段文件以 JSON 编写,支持 C 风格注释,并且可以定义无限数量的代码片段。代码片段支持大多数 TextMate 语法以实现动态行为,根据插入上下文智能格式化空白,并允许轻松进行多行编辑。
以下是 JavaScript 的 for
循环代码片段示例
// 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
。您可以使用 Tab 快速跳到下一个占位符,此时您可以编辑占位符或跳到下一个占位符。冒号 :
后面的字符串(如果有)是默认文本,例如 ${2:element}
中的 element
。占位符遍历顺序按数字递增,从 1 开始;0 是一个可选的特殊情况,始终在最后出现,并在光标位于指定位置时退出代码片段模式。
文件模板代码片段
如果代码片段旨在填充或替换文件内容,则可以向代码片段的定义添加 isFileTemplate
属性。当您在新文件或现有文件中运行代码片段:从代码片段填充文件命令时,文件模板代码片段会显示在下拉列表中。
代码片段范围
代码片段是有作用域的,以便仅建议相关的代码片段。代码片段可以按以下方式进行作用域
- 代码片段作用域的语言(可能全部)
- 代码片段作用域的项目(可能全部)
语言代码片段作用域
每个代码片段都根据其定义位置而作用域到一个、多个或所有(“全局”)语言
- 语言代码片段文件
- 全局代码片段文件
单语言用户定义的代码片段定义在特定语言的代码片段文件中(例如 javascript.json
),您可以通过代码片段:配置代码片段按语言标识符访问这些代码片段。代码片段仅在编辑定义其语言时才可访问。
多语言和全局用户定义的代码片段都定义在“全局”代码片段文件(带有文件后缀 .code-snippets
的 JSON 文件)中,也可以通过代码片段:配置代码片段访问。在全局代码片段文件中,代码片段定义可以有一个附加的 scope
属性,该属性接受一个或多个语言标识符,这使得该代码片段仅适用于那些指定的语言。如果没有给定 scope
属性,则全局代码片段在所有语言中都可用。
大多数用户定义的代码片段作用域到一个单一语言,因此定义在特定语言的代码片段文件中。
项目代码片段作用域
您还可以拥有一个作用域到项目的全局代码片段文件(带有文件后缀 .code-snippets
的 JSON 文件)。项目文件夹代码片段是通过代码片段:配置代码片段下拉菜单中的为“<文件夹名称>”新建代码片段文件...选项创建的,并位于项目根目录的 .vscode
文件夹中。项目代码片段文件对于与在该项目中工作的所有用户共享代码片段非常有用。项目文件夹代码片段类似于全局代码片段,可以通过 scope
属性作用域到特定语言。
代码片段语法
代码片段的 body
可以使用特殊构造来控制光标和要插入的文本。以下是支持的功能及其语法
制表位
使用制表位,您可以让编辑器光标在代码片段内移动。使用 $1
、$2
指定光标位置。数字是制表位被访问的顺序,而 $0
表示最终光标位置。同一制表位的多次出现是链接的,并同步更新。
占位符
占位符是带有值的制表位,例如 ${1:foo}
。占位符文本将被插入并选中,以便可以轻松更改。占位符可以嵌套,例如 ${1:another ${2:placeholder}}
。
选择
占位符可以有值作为选择。语法是逗号分隔的值枚举,用管道符括起来,例如 ${1|one,two,three|}
。当插入代码片段并选中占位符时,选择将提示用户选择其中一个值。
变量
使用 $name
或 ${name:default}
,您可以插入变量的值。当变量未设置时,将插入其默认值或空字符串。当变量未知(即其名称未定义)时,将插入变量的名称并将其转换为占位符。
可以使用以下变量
TM_SELECTED_TEXT
当前选定的文本或空字符串TM_CURRENT_LINE
当前行的内容TM_CURRENT_WORD
光标下单词的内容或空字符串TM_LINE_INDEX
基于零的行号TM_LINE_NUMBER
基于一的行号TM_FILENAME
当前文档的文件名TM_FILENAME_BASE
当前文档不带扩展名的文件名TM_DIRECTORY
当前文档的目录TM_FILEPATH
当前文档的完整文件路径RELATIVE_FILEPATH
当前文档的相对(相对于打开的工作区或文件夹)文件路径CLIPBOARD
剪贴板的内容WORKSPACE_NAME
打开的工作区或文件夹的名称WORKSPACE_FOLDER
打开的工作区或文件夹的路径CURSOR_INDEX
基于零的光标编号CURSOR_NUMBER
基于一的光标编号
用于插入当前日期和时间
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_SECONDS_UNIX
自 Unix 纪元以来的秒数CURRENT_TIMEZONE_OFFSET
当前 UTC 时区偏移量,格式为+HH:MM
或-HH:MM
(例如-07:00
)。
用于插入随机值
RANDOM
6 位随机十进制数字RANDOM_HEX
6 位随机十六进制数字UUID
版本 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"
}
}
变量转换
转换允许您在插入变量值之前修改它。转换的定义包括三个部分
- 一个与变量值匹配的正则表达式,如果变量无法解析,则为空字符串。
- 一个“格式字符串”,允许引用正则表达式中的匹配组。格式字符串允许条件插入和简单修改。
- 传递给正则表达式的选项。
以下示例插入当前文件的名称而不带其结尾,因此将 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
占位符转换
与变量转换一样,占位符的转换允许在移动到下一个制表位时更改占位符的插入文本。插入的文本与正则表达式匹配,并且匹配项(或多个匹配项,取决于选项)将替换为指定的替换格式文本。占位符的每次出现都可以使用第一个占位符的值独立定义其自己的转换。占位符转换的格式与变量转换相同。
转换示例
这些示例以双引号显示,因为它们会出现在代码片段主体中,以说明需要双重转义某些字符。文件名为 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 |
删除非字母数字字符 |
语法
以下是代码片段的 EBNF(扩展巴克斯-诺尔范式)。使用 \
(反斜杠),您可以转义 $
、}
和 \
。在选择元素中,反斜杠也会转义逗号和竖线字符。只有需要转义的字符才能被转义,因此在这些构造中不应转义 $
,在选择构造中也不应转义 $
或 }
。
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' '}'
| '${' 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
使用 TextMate 代码片段
您还可以将现有的 TextMate 代码片段 (.tmSnippets) 与 VS Code 一起使用。有关更多信息,请参阅我们的扩展 API 部分中的使用 TextMate 代码片段主题。
为代码片段分配键盘快捷键
您可以创建自定义键盘快捷键来插入特定代码片段。打开 keybindings.json
(首选项:打开键盘快捷键文件),其中定义了所有键盘快捷键,然后添加一个传递 "snippet"
作为额外参数的键盘快捷键
{
"key": "cmd+k 1",
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"snippet": "console.log($1)$0"
}
}
键盘快捷键将调用插入代码片段命令,但它不会提示您选择代码片段,而是插入提供的代码片段。您可以像往常一样使用键盘快捷键、命令 ID 和可选的when 子句上下文来定义自定义键绑定,以确定何时启用键盘快捷键。
此外,您可以使用 langId
和 name
参数来引用现有代码片段,而不是使用 snippet
参数值内联定义代码片段。langId
参数选择由 name
表示的代码片段要插入的语言,例如,下面的示例选择可用于 csharp
文件的 myFavSnippet
。
{
"key": "cmd+k 1",
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"langId": "csharp",
"name": "myFavSnippet"
}
}
后续步骤
- 命令行 - VS Code 具有丰富的命令行界面,可用于打开或比较文件以及安装扩展。
- 扩展 API - 了解扩展 VS Code 的其他方式。
- 代码片段指南 - 您可以将代码片段打包以在 VS Code 中使用。
常见问题
如果我想使用 .tmSnippet 文件中的现有 TextMate 代码片段怎么办?
您可以轻松地将 TextMate 代码片段文件打包以在 VS Code 中使用。请参阅我们的扩展 API 文档中的使用 TextMate 代码片段。
如何让代码片段将变量放置在粘贴的脚本中?
要在粘贴的脚本中包含变量,您需要转义 $variable
名称中的“$”,使其不会被代码片段展开阶段解析。
"VariableSnippet":{
"prefix": "_Var",
"body": "\\$MyVar = 2",
"description": "A basic snippet that places a variable into script with the $ prefix"
}
这导致粘贴的代码片段如下
$MyVar = 2
我可以从 IntelliSense 中删除代码片段吗?
是的,您可以通过选择插入代码片段命令下拉列表中代码片段项右侧的从 IntelliSense 中隐藏按钮来隐藏特定代码片段,使其不显示在 IntelliSense(完成列表)中。
您仍然可以使用插入代码片段命令选择代码片段,但隐藏的代码片段将不会显示在 IntelliSense 中。