Visual Studio Code 中的程式碼片段

程式碼片段是範本,能讓您更容易輸入重複的程式碼模式,例如迴圈或條件陳述式。

在 Visual Studio Code 中,程式碼片段會顯示在 IntelliSense (⌃Space (Windows, Linux Ctrl+Space)) 中,與其他建議混合,以及專用的程式碼片段選擇器 (命令選擇區中的插入程式碼片段)。也支援分頁鍵自動完成:使用 "editor.tabCompletion": "on" 啟用它,輸入程式碼片段前綴 (觸發文字),然後按下 Tab 鍵來插入程式碼片段。

程式碼片段語法遵循 TextMate 程式碼片段語法,但 'interpolated shell code' 和 \u 的使用不支援。

ajax snippet

內建程式碼片段

VS Code 針對多種語言提供內建程式碼片段,例如:JavaScript、TypeScript、Markdown 和 PHP。

builtin javascript snippet

您可以透過在命令選擇區中執行插入程式碼片段命令,來查看特定語言可用的程式碼片段,以取得目前檔案語言的程式碼片段清單。然而,請記住此清單也包含您已定義的使用者程式碼片段,以及您已安裝延伸模組所提供的任何程式碼片段。

從市集安裝程式碼片段

VS Code Marketplace 上的許多延伸模組都包含程式碼片段。您可以在延伸模組檢視 (⇧⌘X (Windows、Linux Ctrl+Shift+X)) 中,使用 @category:"snippets" 篩選器來搜尋包含程式碼片段的延伸模組。

Searching for extensions with snippets

如果您找到想要使用的延伸模組,請安裝它,然後重新啟動 VS Code,新的程式碼片段就會可用。

建立您自己的程式碼片段

您可以輕鬆地定義自己的程式碼片段,而無需任何延伸模組。若要建立或編輯自己的程式碼片段,請在 檔案 > 喜好設定 下選取設定程式碼片段,然後選取程式碼片段應出現的語言 (依據語言識別碼),或者如果它們應該出現在所有語言中,則選取新增全域程式碼片段檔案選項。VS Code 會為您管理基礎程式碼片段檔案的建立與更新。

snippet dropdown

程式碼片段檔案以 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 屬性新增到程式碼片段的定義中。當您在新檔案或現有檔案中執行程式碼片段:使用程式碼片段填滿檔案命令時,檔案範本程式碼片段會顯示在下拉式選單中。

程式碼片段範圍

程式碼片段有範圍限制,因此只會建議相關的程式碼片段。程式碼片段可以透過以下方式限制範圍:

  1. 程式碼片段所屬的語言 (可能全部)
  2. 程式碼片段所屬的專案 (可能全部)

語言程式碼片段範圍

每個程式碼片段的範圍是一個、幾個或所有 (「全域」) 語言,這取決於它是否定義在

  1. 語言程式碼片段檔案
  2. 全域程式碼片段檔案

單一語言的使用者定義程式碼片段會定義在特定語言的程式碼片段檔案中 (例如 javascript.json),您可以透過程式碼片段:設定程式碼片段依語言識別碼存取。程式碼片段僅在編輯定義它的語言時才可存取。

多語言和全域使用者定義的程式碼片段都定義在「全域」程式碼片段檔案中 (JSON 檔案,副檔名為 .code-snippets),這也可以透過程式碼片段:設定程式碼片段存取。在全域程式碼片段檔案中,程式碼片段定義可能會有額外的 scope 屬性,該屬性接受一個或多個語言識別碼,這使得程式碼片段僅對那些指定的語言可用。如果沒有給定 scope 屬性,則全域程式碼片段在所有語言中都可用。

大多數使用者定義的程式碼片段都限定在單一語言,因此定義在特定語言的程式碼片段檔案中。

專案程式碼片段範圍

您也可以擁有一個全域程式碼片段檔案 (JSON 檔案,副檔名為 .code-snippets),其範圍限定於您的專案。專案資料夾程式碼片段是透過程式碼片段:設定程式碼片段下拉式選單中的「為 '<資料夾名稱>' 建立新的程式碼片段檔案...」選項建立的,並且位於專案根目錄下的 .vscode 資料夾中。專案程式碼片段檔案有助於與該專案中所有使用者分享程式碼片段。專案資料夾程式碼片段類似於全域程式碼片段,並且可以透過 scope 屬性將其範圍限定為特定語言。

檔案模式範圍

