透過工作整合外部工具

有許多工具可用來自動化軟體系統的任務,例如程式碼檢查 (linting)、建置 (building)、打包 (packaging)、測試 (testing) 或部署 (deploying)。範例包括 TypeScript 編譯器、像 ESLintTSLint 這樣的程式碼檢查工具,以及像 MakeAntGulpJakeRakeMSBuild 這樣的建置系統。

VS Code can talk to a variety of external tools

這些工具大多從命令列執行,並自動化內部與外部軟體開發循環 (編輯、編譯、測試和偵錯) 的工作。鑑於它們在開發生命週期中的重要性,能夠在 VS Code 中執行工具並分析其結果會很有幫助。VS Code 中的工作可以設定為執行腳本並啟動程序,這樣許多現有工具都可以在 VS Code 中使用,而無需輸入命令列或撰寫新程式碼。工作區或資料夾專屬的工作是在工作區的 .vscode 資料夾中的 tasks.json 檔案中設定的。

擴充功能也可以使用 工作提供者 (Task Provider) 來貢獻工作,這些貢獻的工作可以新增在 tasks.json 檔案中定義的工作區專屬設定。

注意:工作支援僅在處理工作區資料夾時可用。編輯單一檔案時則不可用。

TypeScript Hello World

讓我們從一個簡單的「Hello World」TypeScript 程式開始,我們想將其編譯為 JavaScript。

建立一個空的資料夾「mytask」,產生一個 tsconfig.json 檔案,然後從該資料夾啟動 VS Code。

mkdir mytask
cd mytask
tsc --init
code .

現在建立一個包含以下內容的 HelloWorld.ts 檔案

function sayHello(name: string): void {
  console.log(`Hello ${name}!`);
}

sayHello('Dave');

按下 ⇧⌘B (Windows、Linux Ctrl+Shift+B) 或從全域 終端機 (Terminal) 功能表執行 執行建置工作 (Run Build Task) 會顯示以下選取器

TypeScript Build Task

第一個項目會執行 TypeScript 編譯器並將 TypeScript 檔案轉譯為 JavaScript 檔案。當編譯器完成後,應該會有一個 HelloWorld.js 檔案。第二個項目會以監看模式啟動 TypeScript 編譯器。每次儲存 HelloWorld.ts 檔案都會重新產生 HelloWorld.js 檔案。

您也可以將 TypeScript 建置或監看工作定義為預設建置工作,這樣當觸發 執行建置工作 (Run Build Task) (⇧⌘B (Windows、Linux Ctrl+Shift+B)) 時,它會直接執行。為此,請從全域 終端機 (Terminal) 功能表選擇 設定預設建置工作 (Configure Default Build Task)。這會顯示一個包含可用建置工作的選取器。選擇 tsc: buildtsc: watch,VS Code 將會產生一個 tasks.json 檔案。下面顯示的檔案將 tsc: build 工作設為預設建置工作

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "type": "typescript",
      "tsconfig": "tsconfig.json",
      "problemMatcher": ["$tsc"],
      "group": {
        "kind": "build",
        "isDefault": true
      }
    }
  ]
}

上述的 tasks.json 範例並未定義新工作。它只是將 VS Code 的 TypeScript 擴充功能所貢獻的 tsc: build 工作註記為預設建置工作。您現在可以按下 ⇧⌘B (Windows、Linux Ctrl+Shift+B) 來執行 TypeScript 編譯器。

工作自動偵測

VS Code 目前會自動偵測以下系統的工作:Gulp、Grunt、Jake 和 npm。我們正在與相關的擴充功能作者合作,以新增對 Maven 和 C# dotnet 命令的支援。如果您使用 Node.js 作為執行階段來開發 JavaScript 應用程式,通常會有一個 package.json 檔案來描述您的依賴項和要執行的腳本。如果您已複製 eslint-starter 範例,那麼從全域功能表執行 執行工作 (Run Tasks) 會顯示以下清單

Tasks ESLint starter

如果您尚未執行,請執行 npm install 以安裝必要的 npm 模組。現在開啟 server.js 檔案並在語句末尾新增一個分號 (請注意 ESLint 啟動器假設語句沒有分號),然後再次執行 執行工作 (Run Tasks)。這次選擇 npm: lint 工作。當系統提示要使用的問題比對器時,請選擇 ESLint stylish

Tasks ESLint Problem Matcher Selection

執行此工作會產生一個錯誤,顯示在 問題 (Problems) 檢視中

Tasks ESLint Problem

此外,VS Code 建立了包含以下內容的 tasks.json 檔案

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "type": "npm",
      "script": "lint",
      "problemMatcher": ["$eslint-stylish"]
    }
  ]
}

這指示 VS Code 使用 ESLint stylish 格式掃描 npm lint 腳本的輸出以尋找問題。

對於 Gulp、Grunt 和 Jake,工作自動偵測的工作方式相同。以下是為 vscode-node-debug 擴充功能偵測到的工作範例。

Gulp task auto-detection

提示:您可以透過 快速開啟 (Quick Open) (⌘P (Windows、Linux Ctrl+P)) 執行您的工作,方法是輸入「task」、空白鍵 和命令名稱。在本例中為「task lint」。

可以使用以下設定停用工作自動偵測

