[TOC] ## 代码段 代码片段是一种模板,可以更轻松地输入重复的代码模式,例如循环或条件语句。 在Visual Studio代码中,片段显示在IntelliSense(Ctrl + Space)中,与其他建议以及专用片段选择器(命令选项板中的“ 插入片段”)混合使用。还有对tab-completion的支持:启用它`"editor.tabCompletion": true`,键入一个片段前缀,然后按Tab键插入一个片段。 片段语法遵循TextMate片段语法,但“`插值shell代码`”和使用`\u`除外; 两者都不受支持。 ## 从市场添加片段 VS Code Marketplace上的许多扩展包括代码段。如果您找到了要使用的设备,请安装它并重新启动VS Code并使用新的代码段(有关安装扩展程序的更多说明,请参阅此处)。 ## 创建自己的代码段 您可以定义自己的代码段,全局代码段或特定语言的代码段。为了开拓编辑,选择一个代码片断文件用户摘录下的文件 > 首选项(代码 > 首选项在MacOS),然后选择语言(由语言标识符)该片段应出现或创建一个新的全球段(新的全球片段文件。 ..)。 ![](https://box.kancloud.cn/aa9a08c25a9bda8452f9f21745665800_906x398.png) 片段以JSON格式定义。以下示例是For Loop您将用于JavaScript 的代码段: ```json { "For_Loop": { "prefix": "for", "body": [ "for (const ${2:element} of ${1:array}) {", "\t$0", "}" ], "description": "For Loop" } } ``` >[info]在上面的例子中: * For Loop 是片段名称。 * prefix定义如何从IntelliSense和选项卡完成中选择此代码段。在这种情况下for。 * body 是内容,可以是单个字符串,也可以是字符串数组,每个字符串都将作为单独的行插入。 * description 是IntelliSense下拉列表中使用的描述。 >上面的例子有两个占位符,${1:array}和${2:element}。您可以按照其编号顺序快速遍历它们。数字和冒号后面的字符串用作初始默认值。 ## 代码段文件名 文件类型和名称定义片段是全局的还是特定于语言的。存储在以语言标识符(<languageId>.json)命名的JSON文件中的代码段是特定于语言的。例如,仅限JavaScript的代码段会放入javascript.json文件中。 ## 全局代码段 例如,无论何时编辑并存储在<name>.code-snippets文件中,都适用的全局片段MyGlobal.code-snippets。全局代码段的JSON模式允许您定义一个scope属性,该属性可以过滤适用于该代码段的语言(基于语言标识符)。 下面的示例再次是For Loop,但这次它的范围是JavaScript 和 TypeScript。 ```json { "For_Loop": { "prefix": "for", "scope": "javascript,typescript", "body": [ "for (const ${2:element} of ${1:array}) {", "\t$0", "}" ], "description": "For Loop" } } ``` 添加新代码段后,您可以立即尝试,无需重新启动。 ## 片段语法 该body片段可以使用特殊的结构来控制插入光标和文字。以下是支持的功能及其语法: ### 制表位 使用tabstops,您可以使编辑器光标在代码段内移动。使用`$1`,`$2`指定光标位置。数字是访问tabstops的顺序,而$0表示最终光标位置。同一个tabstop的多次出现被链接并同步更新。 ### 占位符 占位符是带有值的tabstops,例如`${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 剪贴板的内容 用于插入当前日期和时间: * 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 目前的第二个 >[info]以上的这些变量是很有用的,比如在创建文件头部信息的时候。 ### 变量变换 转换允许您在插入变量之前修改变量的值。转型的定义包括三个部分: 1. 与变量值匹配的正则表达式,或无法解析变量时的空字符串。 2. “格式字符串”,允许从正则表达式引用匹配组。格式字符串允许条件插入和简单修改。 3. 传递给正则表达式的选项。 以下示例插入当前文件的名称而不是其结尾,因此从中foo.txt进行foo。 ```txt ${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-Transforms的格式与Variable-Transforms的格式相同。 #### 转换示例 这些示例显示在双引号内,因为它们会显示在代码段内,以说明需要双重转义某些字符。样本转换以及文件名的结果输出`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形式)。使用\(反斜杠),你可以逃避$,}并且\。在选择元素中,反斜杠也会转义逗号和管道字符。 ```txt 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 ::= .* ``` ## 使用TextMate片段 您还可以将现有的TextMate代码段(.tmSnippets)与VS代码一起使用。有关详细信息,请参阅“ 扩展创作”部分中的“ 使用TextMate代码段”主题。 ## 将键绑定分配给片段 您可以创建自定义键绑定以插入特定代码段。打开keybindings.json(首选项:打开键盘快捷键文件),它定义所有键绑定,并添加"snippet"作为额外参数传递的键绑定: ```json { "key": "cmd+k 1", "command": "editor.action.insertSnippet", "when": "editorTextFocus", "args": { "snippet": "console.log($1)$0" } } ``` 键绑定将调用Insert Snippet命令,但不会提示您选择片段,而是会插入提供的片段。您可以像往常一样使用键盘快捷键,命令ID和可选的when子句上下文定义自定义键绑定,以启用键盘快捷键。 此外,snippet您可以使用langId和name参数引用现有的代码段,而不是使用参数值来定义内联代码段: ```json { "key": "cmd+k 1", "command": "editor.action.insertSnippet", "when": "editorTextFocus", "args": { "langId": "csharp", "name": "myFavSnippet" } } ``` ## 示例:使用变量来自动填充js文件头 ```json "print to jsHeader":{ "prefix": "jsh", "body": [ "/**", " * @file $TM_FILENAME", " * @author YYago <877675862@qq.com>", " * Date: $CURRENT_YEAR/$CURRENT_MONTH/$CURRENT_DATE", " * LICENSE:", " * MIT License", " *", " * Copyright (c) 2018 YYago", " *", " * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:", " *", " * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.", " *", " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ", " * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", " * ", " */" ], "description": "Add JS header with license。" } ``` >[info] 这是在文件头部加入文件名、创建日期、作者信息以及代码开源协议内容。键入的时候输入`jsh`之后选择对应的项即可输入对应的内容。 效果如下: ```js /** * @file getTime.js * @author YYago <877675862@qq.com> * Date: 2018/10/13 * LICENSE: * MIT License * * Copyright (c) 2018 YYago * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ ``` >[info]我最近逛了下vscode的扩展商城(插件商城),已经有很多的这种类似注释用的扩展,看了描述还是不错的,使用扩展可以免去自己写片段的麻烦。用`comment`作为关键词在vscode扩展区去搜索就能发现它们了。 ## 注意细节处理 由于vscode的代码片段使用JSON格式,因此某些符号会造成JSON语法错误而不能成功运行。比如Jquery.js 的"$"符号会和占位符冲突、JS常量的值的字符类型和JSON语法符号冲突:"`"`"和"`{、}`"以及"`[、]`"等。 解决的方法是使用转义符“`\`”: ```json body:[ "var foo = \"123\"" ] ``` >[info] 碰到`$、{、}`的时候使用双反斜杠:`\\` ```json "body":"\\$CURRENT_YEAR" ``` >[info] 只要不造成JSON语法错误就行(语法错误vscode会用红色波浪底线提示的),至少填充到文件的时候不会因为语法错误而不能键入。