Vs code添加自定义snippet
Vs code添加自定义snippet(代码段)
前言
代码段能够帮助输入重复代码模式,在智能感知下可以帮我们快速补全代码,节省时间方便之余更利于代码格式的统一规范化。
1. Vs code代码段配置
1.1 配置方法
进入配置方法:
1.File--Preferences--User Snippets--
我们选择新建一个全局的代码段配置文件 New Globar Snippers File
2.通过快捷键「Ctrl + Shift + P」打开命令窗口,输入「snippet」,点选「Preferences: Config User Snippets」,然后同上;
wh.code-snippets
{
// Place your global snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
// Placeholders with the same ids are connected.
// Example:
// "Print to console": {
// "scope": "javascript,typescript",
// "prefix": "log",
// "body": [
// "console.log('$1');",
// "$2"
// ],
// "description": "Log output to console"
// }
"create a new c source file": {
"prefix": "filec",
"body": [
"/**\n * @file ${TM_FILENAME}",
" * @brief $1",
" * @author wangh (wanghuan3037@fiberhome.com)",
" * @version 1.0",
" * @date $CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE",
" * @copyright Copyright (c) $CURRENT_YEAR 烽火通信",
" ***************************************************************",
" * @par 修改日志:",
" * <table>",
" * <tr><th>Date <th>Version <th>Author <th>Description",
" * <tr><td>2019-11-17 <td>1.0 <td>wangh <td>内容",
" * </table>",
" */",
"\n\n\n\n",
"/*********** (C) COPYRIGHT $CURRENT_YEAR FiberHome *****END OF FILE****/\n"
]
},
"create a new c head file": {
"prefix": "fileh",
"body": [
"/**\n * @file ${TM_FILENAME}",
" * @brief ",
" * @author wangh (wanghuan3037@fiberhome.com)",
" * @version 1.0",
" * @date $CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE",
" * @copyright Copyright (c) $CURRENT_YEAR 烽火通信",
" */",
"#ifndef __${1:${TM_FILENAME/(.*)\\.h$/${1:/upcase}_H/i}}",
"#define __$1",
"\n\n\n\n",
"#endif\t // __$1 \n",
"/*********** (C) COPYRIGHT $CURRENT_YEAR FiberHome *****END OF FILE****/\n"
],
},
"Define a struct": {
"prefix": "defstruct",
"body": "typedef struct \n{\n\t$2\n\t$3\n} ${1:name_t};"
},
"Define a enum": {
"prefix": "defenum",
"body": "typedef enum \n{\n\t$2\n\t$3\n} ${1:name_t};"
},
"main()": {
"prefix": "main",
"body": [
"int main(int argc, char const *argv[])",
"{\n\t$1\n\treturn 0;\n}"
]
},
"For loop": {
"prefix": "for",
"body": [
"for (${1:i} = 0; ${1:i} < ${2:count}; ${1:i}${3:++})",
"{\n\t$4\n}"
]
},
"Do while loop": {
"prefix": "do",
"body": "do {\n\t$0\n} while($1);"
},
"While loop": {
"prefix": "while",
"body": "while ($1)\n{\n\t$2\n}"
},
"Switch case": {
"prefix": "switch",
"body": [
"switch ($1) {",
"case $2:\n\t$3\n\tbreak;\n",
"default:\n\tbreak;\n}$0"
]
},
"printf()": {
"prefix": "printf",
"body": "printf(\"${1:%s }\\n\", $2);$3"
},
}
1.2 使用效果
新建一个 test.c 文件
输入 "filec" 一般右侧会弹出匹配项,上下键选择 filec 回车,效果如下:
/**
* @file test.c
* @brief 测试文件
* @author wangh (wanghuan3037@fiberhome.com)
* @version 1.0
* @date 2019-11-17
* @copyright Copyright (c) 2019 烽火通信
***************************************************************
* @par 修改日志:
* <table>
* <tr><th>Date <th>Version <th>Author <th>Description
* <tr><td>2019-11-17 <td>1.0 <td>wangh <td>内容
* </table>
*/
/*********** (C) COPYRIGHT 2019 FiberHome *****END OF FILE****/
新建一个 test.h 文件
输入 "filec" 一般右侧会弹出匹配项,上下键选择 filec 回车,效果如下:
/**
* @file test.h
* @brief
* @author wangh (wanghuan3037@fiberhome.com)
* @version 1.0
* @date 2019-11-17
* @copyright Copyright (c) 2019 烽火通信
*/
#ifndef __TEST_H
#define __TEST_H
#endif // __TEST_H
/*********** (C) COPYRIGHT 2019 FiberHome *****END OF FILE****/
其他代码段可根据自己设置的名称予以测试。
2. 代码段配置语法
下面主要是基于官方文档的翻译及总结。
2.1 json格式
我们以一个简单的示例来说明组成
{
"For Loop": {
"prefix": ["for", "for-const"],
"body": ["for (const ${2:element} of ${1:array}) {", "\t$0", "}"],
"description": "A for loop."
}
}
在上面的示例中:
- “ For Loop”是代码段名称。
prefix
定义一个或多个触发词,这些触发词在IntelliSense中显示摘要。子字符串匹配在前缀上执行,因此在这种情况下,“ fc”可以匹配“ for-const”。body
是一或多个内容行,插入时将作为多行加入。换行符和嵌入的选项卡将根据插入代码段的上下文进行格式化。description
是IntelliSense显示的代码段的可选描述。scope
在使用全局配置时有用,可以配置其适用语言,不填则代表适用于所有语言。
另外,所述body
的例子中的上述具有三个占位符(在遍历顺序列出): ,${1:array}
,${2:element}
和$0
。您可以使用Tab快速跳到下一个占位符,此时您可以编辑占位符或再次跳到下一个占位符。冒号之后的字符串是默认的文本,例如element
在${2:element}
。占位符遍历顺序从数字开始递增,从1开始;零是一种可选的特殊情况,它总是最后出现,并在光标位于指定位置时退出摘要模式。
2.2 语法
涉及到语法的主要时 body
段,可以使用特殊的结构来控制插入光标和文字。以下是受支持的功能及其语法:
制表符
使用制表符,可以使编辑器光标在摘要中移动。使用$1
,$2
指定游标的位置,是按Tab键访问的顺序,$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
当前文档的完整文件路径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
一天的名称(例如“周一”)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//
或HTML<!-- -->
以下代码段可插入/* Hello World */
JavaScript文件和<!-- Hello World -->
HTML文件中:
{
"hello": {
"scope": "javascript,html", // 限定作用语言
"prefix": "hello",
"body": "$BLOCK_COMMENT_START Hello World $BLOCK_COMMENT_END"
}
}
可变变换
转换允许您在插入变量之前修改变量的值。转换的定义包括三个部分:
- 与变量值匹配的正则表达式,或者在无法解析变量时为空字符串。
- 一个“格式字符串”,它允许从正则表达式中引用匹配的组,格式字符串允许条件插入和简单修改。
- 传递给正则表达式的选项。
关于正则表达式可以参考 JavaScript RegExp 对象
以下示例是我们头文件定义时使用的,以此为例进行说明
${1:${TM_FILENAME/(.*)\\.h$/${1:/upcase}_H/i}}
- TM_FILENAME:本文件名 test.c
- (.*)\.h$ :正则表达式 ()里面表示TM_FILENAME除去 .h的部分
- ${1:/upcase}_H:${1:/upcase}表示正则表达式第一个()大写,然后在加上 _H
- i:不区分大小写
以下示例插入了当前文件的名称而没有结尾,因此从foo.txt
该名称开始foo
。
${TM_FILENAME/(.*)\\..+$/$1/}
| | | |
| | | |-> 选项
| | |
| | |-> 第一个正则匹配捕获的内容
| |
| |-> 正则表达式
|
|-> 待转换的变量值
占位符转换
与变量转换一样,占位符的转换允许在移至下一个制表位时更改占位符的插入文本。插入的文本与正则表达式匹配,并且一个或多个匹配项(取决于选项)将替换为指定的替换格式文本。每次出现占位符都可以使用第一个占位符的值独立定义其自己的转换。占位符转换的格式与变量转换的格式相同。
转换示例
这些示例在双引号中显示,因为它们将出现在摘要正文中,以说明需要对某些字符进行两次转义。样本转换和文件名的结果输出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 |
删除非字母数字字符 |
语法
以下是摘要的EBNF(扩展的Backus-Naur形式)。随着\
(反斜线),你可以逃脱$
,}
和\
。在选择元素中,反斜杠还会转义逗号和竖线字符。
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' '}'
| '${' 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 ::= .*