{
  "js/ts.tsc.autoDetect": "off",
  "grunt.autoDetect": "off",
  "jake.autoDetect": "off",
  "gulp.autoDetect": "off",
  "npm.autoDetect": "off"
}

自訂工作

並非所有工作或腳本都可以在您的工作區中自動偵測。有時有必要定義您自己的自訂工作。假設您有一個腳本來執行您的測試以正確設定一些環境。該腳本儲存在您工作區內的腳本資料夾中,在 Linux 和 macOS 上命名為 test.sh,在 Windows 上命名為 test.cmd。從全域 終端機 (Terminal) 功能表執行 設定工作 (Configure Tasks) 並選擇 從範本建立 tasks.json 檔案 (Create tasks.json file from template) 項目。這會開啟以下選取器

Configure Task Runner

注意:如果您沒有看到工作執行器範本清單,您的資料夾中可能已經有一個 tasks.json 檔案,其內容將在編輯器中開啟。請關閉該檔案,並為了此範例刪除或重新命名它。

我們正在努力提供更多自動偵測支援,因此這個清單將來會越來越短。由於我們要編寫自己的自訂工作,請從清單中選擇 其他 (Others)。這會開啟帶有工作骨架的 tasks.json 檔案。將內容替換為以下內容

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Run tests",
      "type": "shell",
      "command": "./scripts/test.sh",
      "windows": {
        "command": ".\\scripts\\test.cmd"
      },
      "group": "test",
      "presentation": {
        "reveal": "always",
        "panel": "new"
      }
    }
  ]
}

工作屬性具有以下語義

  • label:在使用者介面中使用的工作標籤。
  • type:工作的類型。對於自訂工作,這可以是 shellprocess。如果指定 shell,命令會被解釋為一個 shell 命令 (例如:bash、cmd 或 PowerShell)。如果指定 process,命令會被解釋為一個要執行的程序。
  • command:要執行的實際命令。
  • windows:任何 Windows 專屬屬性。當命令在 Windows 作業系統上執行時,將使用這些屬性而非預設屬性。
  • group:定義工作所屬的群組。在本範例中,它屬於 test 群組。屬於測試群組的工作可以透過從 命令選擇區 (Command Palette) 執行 執行測試工作 (Run Test Task) 來執行。
  • presentation:定義使用者介面中如何處理工作輸出。在此範例中,顯示輸出的整合終端機 (Integrated Terminal) 會 總是 (always) 顯示,並且每次執行工作時都會建立一個 新 (new) 終端機。
  • options:覆寫 cwd (目前工作目錄)、env (環境變數) 或 shell (預設 shell) 的預設值。選項可以按工作設定,也可以全域或按平台設定。此處設定的環境變數只能從您的工作腳本或程序中引用,如果它們是您的參數、命令或其他工作屬性的一部分,則不會被解析。
  • runOptions:定義工作執行時機和方式。
  • hide:從「執行工作快速選取 (Run Task Quick Pick)」中隱藏工作,這對於複合工作中無法獨立執行的元素很有用。

您可以在 tasks.json 檔案中使用 IntelliSense 查看完整的任務屬性和值。透過 觸發建議 (Trigger Suggest) (⌃Space (Windows、Linux Ctrl+Space)) 顯示建議,並在懸停時或使用 閱讀更多... (Read More...) ('i') 彈出視窗閱讀說明。

tasks.json IntelliSense

您也可以檢閱 tasks.json 結構描述

Shell 命令在處理包含空格或其他特殊字元 (如 $) 的命令和引數時需要特殊處理。預設情況下,工作系統支援以下行為

  • 如果提供單一命令,工作系統會將命令原封不動地傳遞給底層 shell。如果命令需要引號或逸出才能正常運作,命令需要包含適當的引號或逸出字元。例如,要列出名稱中包含空格的資料夾的目錄,在 bash 中執行的命令應如下所示:ls 'folder with spaces'
{
  "label": "dir",
  "type": "shell",
  "command": "dir 'folder with spaces'"
}
  • 如果提供命令和引數,如果命令或引數包含空格,工作系統將使用單引號。對於 cmd.exe,則使用雙引號。以下所示的 shell 命令將在 PowerShell 中執行為 dir 'folder with spaces'
{
  "label": "dir",
  "type": "shell",
  "command": "dir",
  "args": ["folder with spaces"]
}
  • 如果您想控制引數的引號方式,引數可以是一個指定值和引號樣式的字面值。以下範例使用逸出而非引號來處理包含空格的引數。
{
  "label": "dir",
  "type": "shell",
  "command": "dir",
  "args": [
    {
      "value": "folder with spaces",
      "quoting": "escape"
    }
  ]
}

