ここでは上で見たextension.sayHelloコマンドと同様なextension.calcコマンドを、このプロジェクトに追加で作成する(1つの拡張機能に複数のコマンドを実装するサンプルだと思ってほしい)。基本構造はsayHelloと変わらないので、ポイントを絞って、コードを見ていこう。
package.jsonファイルは次のようになる。
{
…… 省略 ……
"activationEvents": [
"onCommand:extension.sayHello",
"onCommand:extension.calc"
],
"main": "./out/src/extension",
"contributes": {
"commands": [{
"command": "extension.sayHello",
"title": "Hello World"
}, {
"command": "extension.calc",
"title": "Tiny Calculator"
}]
},
…… 省略 ……
}
activationEvents属性には、どちらのコマンドが先に実行されてもアクティベーションが行われるように両方のコマンドを記述している。また、contributes属性には、extension.sayHelloコマンドと同様にextension.calcコマンドの記述を追加する。
コマンドの実装は次のようになる(変数disposableの名前を「cmd1」に変更している)。変更したのはactivateメソッドのみだ。
export function activate(context: vscode.ExtensionContext) {
console.log('Congratulations, your extension "hellovscext" is now active!');
let cmd1 = vscode.commands.registerCommand('extension.sayHello', () => {
vscode.window.showInformationMessage('Hello World!');
});
let cmd2 = vscode.commands.registerCommand('extension.calc', () => {
vscode.window.showInputBox({
prompt: 'Tiny Calculator: ',
validateInput: param => {
var regex = /\d+\s*[-+*/]\s*\d/;
return regex.test(param) ? '' : 'input: number [-+*/] number';
}
}).then((value) => {
if (value == undefined) return;
let result = eval(value);
vscode.window.showInformationMessage(value + ' = ' + result);
});
});
context.subscriptions.push(cmd1);
context.subscriptions.push(cmd2);
}
extension.calcコマンドが呼び出されると、簡易計算機はユーザーから「数値 演算記号 数値」という形式の入力を受け取り、その計算結果を表示する。これを行っているのが、上で強調表示しているregisterCommand関数呼び出しに渡しているアロー関数の部分だ(それ以外はextension.sayHelloコマンドと同様なので、特に説明の必要はないだろう)。
このアロー関数内では、showInputBox関数(vscode.window名前空間)を呼び出して、ユーザーにプロンプトを表示している。この関数の戻り値はThenableオブジェクトとなっていて、showInputBox関数呼び出しにチェーンしたthenメソッドの引数にユーザー入力が渡される(ただし、catchメソッドのチェーンはできないようだ)。つまり、大ざっぱには次のような構造になっている。
vscode.window.showInputBox({
…… showInpuBox関数に渡すオプション ……
}).then((value) => {
…… ユーザー入力(value)を使って処理を行う ……
});
showInputBox関数には渡せるオプションには幾つかあるが、ここではユーザーに表示するプロンプト(promptプロパティ)と、ユーザー入力の検証を行う関数(validateInputプロパティ)を渡している。検証関数では正規表現を使用して上述の「数値 演算記号 数値」形式の入力になっているかをチェックしている。
validateInput: param => {
var regex = /\d+\s*[-+*/]\s*\d/;
return regex.test(param) ? '' : 'input: number [-+*/] number';
}
検証結果が正しければ上のように空文字列(あるいはnull、undefined)を返す。そうでなければ、ユーザーに表示するメッセージを返す。ここでは上で述べた形式で入力するようなメッセージとなっている(実際には空白文字はなくてもよい)。なお、検証は文字が入力されるたびに行われる([Enter]キーを押して、コマンドを実行するタイミングではないので注意しよう)。
ユーザーが[Enter]キーを押して、プロンプトを閉じると、thenメソッドに渡したアロー関数が呼び出される。このとき、検証が失敗していれば引数にはundefinedが、検証が成功していればユーザーが入力した文字列が渡される。
vscode.window.showInputBox({
…… 省略 ……
}).then((value) => {
if (value == undefined) return;
let result = eval(value);
vscode.window.showInformationMessage(value + ' = ' + result);
});
ここは思いっきり手抜きで、eval関数を利用して、入力された文字列を評価し、その結果をshowInformationMessage関数を使用して表示している。上では元の入力(数式)と評価結果を連結して文字列化しているので問題ないが、実際にはshowInformationMessage関数は文字列以外の値を受け取るとメッセージを表示しないので注意すること。
この拡張機能の実行画面を以下に示す。
拡張機能の実行画面
これで先ほどの例より少しはましな拡張機能は完成だ。
今回は、generator-codeが生成するデフォルトの拡張機能を使用して、VS Codeの拡張機能作成の基礎の基礎を見た。「Extending Visual Studio Code」ページでは、拡張機能を作成するために必要となる情報がこれでもかというほど掲載されているので、興味のある方はぜひご覧になってほしい。
Copyright© Digital Advantage Corp. All Rights Reserved.