タスクで外部ツールを統合する
リンティング、ビルド、パッケージング、テスト、ソフトウェアシステムのデプロイなどのタスクを自動化するためのツールは数多く存在します。TypeScript コンパイラ、ESLint や TSLint などのリンター、さらに Make、Ant、Gulp、Jake、Rake、MSBuild などのビルドシステムがその例です。
これらのツールはほとんどがコマンドラインから実行され、内部のソフトウェア開発ループ (編集、コンパイル、テスト、デバッグ) の内外でジョブを自動化します。開発ライフサイクルにおけるその重要性を考慮すると、VS Code 内からツールを実行し、その結果を分析できることは役立ちます。VS Code のタスクは、スクリプトを実行し、プロセスを開始するように構成できるため、これらの既存のツールの多くを、コマンドラインを入力したり新しいコードを記述したりすることなく VS Code 内から使用できます。ワークスペースまたはフォルダー固有のタスクは、ワークスペースの `.vscode` フォルダーにある `tasks.json` ファイルから構成されます。
拡張機能は、タスクプロバイダーを使用してタスクを提供することもでき、これらの提供されたタスクは、`tasks.json` ファイルで定義されたワークスペース固有の構成を追加できます。
注: タスクのサポートは、ワークスペースフォルダーで作業している場合にのみ利用できます。単一のファイルを編集している場合は利用できません。
TypeScript Hello World
JavaScript にコンパイルしたいシンプルな「Hello World」TypeScript プログラムから始めましょう。
空のフォルダー「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) を押すか、グローバルなターミナルメニューからビルドタスクの実行を実行すると、以下のピッカーが表示されます。
最初の項目は TypeScript コンパイラを実行し、TypeScript ファイルを JavaScript ファイルに変換します。コンパイラが完了すると、`HelloWorld.js` ファイルが作成されます。2 番目の項目は、TypeScript コンパイラをウォッチモードで開始します。`HelloWorld.ts` ファイルを保存するたびに、`HelloWorld.js` ファイルが再生成されます。
TypeScript ビルドまたはウォッチタスクを既定のビルドタスクとして定義することもできます。そうすることで、ビルドタスクの実行 (⇧⌘B (Windows、Linux Ctrl+Shift+B)) をトリガーしたときに直接実行されます。これを行うには、グローバルなターミナルメニューから既定のビルドタスクの構成を選択します。これにより、利用可能なビルドタスクのピッカーが表示されます。tsc: build または tsc: 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 の例をクローンしている場合、グローバルメニューからタスクの実行を実行すると、次のリストが表示されます。
まだインストールしていない場合は、`npm install` を実行して必要な npm モジュールをインストールします。次に、`server.js` ファイルを開き、ステートメントの最後にセミコロンを追加し (ESLint スターターはセミコロンなしのステートメントを想定していることに注意してください)、もう一度タスクの実行を実行します。今回はnpm: lintタスクを選択します。使用する問題マッチャーを尋ねられたら、ESLint stylishを選択します。
タスクを実行すると、問題ビューにエラーが 1 つ表示されます。
さらに、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 拡張機能で検出されたタスクの例です。
ヒント: 「task」、「スペース」、コマンド名(この場合は「task lint」)を入力することで、クイックオープン (⌘P (Windows、Linux Ctrl+P)) を通じてタスクを実行できます。
タスクの自動検出は、以下の設定で無効にできます。
{
"typescript.tsc.autoDetect": "off",
"grunt.autoDetect": "off",
"jake.autoDetect": "off",
"gulp.autoDetect": "off",
"npm.autoDetect": "off"
}
カスタムタスク
ワークスペース内のすべてのタスクやスクリプトが自動検出されるわけではありません。独自のカスタムタスクを定義する必要がある場合もあります。環境を正しく設定するためにテストを実行するスクリプトがあるとします。スクリプトはワークスペース内のスクリプトフォルダーに保存されており、Linux と macOS の場合は `test.sh`、Windows の場合は `test.cmd` と名付けられています。グローバルなターミナルメニューからタスクの構成を実行し、テンプレートから tasks.json ファイルを作成エントリを選択します。これにより、以下のピッカーが開きます。
注: タスクランナーテンプレートのリストが表示されない場合は、すでにフォルダーに `tasks.json` ファイルが存在し、その内容がエディターで開かれている可能性があります。この例では、ファイルを閉じて削除するか名前を変更してください。
私たちはさらなる自動検出のサポートに取り組んでおり、このリストは将来的にはどんどん小さくなっていきます。独自のカスタムタスクを記述したいので、リストからその他を選択します。これにより、タスクスケルトンが記述された `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: タスクのタイプ。カスタムタスクの場合、`shell` または `process` のいずれかになります。`shell` が指定されている場合、コマンドはシェルコマンド (例: bash、cmd、PowerShell) として解釈されます。`process` が指定されている場合、コマンドは実行するプロセスとして解釈されます。
- command: 実際に実行するコマンド。
- windows: Windows 固有のプロパティ。コマンドが Windows オペレーティングシステムで実行されるときに、既定のプロパティの代わりに使用されます。
- group: タスクが属するグループを定義します。例では、`test` グループに属します。テストグループに属するタスクは、コマンドパレットからテストタスクの実行を実行することで実行できます。
- presentation: ユーザーインターフェースでタスク出力がどのように扱われるかを定義します。この例では、出力が表示される統合ターミナルが`常に`表示され、タスクが実行されるたびに`新しい`ターミナルが作成されます。
- options: `cwd` (現在の作業ディレクトリ)、`env` (環境変数)、または `shell` (既定のシェル) のデフォルトをオーバーライドします。オプションはタスクごとに設定できますが、グローバルまたはプラットフォームごとにも設定できます。ここで構成された環境変数は、タスクスクリプトまたはプロセス内からのみ参照でき、args、コマンド、またはその他のタスク属性の一部である場合は解決されません。
- runOptions: タスクがいつ、どのように実行されるかを定義します。
- hide: タスクを「タスクの実行クイックピッカー」から非表示にします。これは、独立して実行できない複合タスクの要素に役立ちます。
`tasks.json` ファイルで IntelliSense を使用して、タスクプロパティと値の全セットを確認できます。サジェストのトリガー (⌃Space (Windows, Linux Ctrl+Space)) で候補を表示し、ホバーまたは詳細を読む... ('i') のフライアウトで説明を読みます。
tasks.json スキーマも確認できます。
スペースや `$` などの特殊文字を含むコマンドや引数に関しては、シェルコマンドには特別な処理が必要です。デフォルトでは、タスクシステムは以下の動作をサポートしています。
- 単一のコマンドが提供された場合、タスクシステムはコマンドをそのまま基盤となるシェルに渡します。コマンドが適切に機能するためにクォーティングやエスケープが必要な場合、コマンドは適切なクォートまたはエスケープ文字を含む必要があります。例えば、名前にスペースを含むフォルダのディレクトリをリストアップするには、bashで実行されるコマンドは `ls 'folder with spaces'` のようになります。
{
"label": "dir",
"type": "shell",
"command": "dir 'folder with spaces'"
}
- コマンドと引数が提供される場合、コマンドまたは引数にスペースが含まれていると、タスクシステムはシングルクォートを使用します。`cmd.exe` の場合はダブルクォートが使用されます。以下のシェルコマンドは、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: シェルの強力なクォーティングメカニズムを使用します。これにより、文字列内のすべての評価が抑制されます。PowerShell および Linux と macOS のシェルでは、シングルクォート (`'`) が使用されます。cmd.exe では、`"` が使用されます。
- weak: シェルの弱い引用メカニズムを使用します。これにより、文字列内の式 (たとえば、環境変数) は引き続き評価されます。PowerShell および Linux と macOS のシェルでは、二重引用符 (`"`) が使用されます。cmd.exe は弱い引用をサポートしていないため、VS Code も `"` を使用します。
コマンド自体にスペースが含まれている場合、VS Code はデフォルトでコマンドも強力に引用します。引数と同様に、ユーザーは同じリテラルスタイルを使用してコマンドの引用を制御できます。
ワークフローを設定するためのタスクプロパティは他にも多数あります。IntelliSense を使用して ⌃Space (Windows, Linux Ctrl+Space) で有効なプロパティの概要を確認できます。
グローバルメニューバーに加えて、タスクコマンドはコマンドパレット (⇧⌘P (Windows, Linux Ctrl+Shift+P)) を使用してアクセスできます。「task」でフィルタリングすると、さまざまなタスク関連コマンドが表示されます。
複合タスク
`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` にリストされている順序で実行されます。`"dependsOrder": "sequence"` とともに `dependsOn` で使用されるバックグラウンド/ウォッチタスクには、それらが「完了」したときに追跡する問題マッチャーが必要です。以下のタスクは、タスク 2、タスク 3、次にタスク 1 を実行します。
{
"label": "One",
"type": "shell",
"command": "echo Hello ",
"dependsOrder": "sequence",
"dependsOn": ["Two", "Three"]
}
ユーザーレベルのタスク
特定のワークスペースやフォルダーに関連付けられていないユーザーレベルのタスクは、タスク: ユーザータスクを開くコマンドを使用して作成できます。他のタスクタイプはワークスペース情報を必要とするため、ここでは `shell` および `process` タスクのみを使用できます。
出力動作
タスクの実行時に統合ターミナルパネルがどのように動作するかを制御したい場合があります。たとえば、エディターのスペースを最大化し、問題があると思われる場合にのみタスク出力を確認したい場合があります。ターミナルの動作は、タスクの `presentation` プロパティを使用して制御できます。このプロパティには以下のプロパティがあります。
- reveal: 統合ターミナルパネルを前面に表示するかどうかを制御します。有効な値は次のとおりです。
- `always` - パネルは常に前面に表示されます。これがデフォルトです。
- `never` - ユーザーは、表示 > ターミナル コマンド (⌃` (Windows, Linux Ctrl+`)) を使用して、ターミナルパネルを明示的に前面に表示する必要があります。
- `silent` - 出力がエラーや警告についてスキャンされていない場合にのみ、ターミナルパネルが前面に表示されます。
- revealProblems: このタスクの実行時に問題パネルを表示するかどうかを制御します。`reveal` オプションよりも優先されます。デフォルトは `never` です。
- `always` - このタスクが実行されると、常に問題パネルが表示されます。
- `onProblem` - 問題が見つかった場合にのみ、問題パネルが表示されます。
- `never` - このタスクが実行されても、問題パネルは表示されません。
- 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: 最後に実行したタスクを再実行コマンドでタスクが実行されたときに、変数がどのように評価されるかを制御します。デフォルトは `true` であり、タスクが再実行されるときに変数が再評価されることを意味します。`false` に設定すると、タスクの以前の実行で解決された変数値が使用されます。
- runOn: タスクがいつ実行されるかを指定します。
- `default` - タスクはタスクの実行コマンドを介して実行された場合にのみ実行されます。
- `folderOpen` - タスクは、含むフォルダーが開かれたときに実行されます。`folderOpen` を含むタスクがあるフォルダーを初めて開くと、そのフォルダーでタスクを自動的に実行することを許可するかどうかを尋ねられます。後で、自動タスクの管理コマンドを使用して、自動タスクを許可と自動タスクを許可しないの間で決定を変更できます。
- instanceLimit - タスクの同時実行を許可されるインスタンスの数。デフォルト値は `1` です。
自動検出タスクのカスタマイズ
前述のとおり、`tasks.json` ファイルで自動検出されたタスクをカスタマイズできます。通常、プレゼンテーションプロパティを変更したり、タスクの出力からエラーや警告をスキャンするために問題マッチャーをアタッチしたりするためにこれを行います。タスクの実行リストからタスクを直接カスタマイズするには、右側の歯車アイコンを押して、対応するタスク参照を `tasks.json` ファイルに挿入します。ESLint を使用して JavaScript ファイルをリンティングする以下の Gulp ファイルがあるとします (ファイルは 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...
});
グローバルなターミナルメニューからタスクの実行を実行すると、以下のピッカーが表示されます。
歯車アイコンを押します。これにより、以下の `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 は、問題マッチャーを使用してタスクからの出力を処理できます。問題マッチャーは、タスク出力テキストで既知の警告またはエラー文字列をスキャンし、これらをエディターと問題パネルにインラインで報告します。VS Code には、いくつかの問題マッチャーが「標準で」搭載されています。
- TypeScript: `$tsc` は、出力のファイル名が、開いているフォルダに対して相対的であると仮定します。
- TypeScript Watch: `$tsc-watch` は、ウォッチモードで実行されたときの `tsc` コンパイラからの問題を照合します。
- JSHint: `$jshint` は、ファイル名が絶対パスとして報告されると仮定します。
- JSHint Stylish: `$jshint-stylish` は、ファイル名が絶対パスとして報告されると仮定します。
- ESLint Compact: `$eslint-compact` は、出力のファイル名が、開いているフォルダに対して相対的であると仮定します。
- ESLint Stylish: `$eslint-stylish` は、出力のファイル名が、開いているフォルダに対して相対的であると仮定します。
- Go: `$go` は、`go` コンパイラから報告された問題にマッチします。ファイル名が、開いているフォルダに対して相対的であると仮定します。
- CSharp および VB コンパイラ: `$mscompile` は、ファイル名が絶対パスとして報告されると仮定します。
- Lessc コンパイラ: `$lessc` は、ファイル名が絶対パスとして報告されると仮定します。
- Node Sass コンパイラ: `$node-sass` は、ファイル名が絶対パスとして報告されると仮定します。
独自の課題マッチャーを作成することもできますが、それは後のセクションで説明します。
タスクにキーボードショートカットをバインドする
頻繁にタスクを実行する必要がある場合、そのタスクにキーボードショートカットを定義できます。
たとえば、上記のテストの実行タスクに `Ctrl+H` をバインドするには、`keybindings.json` ファイルに以下を追加します。
{
"key": "ctrl+h",
"command": "workbench.action.tasks.runTask",
"args": "Run tests"
}
変数の置換
タスク構成を作成する際、アクティブなファイル (`${file}`) やワークスペースのルートフォルダー (`${workspaceFolder}`) など、事前に定義された一般的な変数セットがあると便利です。VS Code は `tasks.json` ファイル内の文字列内の変数置換をサポートしており、事前定義された変数の完全なリストは変数リファレンスで確認できます。
注: すべてのプロパティが変数置換を受け入れるわけではありません。具体的には、`command`、`args`、`options` のみが変数置換をサポートしています。
以下は、現在開いているファイルを 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}"]
}
`tasks.json` または `launch.json` で Python 拡張機能が使用する選択された Python インタープリターを指定したい場合は、` ${command:python.interpreterPath}` コマンドを使用できます。
単純な変数置換では不十分な場合、`tasks.json` ファイルに `inputs` セクションを追加することで、タスクのユーザーから入力を取得することもできます。
`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"
}
}
有効なOS固有のプロパティは、Windowsの場合は`windows`、Linuxの場合は`linux`、macOSの場合は`osx`です。OS固有のスコープで定義されたプロパティは、タスクまたはグローバルスコープで定義されたプロパティを上書きします。
グローバルタスク
タスクプロパティはグローバルスコープでも定義できます。存在する場合、それらは異なる値で同じプロパティを定義しない限り、特定のタスクに使用されます。以下の例では、すべてのタスクが新しいパネルで実行されることを定義するグローバルな`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)) を開き、タスク: ユーザータスクを開くコマンドを実行します。
PowerShellでの文字のエスケープ
デフォルトのシェルが PowerShell の場合、またはタスクが PowerShell を使用するように構成されている場合、予期しないスペースや引用符のエスケープが発生することがあります。この予期しないエスケープは、コマンドレットを含む場合にのみ発生します。VS Code はコマンドにコマンドレットが含まれているかどうかを判断できないためです。以下の例 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\\\""
}
]
タスク出力のエンコーディングを変更する
タスクはディスク上のファイルと頻繁に連携します。これらのファイルがシステムエンコーディングとは異なるエンコーディングでディスクに保存されている場合、タスクとして実行されるコマンドにどのエンコーディングを使用するかを知らせる必要があります。これはオペレーティングシステムと使用されるシェルに依存するため、これを制御するための一般的な解決策はありません。以下は、これを機能させるためのアドバイスと例です。
エンコーディングを調整する必要がある場合は、オペレーティングシステムで使用されるデフォルトのエンコーディングを変更するか、少なくともシェルのプロファイルファイルを調整して使用するシェルを変更することを検討する必要があります。
特定のタスクにのみ調整する必要がある場合は、エンコーディングを変更するために必要な OS 固有のコマンドをタスクコマンドラインに追加します。次の例は、デフォルトがコードページ 437 の Windows 用です。タスクはキリル文字を含むファイルの出力を表示するため、コードページ 866 が必要です。デフォルトシェルが `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` コマンドを使用してロケールを検査し、必要な環境変数を調整できます。
タスクの実行例
タスクの威力を示すために、VS Code がリンターやコンパイラなどの外部ツールを統合するためにタスクをどのように使用できるかを示すいくつかの例を以下に示します。
TypeScript から JavaScript へのトランスパイル
TypeScript のトピックには、TypeScript を JavaScript にトランスパイルし、VS Code 内から関連するエラーを監視するタスクを作成する例が含まれています。
Less および SCSS から CSS へのトランスパイル
CSS のトピックでは、タスクを使用して CSS ファイルを生成する方法の例が示されています。
問題マッチャーの定義
VS Codeには、最も一般的な問題マッチャーがいくつか標準で搭載されています。しかし、世の中には多くのコンパイラやリンティングツールが存在し、それぞれ独自の形式のエラーや警告を出力するため、独自の問題マッチャーを作成したい場合があります。
`helloWorld.c` プログラムで、開発者が **printf** を **prinft** と誤入力したとします。gcc でコンパイルすると、以下の警告が表示されます。
helloWorld.c:5:3: warning: implicit declaration of function ‘prinft’
出力メッセージをキャプチャし、VS Code で対応する問題を表示できる問題マッチャーを作成したいと考えています。問題マッチャーは正規表現に大きく依存しています。以下のセクションでは、正規表現に精通していることを前提としています。
ヒント: ECMAScript (JavaScript) フレーバーを搭載した RegEx101 playground は、正規表現を開発およびテストするための優れた方法であると私たちは考えています。
上記の警告(およびエラー)をキャプチャするマッチャーは次のようになります。
{
// 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) を押して問題リストを取得すると、以下の出力が得られます。
注: C/C++ 拡張機能には GCC の問題マッチャーが含まれているため、独自に定義する必要はありません。
パターン内で使用できるプロパティはいくつかあります。
- location - 問題の場所が line または line,column または startLine,startColumn,endLine,endColumn の場合、汎用的な location マッチグループを使用できます。
- endLine - 問題の終了行のマッチグループインデックス。コンパイラによって終了行の値が提供されない場合は省略できます。
- endColumn - 問題の終了列のマッチグループインデックス。コンパイラによって終了列の値が提供されない場合は省略できます。
- code - 問題のコードのマッチグループインデックス。コンパイラによってコード値が提供されない場合は省略できます。
ファイルのみをキャプチャする問題マッチャーを定義することもできます。これを行うには、オプションの `kind` 属性を `file` に設定した `pattern` を定義します。この場合、`line` または `location` プロパティを提供する必要はありません。
注: `kind` プロパティが `file` に設定されている場合、機能するパターンは少なくとも `file` と `message` のマッチグループを提供する必要があります。`kind` プロパティが提供されていない場合、または `kind` プロパティが `location` に設定されている場合、機能するパターンは `line` または `location` プロパティも提供する必要があります。
注: 問題マッチャーは、与えられたコマンドからの出力のみを解析します。別のファイル (たとえば、ログファイル) に書き込まれた出力を解析したい場合は、実行するコマンドが、実行を終了する前にその別のファイルからの行を出力するようにしてください。
複数行問題マッチャーの定義
一部のツールは、特にスタイリッシュなレポーターが使用されている場合、ソースファイルで見つかった問題を複数の行にわたって表示します。例は ESLint です。スタイリッシュモードでは、次のような出力を生成します。
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 からの出力に一致しますが、解決する必要のある小さな問題がまだ 1 つあります。以下のコードには、ファイル名をキャプチャするための最初の正規表現と、行、列、重大度、メッセージ、エラーコードをキャプチャするための 2 番目の正規表現があります。
{
"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」に一致し、2番目の正規表現は「1:0 error ...」に一致します。次の行「1:9 error ...」は処理されますが、最初の正規表現とは一致しないため、問題はキャプチャされません。
これを機能させるには、複数行パターンで最後の正規表現に `loop` プロパティを指定できます。`true` に設定すると、タスクシステムは正規表現が一致する限り、複数行マッチャーの最後のパターンを、出力の各行に適用するように指示します。
この場合、`test.js` に一致する最初のパターンによってキャプチャされた情報は、`loop` パターンに一致する後続の各行と結合され、複数の問題が作成されます。この例では、6つの問題が作成されます。
以下は、ESLint のスタイリッシュな問題を完全にキャプチャするための問題マッチャーです。
{
"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
}
]
}
注: 同じリソースで全く同じ行と列で複数の問題が発生した場合、1つの問題のみが表示されます。これは、マルチライン問題マッチャーだけでなく、すべての問題マッチャーに適用されます。
既存の問題マッチャーの変更
既存の問題マッチャーがあなたのニーズに近い場合、`tasks.json` タスクでそれを変更できます。たとえば、`$tsc-watch` 問題マッチャーは閉じたドキュメントにのみ適用されます。すべてのドキュメントに適用したい場合は、それを変更できます。
{
"type": "npm",
"script": "watch",
"problemMatcher": {
"base": "$tsc-watch",
"applyTo": "allDocuments"
},
"isBackground": true
}
その他の変更可能な問題マッチャープロパティには、`background`、`fileLocation`、`owner`、`pattern`、`severity`、`source` があります。
バックグラウンド / ウォッチタスク
一部のツールは、ファイルシステムの変更を監視しながらバックグラウンドで実行し、ディスク上のファイルが変更されたときにアクションをトリガーする機能をサポートしています。`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.` がコンソールに出力されると停止します。
- これらの2つの文字列の間で問題が報告されます。
- コンパイラは、初期起動時にも一度実行されます(コンソールに`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` とマークされている必要があります。そうしないと、タスクはバックグラウンドで実行され続けます。
ウォッチモードで実行される `tsc` タスクのための、完全に手書きされた `tasks.json` は次のようになります。
{
"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 エディターで直接ソースコードをデバッグします。
よくある質問
タスクは統合ターミナルで指定されたシェルとは異なるシェルを使用できますか?
はい。`"terminal.integrated.automationProfile.*"` 設定を使用して、タスクを含む VS Code のすべての自動化に使用されるシェルを設定できます。
"terminal.integrated.automationProfile.windows": {
"path": "cmd.exe"
}
あるいは、`options.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` は、バックグラウンドタスクに必要とされるバックグラウンド問題マッチャーです。
その後、`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"
}
バックグラウンドタスクの詳細については、バックグラウンド / ウォッチタスクを参照してください。
タスクを実行すると「コマンドが見つかりません」というエラーが発生するのはなぜですか?
「コマンドが見つかりません」というメッセージは、実行しようとしているタスクコマンドがターミナルで実行可能なものとして認識されない場合に発生します。これは多くの場合、コマンドがシェルの起動スクリプトの一部として構成されているために起こります。タスクは非ログインおよび非インタラクティブとして実行されるため、シェルの起動スクリプトは実行されません。特に `nvm` は、設定の一部として起動スクリプトを使用することが知られています。
この問題にはいくつかの解決策があります。
- コマンドがパス上にあり、パスに追加するために起動スクリプトを必要としないことを確認します。これは、問題を解決する最も徹底的な方法であり、推奨される解決策です。
- タスクをログインまたはインタラクティブとして実行するように、一時的な修正を行うことができます。これは、他の結果をもたらす可能性があるため推奨されません。ただし、単一のタスクの場合、迅速かつ簡単な修正にもなりえます。以下は、シェルとして `bash` を使用してこれを行うタスクの例です。
{
"type": "npm",
"script": "watch",
"options": {
"shell": {
"args": ["-c", "-l"]
}
}
}
上記の `npm` タスクは、タスクシステムがデフォルトで行うように、コマンド (`-c`) を付けて `bash` を実行します。ただし、このタスクは `bash` をログインシェル (`-l`) としても実行します。