除了逸出,還支援以下值

  • strong (強式):使用 shell 的強式引號機制,它會抑制字串內的所有評估。在 PowerShell 以及 Linux 和 macOS 的 shell 中,使用單引號 (')。對於 cmd.exe,則使用 "
  • weak (弱式):使用 shell 的弱式引號機制,它仍然會評估字串內的表達式 (例如,環境變數)。在 PowerShell 以及 Linux 和 macOS 的 shell 中,使用雙引號 (")。cmd.exe 不支援弱式引號,因此 VS Code 也使用 "

如果命令本身包含空格,VS Code 預設也會對命令使用強式引號。與引數一樣,使用者可以使用相同的字面值樣式來控制命令的引號方式。

還有更多工作屬性可供您設定工作流程。您可以使用 IntelliSense 並搭配 ⌃Space (Windows、Linux Ctrl+Space) 來概覽有效的屬性。

Tasks IntelliSense

除了全域功能表列之外,還可以透過 命令選擇區 (Command Palette) (⇧⌘P (Windows、Linux Ctrl+Shift+P)) 存取工作命令。您可以篩選「task」並查看各種與工作相關的命令。

Tasks in Command Palette

複合工作

您也可以使用 dependsOn 屬性將簡單的工作組合成複合工作。例如,如果您的工作區有一個用戶端和伺服器資料夾,並且兩者都包含建置腳本,您可以建立一個任務,在不同的終端機中啟動這兩個建置腳本。如果 dependsOn 屬性中列出多個工作,它們預設會並行執行。

tasks.json 檔案如下所示

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Client Build",
      "command": "gulp",
      "args": ["build"],
      "options": {
        "cwd": "${workspaceFolder}/client"
      }
    },
    {
      "label": "Server Build",
      "command": "gulp",
      "args": ["build"],
      "options": {
        "cwd": "${workspaceFolder}/server"
      }
    },
    {
      "label": "Build",
      "dependsOn": ["Client Build", "Server Build"]
    }
  ]
}

如果您指定 "dependsOrder": "sequence",那麼您的工作依賴項將按照它們在 dependsOn 中列出的順序執行。任何在 dependsOn 中與 "dependsOrder": "sequence" 一起使用的背景/監看工作都必須有一個問題比對器,用於追蹤它們何時「完成」。以下工作會執行工作二、工作三,然後執行工作一。

{
  "label": "One",
  "type": "shell",
  "command": "echo Hello ",
  "dependsOrder": "sequence",
  "dependsOn": ["Two", "Three"]
}

使用者層級工作

您可以使用 工作:開啟使用者工作 (Tasks: Open User Tasks) 命令建立不與特定工作區或資料夾綁定的使用者層級工作。這裡只能使用 shellprocess 工作,因為其他工作類型需要工作區資訊。

輸出行為

有時您會想控制整合終端機 (Integrated Terminal) 面板在執行工作時的行為。例如,您可能想最大化編輯器空間,只在認為有問題時才查看工作輸出。終端機的行為可以使用工作的 presentation 屬性來控制。它提供以下屬性

  • reveal (顯示):控制整合終端機 (Integrated Terminal) 面板是否帶到最前面。有效值為
    • always - 面板總是帶到最前面。這是預設值。
    • never - 使用者必須使用 檢視 (View) > 終端機 (Terminal) 命令 (⌃` (Windows、Linux Ctrl+`)) 明確地將終端機面板帶到最前面。
    • silent - 終端機面板僅在輸出未掃描到錯誤和警告時才會帶到最前面。
  • revealProblems (顯示問題):控制執行此工作時是否顯示「問題 (Problems)」面板。優先於 reveal 選項。預設為 never
    • always - 執行此工作時,總是顯示「問題 (Problems)」面板。
    • onProblem - 僅在發現問題時才顯示「問題 (Problems)」面板。
    • never - 執行此工作時,絕不顯示「問題 (Problems)」面板。
  • focus (焦點):控制終端機是否取得輸入焦點。預設為 false
  • echo (回聲):控制執行命令是否在終端機中回顯。預設為 true
  • showReuseMessage (顯示重複使用訊息):控制是否顯示「終端機將被工作重複使用,按任意鍵關閉它」的訊息。
  • panel (面板):控制終端機實例是否在不同工作執行之間共用。可能的值為
    • shared - 終端機被共用,其他工作執行的輸出會新增到同一個終端機。
    • dedicated - 終端機專用於特定工作。如果該工作再次執行,終端機將被重複使用。然而,不同工作的輸出將顯示在不同的終端機中。
    • new - 該工作的每次執行都使用一個全新的終端機。
  • clear (清除):控制在執行此工作之前是否清除終端機。預設為 false
  • close (關閉):控制工作結束時,執行該工作的終端機是否關閉。預設為 false
  • group (群組):控制工作是否在特定終端機群組中使用分割窗格執行。相同群組 (由字串值指定) 中的工作將使用分割終端機來呈現,而不是新的終端機面板。

您也可以修改自動偵測到的工作的終端機面板行為。例如,如果您想變更上面 ESLint 範例中 npm: run lint 的輸出行為,請為其新增 presentation 屬性

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "type": "npm",
      "script": "lint",
      "problemMatcher": ["$eslint-stylish"],
      "presentation": {
        "reveal": "never"
      }
    }
  ]
}

您也可以將自訂工作與偵測到的工作設定混合使用。一個設定 npm: run lint 工作並新增自訂 執行測試 (Run Test) 工作的 tasks.json 檔案如下所示

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "type": "npm",
      "script": "lint",
      "problemMatcher": ["$eslint-stylish"],
      "presentation": {
        "reveal": "never"
      }
    },
    {
      "label": "Run tests",
      "type": "shell",
      "command": "./scripts/test.sh",
      "windows": {
        "command": ".\\scripts\\test.cmd"
      },
      "group": "test",
      "presentation": {
        "reveal": "always",
        "panel": "new"
      }
    }
  ]
}

