[TOC]
## 代碼段
代碼片段是一種模板,可以更輕松地輸入重復的代碼模式,例如循環或條件語句。
在Visual Studio代碼中,片段顯示在IntelliSense(Ctrl + Space)中,與其他建議以及專用片段選擇器(命令選項板中的“ 插入片段”)混合使用。還有對tab-completion的支持:啟用它`"editor.tabCompletion": true`,鍵入一個片段前綴,然后按Tab鍵插入一個片段。
片段語法遵循TextMate片段語法,但“`插值shell代碼`”和使用`\u`除外; 兩者都不受支持。
## 從市場添加片段
VS Code Marketplace上的許多擴展包括代碼段。如果您找到了要使用的設備,請安裝它并重新啟動VS Code并使用新的代碼段(有關安裝擴展程序的更多說明,請參閱此處)。
## 創建自己的代碼段
您可以定義自己的代碼段,全局代碼段或特定語言的代碼段。為了開拓編輯,選擇一個代碼片斷文件用戶摘錄下的文件 > 首選項(代碼 > 首選項在MacOS),然后選擇語言(由語言標識符)該片段應出現或創建一個新的全球段(新的全球片段文件。 ..)。

片段以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會用紅色波浪底線提示的),至少填充到文件的時候不會因為語法錯誤而不能鍵入。