您可以使用選用的 includeexclude 屬性來指定檔案模式,進一步控制程式碼片段的顯示時機。這些屬性適用於特定語言和全域程式碼片段檔案,並且可以與 scope 屬性結合使用,以更精確地控制程式碼片段建議。

  • include - 用於指定程式碼片段應顯示在哪些檔案中的 glob 模式或 glob 模式陣列。
  • exclude - 用於指定程式碼片段不應顯示在哪些檔案中的 glob 模式或 glob 模式陣列。

模式比對運作方式如下

  • 僅限檔名模式 (例如 *.test.ts) 根據檔名進行比對,無論檔案在您專案中的位置為何。
  • 基於路徑的模式 (例如 **/*.test.ts**/dist/**) 針對完整的檔案路徑進行比對。
  • 如果檔案同時比對到 includeexclude 模式,則 exclude 模式優先。
  • 如果未指定任何屬性,則程式碼片段會根據 scope 屬性顯示在所有適用檔案中。
範例

範例:測試程式碼片段

此程式碼片段僅出現在 TypeScript 測試檔案中

{
  "Test Block": {
    "prefix": "test",
    "body": ["test('${1:description}', () => {", "\t${0}", "});"],
    "description": "Insert a test block",
    "scope": "typescript",
    "include": ["**/*.test.ts", "**/*.spec.ts"]
  }
}

範例:排除目錄

此程式碼片段會出現在所有 JavaScript 檔案中,但 distnode_modules 目錄中的檔案除外

{
  "Console Log": {
    "prefix": "log",
    "body": "console.log(${0});",
    "description": "Insert console.log",
    "scope": "javascript",
    "exclude": ["**/dist/**", "**/node_modules/**"]
  }
}

範例:設定檔程式碼片段

此程式碼片段僅出現在 travis.yml 檔案中,使用僅限檔名模式

{
  "Travis CI Node": {
    "prefix": "travis-node",
    "body": ["language: node_js", "node_js:", "  - ${1:18}"],
    "description": "Travis CI Node.js configuration",
    "scope": "yaml",
    "include": ["travis.yml"]
  }
}

使用 includeexclude 模式有助於減少 IntelliSense 中的雜亂,只在相關時顯示程式碼片段。

程式碼片段語法

程式碼片段的 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 epoch 以來的秒數
  • 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"
  }
}

變數轉換

轉換允許您在插入變數值之前修改它。轉換的定義包含三個部分

  1. 用於比對變數值的正規表示式,或者當變數無法解析時的空字串。
  2. 一個「格式字串」,允許引用正規表示式中的比對群組。格式字串允許條件式插入和簡單修改。
  3. 傳遞給正規表示式的選項。

以下範例會插入當前文件的名稱而不帶副檔名,因此從 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 的範例轉換和結果輸出。

範例 輸出 說明
"${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-9a-z]//gi}" 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' | '/snakecase' | '/kebabcase' '}'
                | '${' 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 程式碼片段

您也可以將現有的 TextMate 程式碼片段 (.tmSnippets) 與 VS Code 搭配使用。請參閱我們的延伸模組 API 小節中的使用 TextMate 程式碼片段主題以了解更多資訊。

為程式碼片段指派鍵盤快速鍵

您可以建立自訂的鍵盤快速鍵來插入特定的程式碼片段。開啟 keybindings.json (喜好設定:開啟鍵盤快速鍵檔案),它定義了您的所有鍵盤快速鍵,並新增一個將 "snippet" 作為額外引數傳遞的鍵盤快速鍵

{
  "key": "cmd+k 1",
  "command": "editor.action.insertSnippet",
  "when": "editorTextFocus",
  "args": {
    "snippet": "console.log($1)$0"
  }
}

此鍵盤快速鍵將會叫用插入程式碼片段命令,但它不會提示您選取程式碼片段,而是會插入所提供的程式碼片段。您像往常一樣定義自訂的按鍵繫結,包括鍵盤快速鍵、命令 ID 和選用的when 子句內容,用於啟用鍵盤快速鍵的時機。

此外,您可以不使用 snippet 引數值來行內定義您的程式碼片段,而是使用 langIdname 引數來參考現有的程式碼片段。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 (完成清單) 中。

Hide from IntelliSense button in Insert Snippet dropdown

您仍然可以使用插入程式碼片段命令選取程式碼片段,但隱藏的程式碼片段將不會顯示在 IntelliSense 中。

© . This site is unofficial and not affiliated with Microsoft.