執行行為

您可以使用 runOptions 屬性指定工作的執行行為

  • reevaluateOnRerun (重新執行時重新評估):控制透過 重新執行上次工作 (Rerun Last Task) 命令執行工作時變數的評估方式。預設為 true,表示工作重新執行時會重新評估變數。當設定為 false 時,將使用上次工作執行中已解析的變數值。
  • runOn (執行時機):指定工作何時執行。
    • default - 只有透過 執行工作 (Run Task) 命令執行時才會執行此工作。
    • folderOpen - 當包含此工作的資料夾開啟時,該工作將會執行。當您第一次開啟一個包含 folderOpen 工作的資料夾時,系統會詢問您是否允許該資料夾中的工作自動執行。您可以稍後使用 管理自動工作 (Manage Automatic Tasks) 命令,並在 允許自動工作 (Allow Automatic Tasks)不允許自動工作 (Disallow Automatic Tasks) 之間進行選擇來更改您的決定。
  • instanceLimit (實例限制) - 允許同時執行的工作實例數量。預設值為 1
  • instancePolicy (實例策略) - 決定當工作達到其 instanceLimit 時會發生什麼。可以設定為
    • prompt - 提示使用者終止哪個實例 (預設值)。
    • silent - 不啟動新實例 (靜默)。
    • terminateNewest - 終止最新執行的實例。
    • terminateOldest - 終止最舊執行的實例。
    • warn - 不啟動新實例 (顯示警告)。

自訂自動偵測到的工作

如前所述,您可以在 tasks.json 檔案中自訂自動偵測到的工作。您通常會這樣做來修改呈現屬性,或附加一個問題比對器以掃描工作的輸出以查找錯誤和警告。您可以直接從 執行工作 (Run Task) 清單中按右側的齒輪圖示來自訂工作,將相應的工作引用插入到 tasks.json 檔案中。假設您有以下 Gulp 檔案使用 ESLint 來檢查 JavaScript 檔案 (此檔案取自 https://github.com/adametry/gulp-eslint)

const gulp = require('gulp');
const eslint = require('gulp-eslint');

gulp.task('lint', () => {
  // ESLint ignores files with "node_modules" paths.
  // So, it's best to have gulp ignore the directory as well.
  // Also, Be sure to return the stream from the task;
  // Otherwise, the task may end before the stream has finished.
  return (
    gulp
      .src(['**/*.js', '!node_modules/**'])
      // eslint() attaches the lint output to the "eslint" property
      // of the file object so it can be used by other modules.
      .pipe(eslint())
      // eslint.format() outputs the lint results to the console.
      // Alternatively use eslint.formatEach() (see Docs).
      .pipe(eslint.format())
      // To have the process exit with an error code (1) on
      // lint error, return the stream and pipe to failAfterError last.
      .pipe(eslint.failAfterError())
  );
});

gulp.task('default', ['lint'], function() {
  // This will only run if the lint task is successful...
});

從全域 終端機 (Terminal) 功能表執行 執行工作 (Run Task) 將顯示以下選取器

Configure Task

按下齒輪圖示。這將建立以下 tasks.json 檔案

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "type": "gulp",
      "task": "default",
      "problemMatcher": []
    }
  ]
}

通常您現在會新增一個問題比對器 (在本例中為 $eslint-stylish) 或修改呈現設定。

使用問題比對器處理工作輸出

VS Code 可以使用問題比對器處理工作輸出。問題比對器會掃描工作輸出文字以查找已知的警告或錯誤字串,並在編輯器中和「問題 (Problems)」面板中行內報告這些問題。VS Code 內建了多個問題比對器

  • TypeScript$tsc 假設輸出中的檔案名稱是相對於已開啟的資料夾。
  • TypeScript 監看 (TypeScript Watch)$tsc-watch 比對在監看模式下執行 tsc 編譯器時報告的問題。
  • JSHint$jshint 假設檔案名稱以絕對路徑報告。
  • JSHint Stylish$jshint-stylish 假設檔案名稱以絕對路徑報告。
  • ESLint 精簡 (ESLint Compact)$eslint-compact 假設輸出中的檔案名稱是相對於已開啟的資料夾。
  • ESLint Stylish$eslint-stylish 假設輸出中的檔案名稱是相對於已開啟的資料夾。
  • Go$go 比對 go 編譯器報告的問題。假設檔案名稱是相對於已開啟的資料夾。
  • C# 和 VB 編譯器 (CSharp and VB Compiler)$mscompile 假設檔案名稱以絕對路徑報告。
  • Lessc 編譯器 (Lessc compiler)$lessc 假設檔案名稱以絕對路徑報告。
  • Node Sass 編譯器 (Node Sass compiler)$node-sass 假設檔案名稱以絕對路徑報告。

您也可以建立自己的問題比對器,我們將在稍後的章節中討論。

將鍵盤快捷鍵繫結至工作

如果您需要頻繁執行某個工作,可以為該工作定義一個鍵盤快捷鍵。

例如,要將 Ctrl+H 繫結到上面提到的 執行測試 (Run tests) 工作,請將以下內容新增到您的 keybindings.json 檔案中

