Visual Studio Codeで外部プログラムを実行するためにExtensionでタスクが提供することができるようになっている。ただ、公式のサンプル(Task Providerのサンプル)は、タスク自体が高度過ぎてどこまでがタスクの本質か分かりにくく感じたので、実用的ではないが簡単なタスクの例で作り方をまとめる。
タスクとは
Visual Studio Codeで、ビルドやデバッグなど何かを実行することはタスクと呼ばれ、Run Task...
から都度実行に必要なパラメータを設定して実行したり、Configure Task
で予め実行に必要なパラメータを設定したものを実行することができるようになっている。
プロジェクトだけで使用するタスクなら、「Custom Tasks」に載っている方法で以下のように定義できる。Configure Task
からCreate task.json from template
を選択し、タイプを選択するとtask.json
が生成される。
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "echo",
"type": "shell",
"command": "echo Hello"
}
]
}
task.json
で定義したタスクは、Run Task...
で選択可能になる。
実行しようとすると、タスクの実行結果(メッセージなど)をどうするかという確認が表示される。(この辺は未調査)
実行するとechoの結果がコンソールに表示される。
Extensionでタスクを提供するには
Extensionでは、以下のようにしてタスクを提供する。ここで「タスク」とはVisual Studio Codeが実際に何かを実行するために使うvscode.Task
クラスのオブジェクトを指し、「タスク定義」は「タスク」を生成するための情報を指すものとする。タスク定義には、Visual Studio Codeがタスクを識別するためのtype
や、タスクが受け取るパラメータ(型や説明)が含まれる。
-
package.json
のcontributes
に「タスク定義」を登録する -
extension.ts
などで、TaskProvider
を定義する。 -
provideTasks
:Run Task...
で利用可能なタスクを取得するのに使われる。 -
resolveTask
:Configure Task
で設定済みの「タスク定義」から「タスク」を生成するのに使われる。 -
activate
時にTaskProvidr
を登録する
Task Providerの定義
vscode.TaskProvider
を継承したクラスを定義する。Visual Studio Codeがタスクを必要とするときにコールするメソッドprovideTasks
とresolveTask
を定義する。
import * as vscode from 'vscode';
const taskType = 'greeting'; // package.json の taskDefinitions で設定した type の値
// Discriminated Unions でミス防止(いるかどうか)
// https://basarat.gitbook.io/typescript/type-system/discriminated-unions
interface GreetingTaskDefinition extends vscode.TaskDefinition {
type: typeof taskType;
message: string; // taskDefinitions の properties に対応するプロパティ
}
// Task Providerの定義
class GreetingTaskProvider implements vscode.TaskProvider {
provideTasks(): Thenable<vscode.Task[]> | undefined {
// 利用可能なタスクを返す。
// Run Task...で一覧表示する度にコールされる。
// 毎回生成し直す必要が無ければ、一度作成したものを保持して、要求されたときに返しても良い。
return generateTasks();
}
resolveTask( task: vscode.Task ): vscode.Task | undefined {
// task.json で定義したタスク定義を受け取り、Visual Studio Codeが実行するタスクを作成する
const definition: GreetingTaskDefinition = <any>task.definition;
return createGreetingTask( definition );
}
}
タスクの生成
provideTasks
でもresolveTask
でも同じような要領でタスクを作成するので、例えば以下のように「タスク定義」から「タスク」を生成する関数として切り出しておくと良いと思う。また、resolveTask
ではタスク名の表示はないようなので、name
を省略できるようにしても良いと思う。
function createGreetingTask( definition: GreetingTaskDefinition, name: string = '' ) {
// Visual Studio Codeが実行するタスクの作成
return new vscode.Task(
definition, // 最低限タスクを識別するための type があれば良い
vscode.TaskScope.Workspace, // Global/Workspace...Globalは未対応の模様
name, // name
definition.type, // source
// Run Taks...での表示を決める。表示は「source: name」となる。
new vscode.ShellExecution( `echo ${definition.message} > greeting.txt` ) // 実行するコマンド
);
}
provideTasks
は利用可能なタスクを返すので、複数のタスクをまとめて生成する関数を作成しても良いと思う。
なお、ここではasync
である必要性はないものの、provideTasks
は要求があった時にすぐタスクを作れないことを想定し、Promise<vscode.Task[]>
が戻り値となっているため、それに合わせた戻り値にしている。
async function generateTasks(): Promise<vscode.Task[]> {
const now = Date.now().toString();
const task: vscode.Task[] = [
createGreetingTask( { type: taskType, message: 'Good morning.' }, 'morning' ),
createGreetingTask( { type: taskType, message: 'Good evening.' }, 'evening' ),
createGreetingTask( { type: taskType, message: now }, 'now' )
];
return task;
}
Task Providerの登録
これはお決まりのコード。
const disposables: vscode.Disposable[] = [];
export function activate(context: vscode.ExtensionContext) {
// Task Providerの登録
disposables.push( vscode.tasks.registerTaskProvider( taskType, new GreetingTaskProvider() ) );
}
export function deactivate() {
disposables.forEach( disposable => disposable.dispose() );
}
Extensionのタスクの利用
Extensionが提供するタスクは、以下ようにして実行する。
-
Run Task...
から選択する -
Configure Task
で設定したものを実行する - Extensionから実行する
例えば、Configure Task
以下のように設定すると、
{
"version": "2.0.0",
"tasks": [
{
"type": "greeting",
"message": "Greeting from task.json",
"label": "greeting: task.json"
}
]
}
以下の一番下のように設定したタスクが表示される。実行すればGreeting from task.json
と書かれたテキストファイルが生成される。
Extension内部から実行することもでき、例えば以下のようにすればcommand
から実行することができる。
vscode.commands.registerCommand( 'execute-task', () => {
vscode.tasks.executeTask( createGreetingTask( { type: taskType, message: 'Greeting from command.' } ) );
}
まとめ
Visual Studio Codeでは、外部のプログラムの実行をタスクとして提供できる。タスク(vscode.Task
)はTaskProvider
をactivate
時に登録することで、Configure Task
で設定したり、Run Task...
で実行したりできるようになる。また、vscode.tasks.executeTask
により、Extension内から直接実行することもできる。
このページでは扱っていないが、stderrに出力されるエラーを整形したい場合は、Defining a problem matcherに載っているようにProblem Matcherを作ると良いらしい。