# Add code snippets for CLANG in VS Code
> **前記**:在VS Code中自定義snippets用戶代碼段的方法。
* * *
* [Add code snippets for CLANG in VS Code](http://blog.csdn.net/maokelong95/article/details/54379046#add-code-snippets-for-clang-in-vs-code)
* [什么是 snippet](http://blog.csdn.net/maokelong95/article/details/54379046#什么是-snippet)
* [如何配置snippet](http://blog.csdn.net/maokelong95/article/details/54379046#如何配置snippet)
* [操作流程](http://blog.csdn.net/maokelong95/article/details/54379046#操作流程)
* [VSCode中snippet的文法1](http://blog.csdn.net/maokelong95/article/details/54379046#vscode中snippet的文法1)
* [有用的建議](http://blog.csdn.net/maokelong95/article/details/54379046#有用的建議)
## 什么是 snippet
`snippet[?sn?p?t]`,或者說`code snippet`,指的是能夠幫助輸入重復代碼模式串,比如循環或條件語句的**模板**。通過`snippet`,僅僅輸入一小段代碼就可以生成預定義的模板代碼,甚至可以通過內部跳轉快速補全模板。
當然,看圖更易懂:?

圖中將`atc`替換成了定義ActiveSupport::TestCase(簡稱ATC)子類的模板,并跳轉到`case_name`處進行了修改 .etc.
## 如何配置snippet
### 操作流程
1. 進入snippet設置文件?
這里提供了兩種方法:?
1. 按`alt`鍵切換菜單欄,通過**文件**>**首選項**>**用戶代碼片段**,選擇進入目的語言的代碼段設置文件;
2. 通過快捷鍵`ctrl`+`shift`+`P`打開命令窗口(all command window),輸入`snippet`,通過候選欄中的選項進入目的語言的代碼段設置文件。
2. 填寫snippets
### VSCode中snippet的文法[1](http://blog.csdn.net/maokelong95/article/details/54379046#fn:vscode "See footnote")
設置文件頭部通過一個塊注釋講解了snippet的文法,了解`json`就不會對此感到奇怪了。
~~~
// Place your snippets for C here. Each snippet is defined under a snippet name and has a prefix, body and
// description. 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": {
"prefix": "log",,
"body": [
"console.log('$1');",
"$2"
],
"description": "Log output to console"
}
~~~
上例snippet在輸入log后效果如下,在確定后將替換為`console.log('');`。?

snippet由三部分組成:
* **prefix**:前綴,定義了snippets 從IntelliSense中呼出的關鍵字;
* **body**: 主體,即模板的主體內容,每個字符串表示一行;
* **description**:說明,會在IntelliSense候選欄中出現。未定義的情況下顯示對象名,上例中將會顯示`Print to console`。
其中**body**部分可以使用特殊結構來控制光標和要插入的文本。 支持的功能及其文法如下:
* **Tabstops**:制表符
用`Tabstops`可以讓編輯器的指針在代碼段內跳轉。使用`$1`,`$2`?.etc. 指定光標位置。這些數字指定了`Tabstops`將被訪問的順序,而`$0`表示最終光標位置。同序`Tabstops`被鏈接在一起,并將同步更新,比如下列用于生成頭文件封裝的snippet打印在編輯器上時,指針就將同時出現在`$1`位置以進行多列編輯。
~~~
"#ifndef $1"
"#define $1"
"#end // $1"
~~~
* **Placeholders**:占位符
`placeholder`是帶有默認值的`Tabstops`,如`${1:foo}`。?`placeholder`文本將被插入`Tabstops`位置,并在跳轉時被全選,以方便輕松更改。占位符還可以嵌套,例如`${1:another ${2:placeholder}}`。
比如結構體的snippet主體可以這樣寫:
~~~
struct ${1:name_t} {\n\t$2\n};
~~~
作為`Placeholder`的`name_t`一方面可以提供默認的結構名稱,另一方面可以作為輸入的提示。
* **Variables**:變量
使用`$name`或`${name:default}`可以插入變量的值。 當未設置變量時,將插入其缺省值或空字符串。 當`varibale`未知(即,其名稱未定義)時,將插入變量的名稱,并將其轉換為`placeholder`。 可以使用以下`Variable`:
* `TM_SELECTED_TEXT`:當前選定的文本或空字符串
* `TM_CURRENT_LINE`:當前行的內容
* `TM_CURRENT_WORD`:光標下的單詞的內容或空字符串
* `TM_LINE_INDEX`:基于零索引的行號
* `TM_LINE_NUMBER`:基于一索引的行號
* `TM_FILENAME`:當前文檔的文件名
* `TM_DIRECTORY`:當前文檔的目錄
* `TM_FILEPATH`:當前文檔的完整文件路徑
注意,這些都是變量名,不是宏,在實際使用的時候還是要加上$符的。
官網也給出了snippet的EBNF范式的正則文法,注意,使用`\`(反斜杠)轉義`\$`,?`,`,?`}`和`\`。
~~~
any ::= tabstop | placeholder | variable | text
tabstop ::= '$' int | '${' int '}'
placeholder ::= '${' int ':' any '}'
variable ::= '$' var | '${' var }' | '${' var ':' any '}'
var ::= [_a-zA-Z] [_a-zA-Z0-9]*
int ::= [0-9]+
text ::= .*
~~~
### 有用的建議
默認情況下snippet在IntelliSense中的顯示優先級并不高,而且要在IntelliSense中選擇相應snippet需要敲擊enter,這對于手短的人來說并不是什么很好的體驗。所幸,VSCode意識到了這一點,并為我們提供了改進的方式。
在VSCode的**用戶設置**(ctrl+P在輸入框中寫`user settings`后點選)中,檢索**代碼段**,然后根據提示修改,設置建議優先顯示,并且可以通過`TAB`補全snippet。

修改后設置文件中會多出這兩行:
~~~
"editor.snippetSuggestions": "top",
"editor.tabCompletion": true
~~~