Visual Studio Code 中的程式碼片段
程式碼片段(Snippets)是一些模板,可讓您更輕鬆地輸入重複的程式碼模式,例如迴圈或條件語句。
在 Visual Studio Code 中,程式碼片段會與其他建議一起出現在 IntelliSense (⌃Space (Windows, Linux Ctrl+Space)) 中,也會出現在專門的程式碼片段選擇器(在命令面板中選擇“插入程式碼片段”)中。此外,還支援 Tab 補全:透過 "editor.tabCompletion": "on"
啟用此功能,然後鍵入一個程式碼片段字首(觸發文字),再按 Tab 即可插入程式碼片段。
程式碼片段的語法遵循 TextMate snippet syntax,但不支援“內插 shell 程式碼”和 \u
的使用。
內建程式碼片段
VS Code 為多種語言內建了程式碼片段,例如:JavaScript、TypeScript、Markdown 和 PHP。
你可以在命令面板中執行“插入程式碼片段”命令,檢視當前檔案語言可用的程式碼片段列表。不過請記住,此列表也包括您自己定義的使用者程式碼片段以及您安裝的擴充套件提供的任何程式碼片段。
從市場安裝程式碼片段
VS Code 市場上的許多擴充套件都包含程式碼片段。你可以在擴充套件檢視 (⇧⌘X (Windows, Linux Ctrl+Shift+X)) 中使用 @category:"snippets"
過濾器搜尋包含程式碼片段的擴充套件。
如果你找到想要使用的擴充套件,安裝它,然後重啟 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
。佔位符的遍歷順序按數字升序,從一開始;零是一個可選的特殊情況,它總是排在最後,並在指定位置退出程式碼片段模式。
檔案模板程式碼片段
如果程式碼片段旨在填充或替換檔案內容,你可以在程式碼片段定義中新增 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
的示例轉換及其結果輸出。
示例 | 輸出 | 說明 |
---|---|---|
|
example-123_456-TEST.js |
將第一個 . 替換為 _ |
|
example_123_456_TEST_js |
將每個 . 或 - 替換為 _ |
|
EXAMPLE-123.456-TEST.JS |
全部轉換為大寫 |
|
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 程式碼片段
你也可以在 VS Code 中使用現有的 TextMate 程式碼片段 (.tmSnippets)。請參閱我們擴充套件 API 部分中的使用 TextMate 程式碼片段主題以瞭解更多資訊。
為程式碼片段分配鍵盤快捷鍵
你可以建立自定義鍵盤快捷鍵來插入特定的程式碼片段。開啟 keybindings.json
(首選項: 開啟鍵盤快捷方式檔案),它定義了你所有的鍵盤快捷鍵,然後新增一個鍵盤快捷鍵,並將 "snippet"
作為一個額外引數傳入:
{
"key": "cmd+k 1",
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"snippet": "console.log($1)$0"
}
}
該鍵盤快捷鍵將呼叫“插入程式碼片段”命令,但它不會提示你選擇程式碼片段,而是直接插入提供的程式碼片段。你可以像往常一樣定義自定義鍵盤快捷鍵,包括快捷鍵、命令 ID 以及一個可選的when 子句上下文,用於確定該快捷鍵何時啟用。
此外,除了使用 snippet
引數值來內聯定義程式碼片段外,你還可以透過使用 langId
和 name
引數來引用一個已有的程式碼片段。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 中。