{
  "key": "ctrl+h",
  "command": "workbench.action.tasks.runTask",
  "args": "Run tests"
}

變數替換

在撰寫工作設定時,擁有一組預定義的常用變數會很有用,例如作用中檔案 (${file}) 或工作區根資料夾 (${workspaceFolder})。VS Code 支援在 tasks.json 檔案的字串內進行變數替換,您可以在 變數參考 中查看預定義變數的完整清單。

注意:並非所有屬性都接受變數替換。具體而言,只有 commandargsoptions 支援變數替換。

以下是一個自訂工作設定的範例,它會將目前開啟的檔案傳遞給 TypeScript 編譯器。

{
  "label": "TypeScript compile",
  "type": "shell",
  "command": "tsc ${file}",
  "problemMatcher": ["$tsc"]
}

同樣地,您可以透過在名稱前加上 ${config: 來引用專案的設定。例如,${config:python.formatting.autopep8Path} 會回傳 Python 擴充功能設定 formatting.autopep8Path

以下是一個自訂工作設定的範例,它使用由 python.formatting.autopep8Path 設定定義的 autopep8 可執行檔對目前檔案執行 autopep8

{
  "label": "autopep8 current file",
  "type": "process",
  "command": "${config:python.formatting.autopep8Path}",
  "args": ["--in-place", "${file}"]
}

如果您想指定 Python 擴充功能用於 tasks.jsonlaunch.json 的選定 Python 直譯器,您可以使用 ${command:python.interpreterPath} 命令。

如果簡單的變數替換不足以滿足需求,您還可以透過在 tasks.json 檔案中新增 inputs 區段來從工作使用者獲取輸入。

Inputs Example

有關 inputs 的更多資訊,請參閱 變數參考

作業系統專屬屬性

工作系統支援定義特定於作業系統的值 (例如,要執行的命令)。為此,請將作業系統專屬的字面值放入 tasks.json 檔案中,並在該字面值內指定相應的屬性。

以下是一個範例,它使用 Node.js 可執行檔作為命令,在 Windows 和 Linux 上有不同的處理方式

{
  "label": "Run Node",
  "type": "process",
  "windows": {
    "command": "C:\\Program Files\\nodejs\\node.exe"
  },
  "linux": {
    "command": "/usr/bin/node"
  }
}

有效的作業系統屬性為 Windows 的 windows、Linux 的 linux 和 macOS 的 osx。在作業系統特定範圍中定義的屬性會覆寫在工作或全域範圍中定義的屬性。

全域工作

工作屬性也可以在全域範圍中定義。如果存在,它們將用於特定工作,除非這些工作以不同的值定義相同的屬性。在下面的範例中,有一個全域 presentation 屬性,它定義所有工作都應在新面板中執行

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "presentation": {
    "panel": "new"
  },
  "tasks": [
    {
      "label": "TS - Compile current file",
      "type": "shell",
      "command": "tsc ${file}",
      "problemMatcher": ["$tsc"]
    }
  ]
}

提示:要存取全域範圍的 tasks.json 檔案,請開啟命令選擇區 (⇧⌘P (Windows、Linux Ctrl+Shift+P)) 並執行 工作:開啟使用者工作 (Tasks: Open User Tasks) 命令。

PowerShell 中的字元逸出

當預設 shell 為 PowerShell,或當工作設定為使用 PowerShell 時,您可能會看到意外的空格和引號逸出。意外的逸出只會在使用 cmdlet 時發生,因為 VS Code 不知道您的命令是否包含 cmdlet。下面的範例 1 顯示了一個在 PowerShell 中無法使用的逸出情況。範例 2 顯示了獲得良好逸出的最佳跨平台方法。在某些情況下,您可能無法遵循範例 2,您將需要進行範例 3 中顯示的手動逸出。

"tasks": [
    {
        "label": "PowerShell example 1 (unexpected escaping)",
        "type": "shell",
        "command": "Get-ChildItem \"Folder With Spaces\""
    },
    {
        "label": "PowerShell example 2 (expected escaping)",
        "type": "shell",
        "command": "Get-ChildItem",
        "args": ["Folder With Spaces"]
    },
    {
        "label": "PowerShell example 3 (manual escaping)",
        "type": "shell",
        "command": "& Get-ChildItem \\\"Folder With Spaces\\\""
    }
]

變更工作輸出的編碼

工作經常處理磁碟上的檔案。如果這些檔案在磁碟上儲存的編碼與系統編碼不同,您需要讓作為工作執行的命令知道要使用哪種編碼。由於這取決於作業系統和使用的 shell,因此沒有通用的解決方案來控制這一點。以下是關於如何使其運作的建議和範例。

如果您需要調整編碼,您應該檢查變更作業系統使用的預設編碼,或至少透過調整 shell 的設定檔來變更您使用的 shell 的編碼,這是否有意義。

如果您只需要為特定工作調整編碼,則將更改編碼所需的作業系統特定命令新增到工作的命令列中。以下範例適用於 Windows,其預設使用字碼頁 437。此工作顯示包含西里爾字母的檔案輸出,因此需要字碼頁 866。假設預設 shell 設定為 cmd.exe,列出檔案的工作如下所示

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "label": "more",
      "type": "shell",
      "command": "chcp 866 && more russian.txt",
      "problemMatcher": []
    }
  ]
}

如果工作在 PowerShell 中執行,命令需要讀取為 chcp 866; more russian.txt。在 Linux 和 macOS 上,可以使用 locale 命令來檢查 locale 並調整必要的環境變數。

工作實例

為了突顯工作的強大功能,以下是一些 VS Code 如何使用工作來整合外部工具 (如程式碼檢查工具和編譯器) 的範例。

將 TypeScript 轉譯為 JavaScript

TypeScript 主題 包含一個範例,說明如何建立一個工作來將 TypeScript 轉譯為 JavaScript,並在 VS Code 內部觀察任何相關錯誤。

將 Less 和 SCSS 轉譯為 CSS

CSS 主題提供了如何使用工作來產生 CSS 檔案的範例。

  1. 使用建置工作手動轉譯
  2. 使用檔案監看器自動化編譯步驟

定義問題比對器

VS Code 內建了一些最常見的問題比對器。然而,市面上有許多編譯器和程式碼檢查工具,它們都產生自己風格的錯誤和警告,因此您可能需要建立自己的問題比對器。

我們有一個 helloWorld.c 程式,開發人員將 printf 誤打為 prinft。使用 gcc 編譯它將產生以下警告

helloWorld.c:5:3: warning: implicit declaration of function ‘prinft’

我們希望產生一個問題比對器,它可以捕捉輸出中的訊息並在 VS Code 中顯示相應的問題。問題比對器大量依賴於正規表達式。以下章節假設您熟悉正規表達式。

提示:我們發現 RegEx101 playground (具有 ECMAScript (JavaScript) 風格) 是開發和測試正規表達式的好方法。

一個捕捉上述警告 (和錯誤) 的比對器看起來像這樣

{
  // The problem is owned by the cpp language service.
  "owner": "cpp",
  // The file name for reported problems is relative to the opened folder.
  "fileLocation": ["relative", "${workspaceFolder}"],
  // The name that will be shown as the source of the problem.
  "source": "gcc",
  // The actual pattern to match problems in the output.
  "pattern": {
    // The regular expression. Example to match: helloWorld.c:5:3: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
    "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
    // The first match group matches the file name which is relative.
    "file": 1,
    // The second match group matches the line on which the problem occurred.
    "line": 2,
    // The third match group matches the column at which the problem occurred.
    "column": 3,
    // The fourth match group matches the problem's severity. Can be ignored. Then all problems are captured as errors.
    "severity": 4,
    // The fifth match group matches the message.
    "message": 5
  }
}

請注意,檔案、行和訊息屬性是強制性的。fileLocation 指定任務輸出產生並在問題中匹配的檔案路徑是 絕對 (absolute) 還是 相對 (relative)。如果任務產生絕對和相對路徑,您可以使用 autoDetect (自動偵測) 檔案位置。使用 autoDetect,路徑首先被測試為絕對路徑,如果檔案不存在,則假定該路徑是相對路徑。

severity 指定如果模式不包含嚴重性,則使用的問題嚴重性。severity 的可能值為 error (錯誤)warning (警告)info (資訊)

這是一個完成的 tasks.json 檔案,其中包含上述程式碼 (已移除註解) 並包裝實際的工作詳細資訊

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "build",
      "command": "gcc",
      "args": ["-Wall", "helloWorld.c", "-o", "helloWorld"],
      "problemMatcher": {
        "owner": "cpp",
        "fileLocation": ["relative", "${workspaceFolder}"],
        "source": "gcc",
        "pattern": {
          "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
          "file": 1,
          "line": 2,
          "column": 3,
          "severity": 4,
          "message": 5
        }
      }
    }
  ]
}

在 VS Code 中執行它並按下 ⇧⌘M (Windows、Linux Ctrl+Shift+M) 以取得問題清單,您將得到以下輸出

GCC Problem Matcher

注意:C/C++ 擴充功能 包含了 GCC 的問題比對器,因此無需自行定義。

還有一些屬性可以在模式中使用。它們是

  • location (位置) - 如果問題位置是 line 或 line,column 或 startLine,startColumn,endLine,endColumn,則可以使用我們的通用位置比對群組。
  • endLine (結束行) - 問題結束行的比對群組索引。如果編譯器未提供結束行值,則可以省略。
  • endColumn (結束欄) - 問題結束欄的比對群組索引。如果編譯器未提供結束欄值,則可以省略。
  • code (程式碼) - 問題程式碼的比對群組索引。如果編譯器未提供程式碼值,則可以省略。

您還可以定義一個只捕捉檔案的問題比對器。為此,請定義一個 pattern,並將可選的 kind 屬性設定為 file。在這種情況下,無需提供 linelocation 屬性。

注意:如果 kind 屬性設定為 file,功能模式必須至少提供 filemessage 的比對群組。如果未提供 kind 屬性,或 kind 屬性設定為 location,則功能模式也必須提供 linelocation 屬性。

注意:問題比對器只解析來自指定命令的輸出。如果您想解析寫入獨立檔案 (例如日誌檔) 的輸出,請讓您執行的命令在執行完成前印出獨立檔案中的行。

定義多行問題比對器

有些工具會將源檔案中發現的問題分散到多行,特別是使用 stylish 報告器時。例如 ESLint;在 stylish 模式下,它會產生如下輸出

test.js
  1:0   error  Missing "use strict" statement                 strict
 1 problems (1 errors, 0 warnings)

我們的問題比對器是基於行的,因此我們需要使用與實際問題位置和訊息 (1:0 error Missing "use strict" statement) 不同的正規表達式來捕捉檔案名稱 (test.js)。

為此,請為 pattern 屬性使用一個問題模式陣列。這樣您就可以為您要比對的每一行定義一個模式。

注意:在多行問題比對器中,輸出中的每一行都必須按模式陣列的順序進行比對。中間行不能跳過,即使它們不需要用於捕捉值。

以下問題模式比對 ESLint 在 stylish 模式下的輸出 - 但仍然有一個小問題我們需要接下來解決。下面的程式碼有一個用於捕捉檔案名稱的第一個正規表達式,以及一個用於捕捉行、列、嚴重性、訊息和錯誤程式碼的第二個正規表達式

{
  "owner": "javascript",
  "fileLocation": ["relative", "${workspaceFolder}"],
  "pattern": [
    {
      "regexp": "^([^\\s].*)$",
      "file": 1
    },
    {
      "regexp": "^\\s+(\\d+):(\\d+)\\s+(error|warning|info)\\s+(.*)\\s\\s+(.*)$",
      "line": 1,
      "column": 2,
      "severity": 3,
      "message": 4,
      "code": 5
    }
  ]
}

然而,如果資源上有多個問題,此模式將無法運作。例如,想像一下 ESLint 的以下輸出

test.js
  1:0   error  Missing "use strict" statement                 strict
  1:9   error  foo is defined but never used                  no-unused-vars
  2:5   error  x is defined but never used                    no-unused-vars
  2:11  error  Missing semicolon                              semi
  3:1   error  "bar" is not defined                           no-undef
  4:1   error  Newline required at end of file but not found  eol-last
 6 problems (6 errors, 0 warnings)

模式的第一個正規表達式將比對「test.js」,第二個比對「1:0 error ...」。下一行「1:9 error ...」被處理,但沒有被第一個正規表達式比對到,因此沒有捕捉到問題。

為了使其運作,多行模式的最後一個正規表達式可以指定 loop 屬性。如果設定為 true,它會指示工作系統將多行比對器的最後一個模式應用到輸出中的行,只要正規表達式匹配即可。

第一個模式捕捉到的資訊 (在本例中比對 test.js) 將與每個後續比對 loop 模式的行結合,以建立多個問題。在此範例中,將會建立六個問題。

這是一個問題比對器,可以完整捕捉 ESLint stylish 模式的問題

{
  "owner": "javascript",
  "fileLocation": ["relative", "${workspaceFolder}"],
  "pattern": [
    {
      "regexp": "^([^\\s].*)$",
      "file": 1
    },
    {
      "regexp": "^\\s+(\\d+):(\\d+)\\s+(error|warning|info)\\s+(.*)\\s\\s+(.*)$",
      "line": 1,
      "column": 2,
      "severity": 3,
      "message": 4,
      "code": 5,
      "loop": true
    }
  ]
}

注意:如果同一個資源上發生多個具有完全相同行和欄的問題,則只會顯示一個問題。這適用於所有問題比對器,而不僅限於多行問題比對器。

修改現有問題比對器

如果現有的問題比對器接近您的需求,您可以在 tasks.json 工作中修改它。例如,$tsc-watch 問題比對器僅適用於已關閉的文件。如果您希望它適用於所有文件,您可以修改它

{
  "type": "npm",
  "script": "watch",
  "problemMatcher": {
    "base": "$tsc-watch",
    "applyTo": "allDocuments"
  },
  "isBackground": true
}

其他可修改的問題比對器屬性包括 backgroundfileLocationownerpatternseveritysource

背景 / 監看工作

有些工具支援在背景執行,同時監看檔案系統的變化,然後在磁碟上的檔案變更時觸發動作。對於 Gulp,此功能透過 npm 模組 gulp-watch 提供。TypeScript 編譯器 tsc 透過 --watch 命令列選項內建了對此的支援。

為了提供背景工作在 VS Code 中活動並產生問題結果的回饋,問題比對器必須使用額外資訊來偵測輸出中的這些 state 變化。讓我們以 tsc 編譯器為例。當編譯器以監看模式啟動時,它會向控制台印出以下額外資訊

> tsc --watch
12:30:36 PM - Compilation complete. Watching for file changes.

當磁碟上包含問題的檔案發生變更時,會出現以下輸出

12:32:35 PM - File change detected. Starting incremental compilation...
src/messages.ts(276,9): error TS2304: Cannot find name 'candidate'.
12:32:35 PM - Compilation complete. Watching for file changes.

查看輸出顯示以下模式

  • File change detected. Starting incremental compilation... 印到控制台時,編譯器會執行。
  • Compilation complete. Watching for file changes. 印到控制台時,編譯器會停止。
  • 在這兩個字串之間報告問題。
  • 編譯器也會在初始啟動時執行一次 (不將 File change detected. Starting incremental compilation... 印到控制台)。

為了捕捉此資訊,問題比對器可以提供一個 background 屬性。

對於 tsc 編譯器,一個適當的 background 屬性看起來像這樣

"background": {
    "activeOnStart": true,
    "beginsPattern": "^\\s*\\d{1,2}:\\d{1,2}:\\d{1,2}(?: AM| PM)? - File change detected\\. Starting incremental compilation\\.\\.\\.",
    "endsPattern": "^\\s*\\d{1,2}:\\d{1,2}:\\d{1,2}(?: AM| PM)? - Compilation complete\\. Watching for file changes\\."
}

除了問題比對器上的 background 屬性之外,工作本身也必須標記為 isBackground,以便工作在背景持續執行。

一個完整的手工編寫的 tasks.json,用於以監看模式執行的 tsc 工作,看起來像這樣

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "watch",
      "command": "tsc",
      "args": ["--watch"],
      "isBackground": true,
      "problemMatcher": {
        "owner": "typescript",
        "fileLocation": "relative",
        "pattern": {
          "regexp": "^([^\\s].*)\\((\\d+|\\d+,\\d+|\\d+,\\d+,\\d+,\\d+)\\):\\s+(error|warning|info)\\s+(TS\\d+)\\s*:\\s*(.*)$",
          "file": 1,
          "location": 2,
          "severity": 3,
          "code": 4,
          "message": 5
        },
        "background": {
          "activeOnStart": true,
          "beginsPattern": "^\\s*\\d{1,2}:\\d{1,2}:\\d{1,2}(?: AM| PM)? - File change detected\\. Starting incremental compilation\\.\\.\\.",
          "endsPattern": "^\\s*\\d{1,2}:\\d{1,2}:\\d{1,2}(?: AM| PM)? - Compilation complete\\. Watching for file changes\\."
        }
      }
    }
  ]
}

後續步驟

以上是關於工作的部分 - 讓我們繼續...

  • tasks.json 結構描述 - 您可以檢閱完整的 tasks.json 結構描述和說明。
  • 基本編輯 - 了解功能強大的 VS Code 編輯器。
  • 程式碼導覽 - 在原始碼中快速移動。
  • 語言支援 - 了解我們支援的程式語言,包括 VS Code 內建的以及透過社群擴充功能提供的。
  • 偵錯 - 直接在 VS Code 編輯器中偵錯您的原始碼。

常見問題

工作可以使用與整合終端機 (Integrated Terminal) 中指定的 shell 不同的 shell 嗎?

是的。您可以使用 "terminal.integrated.automationProfile.*" 設定來設定 VS Code 中所有自動化 (包括工作) 將使用的 shell。

    "terminal.integrated.automationProfile.windows": {
        "path": "cmd.exe"
    }

或者,您可以使用 options.shell 屬性覆寫工作的 shell。您可以針對每個工作、全域或每個平台設定此項。例如,要在 Windows 上使用 cmd.exe,您的 tasks.json 將包含

{
    "version": "2.0.0",
    "windows": {
        "options": {
            "shell": {
                "executable": "cmd.exe",
                "args": [
                    "/d", "/c"
                ]
            }
        }
    },
    ...

背景工作可以用作 launch.json 中的 prelaunchTask 嗎?

是的。由於背景工作會一直執行直到被終止,所以背景工作本身沒有「完成」的訊號。要將背景工作用作 prelaunchTask,您必須為背景工作新增一個適當的背景 problemMatcher,這樣工作系統和偵錯系統才能知道該工作「已完成」。

您的工作可能是

{
  "type": "npm",
  "script": "watch",
  "problemMatcher": "$tsc-watch",
  "isBackground": true
}

注意:$tsc-watch 是一個 背景 (background) 問題比對器,這是背景工作所需的。

然後,您可以將該工作用作 launch.json 檔案中的 prelaunchTask

{
  "name": "Launch Extension",
  "type": "extensionHost",
  "request": "launch",
  "runtimeExecutable": "${execPath}",
  "args": ["--extensionDevelopmentPath=${workspaceRoot}"],
  "stopOnEntry": false,
  "sourceMaps": true,
  "outFiles": ["${workspaceRoot}/out/src/**/*.js"],
  "preLaunchTask": "npm: watch"
}

有關背景工作的更多資訊,請參閱 背景 / 監看工作

為什麼執行工作時會收到「找不到命令」?

當您的終端機無法辨識您嘗試執行的工作命令時,就會出現「找不到命令」的訊息。最常見的情況是,命令被設定為您的 shell 啟動腳本的一部分。工作以非登入和非互動模式執行,這表示您的 shell 的啟動腳本不會執行。特別是 nvm 已知會使用啟動腳本作為其設定的一部分。

有幾種方法可以解決此問題

  1. 確保您的命令在您的路徑中,並且不需要啟動腳本才能新增到您的路徑中。這是解決問題最徹底的方法,也是推薦的解決方案。
  2. 您可以對您的工作進行一次性修復,使其以登入或互動模式執行。不建議這樣做,因為它可能會產生其他後果。然而,對於單一工作來說,這也是一個快速簡便的修復方法。以下是一個使用 bash 作為 shell 執行此操作的工作範例
{
  "type": "npm",
  "script": "watch",
  "options": {
    "shell": {
      "args": ["-c", "-l"]
    }
  }
}

上面的 npm 工作將使用命令 (-c) 執行 bash,就像工作系統預設所做的那樣。然而,此工作也將 bash 作為登入 shell (-l) 執行。

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