テクノロジー
VSCode の拡張機能を作ってみる
はじめに
唐突ですが VSCode の拡張機能作ってみたくありませんか?
私は日々のコーディングの業務ではもちろん VSCode を使っていますが、痒いところに手が届かないといいますか、自分の思い通りのコードエディタにするために、あと一歩足りない・・・この機能があれば・・・と思うことがあったりします。
みなさんもこう感じた経験ないですか?
こういったニッチな要望に答えてくれる拡張機能があればいいですが、なければ自分で作るしかありません。
ということで今回は VSCode の拡張機能の作り方をこの記事で紹介したいと思います!
とりあえず Hello World してみる
デバッグで動かしてみる
VSCode の公式ドキュメント の Get Started を見てみるとサンプルの拡張機能(拡張機能の雛形)を作る方法が載っています。
この手順に従ってサンプルの拡張機能を作ってみます。
以下のコマンドを打って必要なモジュールをインストールして雛形を作ってみます。
npm install -g yo generator-code
yo code
雛形は yo コマンドが対話的に作成してくれます。
今回は TypeScript を使って雛形をつくることとして、名前は適当にHelloWorld
とします。
# ? What type of extension do you want to create?
> New Extension (TypeScript)
# ? What's the name of your extension? HelloWorld
# ? What's the identifier of your extension? hellowold # そのまま Enter
# ? What's the description of your extension? Sample extension
# ? Initialize a git repository? n # リポジトリとしたい場合は Y を選択
# ? Bundle the source code with webpack? N
# ? Which package manager to use? npm # お好みのものを選んでください
# ? Do you want to open the new folder with Visual Studio Code?
> Open with `code`
これで、HelloWorld 拡張機能の雛形が作られました。
このままF5
を押して拡張機能をデバッグモードで起動させてみます。
HelloWorld 拡張機能が有効になったデバッグ用の VSCode のウインドウが開きます。
この状態で、Ctrl + Shift + p
を押して、コマンドパレットを表示させ、Hello World
と入力するとコマンドがでてきます。
コマンドを実行してみると、右下のテキストボックスにHello World from HelloWorld
が表示されました。
コードを見てみる
拡張機能のエントリポイントは、src/extension.ts 内のactivate
関数になります。
中身は👇です。(実際のコードではコメントが丁寧に入っています。)
▼helloworld/src/extension.ts
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
console.log('Congratulations, your extension "helloworld" is now active!');
let disposable = vscode.commands.registerCommand('helloworld.helloWorld', () => {
vscode.window.showInformationMessage('Hello World from HelloWorld!');
});
context.subscriptions.push(disposable);
}
export function deactivate() {}
コードの中盤あたり👇のdisposable
オブジェクトが Hello World を表示させているコマンドの実態です。
let disposable = vscode.commands.registerCommand('helloworld.helloWorld', () => {
vscode.window.showInformationMessage('Hello World from HelloWorld!');
});
ここでは、vscode.window.showInformationMessage
関数を呼び出すコマンドを作成して、そのコマンドの ID をhelloworld.helloWorld
としています。(showInformationMessage
はVSCode の右下部分にメッセージを表示させるメソッドです)
ここで、サンプルの拡張機能で Hello World を表示させたときのことを思い出してみます。
右下に Hello World が出るのはコマンドパレットに Hello World を入力し、コマンドを実行したときでした。
このようにコマンドパレットから実行可能なコマンドにしている部分の記述が実は package.json
に記載されています。
package.json
の16-23行目に該当の記述があります。👇
▼helloworld/package.json(一部抜粋)
"contributes": {
"commands": [
{
"command": "helloworld.helloWorld",
"title": "Hello World"
}
]
},
この部分で、コマンドのタイトルをHello World
とし、helloworld.helloWorld
をこの拡張機能が提供するコマンドとして登録しています。
このようにして、VSCode の拡張機能では package.json とソースコードに所望の処理を記述して、拡張機能を作っていくことになります。
パッケージ化📦してみる
サンプルの拡張機能の中身を理解できたところで、次はこれを実際に使える形でパッケージ化 📦してみます。
パッケージ化するところについては👇の記事がよくまとまっているので参考にします。
(https://dev.classmethod.jp/articles/easy-vs-code-extension-development/)
※ 今回の記事では拡張機能を公開する部分についてはやったことがないので触れません。
パッケージ化するためには vsce コマンドを使うようです。
とりあえずインストールしておきます。
npm install -g vsce
正しくパッケージ化するために、まずは README を編集します。
ここを編集しないと vsce コマンドを実行したときに以下のエラーが発生してパッケージ化できません(2敗)
ERROR Make sure to edit the README.md file before you package or publish your extension.
# helloworld README
sample extension
README を直したら vsce コマンドを実行して拡張機能をパッケージ化します。
npx vsce package
場合によっては警告がでるので、適切に対応します。
WARNING A 'repository' field is missing from the 'package.json' manifest file.
Do you want to continue? [y/N] y # git リポジトリにしてない場合に発生します
WARNING LICENSE.md, LICENSE.txt or LICENSE not found
Do you want to continue? [y/N] y
完了すると、{拡張機能名}-{バージョン}.vsix
ファイルが出来上がりました。(ちなみにバージョン名や拡張機能名はpackage.json
で管理されています。)
これでパッケージ化は完了です🎉
実際にインストールするときはCtrl + Shift + x
で拡張機能のビューを表示させVSIX からのインストール
を選択し VSCode にインストールします。
おすすめのやり方について話してみる
VSCode の API リファレンス を見ると様々な API の使い方が載っているわけですが、API の呼び出し方を説明するのみで、その機能を使うことで見た目がどう変わるのか、内部で何が起こっているのかをイメージすることは正直厳しいと思います。
例えば、エクスプローラーのようなツリー型のビュー(👇みたいなやつ)を作りたい場合に、膨大な使い方から作り方を探すのは大変だと思います。
そんなときは、VSCode の公式が公開している サンプル集 をみて、動くものから学んでいくのがおすすめです。
ここでは、よく使いがちな機能のサンプルをまとめており、クローンしてきて実際に動かしてみることで中で何が起こっているのか、見た目にどう影響するのかを確認してみることができます。(vim エディタ:memo:を作ってみる ってのもあったりします )
実際に動かしてみて、中身を確認したあと API リファレンス を見ることで理解がしやすくなるんじゃないかと思います。(実際私はそうやって拡張機能の開発をしてます)
また、VSCode の UI 構造やロジック部分の記述に慣れてくると、dockerの拡張機能 や gitlens といった有名な拡張機能のソースコードから、所望の処理の部分を参考にして実装してみるのもいいと思います。
サンプル拡張機能に機能を追加してみる
最後に、紹介したおすすめのやり方でサンプルの拡張機能に👇の機能を追加してみます。
- VSCode の下部ステータスバーに文字を表示させる
- 文字情報は VSCode の設定画面から指定する
ステータスバーに文字を出す部分について調べてみる
ステータスバーに文字を追加している拡張機能をサンプルのリポジトリから探してみます。
👇のコード内、StatusBar
クラスの vscode.StatusBarItem
が該当の部分っぽそうです。
https://github.com/microsoft/vscode-extension-samples/blob/main/vim-sample/src/extension.ts
▼vim-sample/src/extension.ts
class StatusBar {
private _actual: vscode.StatusBarItem;
private _lastText: string;
constructor() {
this._actual = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
this._actual.show();
}
public setText(text: string): void {
if (this._lastText === text) {
return;
}
this._lastText = text;
this._actual.text = this._lastText;
}
}
文字を表示させるにはvscode.StatusBarItem
オブジェクトを作る必要があり、それはvscode.window.createStatusBarItem
関数で、できるようです。
表示させる文字はどのように設定するのかも見てみます。
同じクラスのsetText
メソッド内のコードを見ると、vscode.StatusBarItem
オブジェクトの text プロパティに表示する文字を入れているみたいです。
API リファレンスも見てみます。
createStatusBarItem
関数は このリンク をちょっとスクロールした部分に定義がありました。
StatusBarItem
クラスについてはこちらの リンク に使い方があるみたいです。
text プロパティを見てみると、どうやら特殊な書き方でアイコンも表示させることができることもわかりました。
設定画面から文字を取得する部分について調べてみる
次に設定画面から文字を得る部分を調べてみます。
このコード の👇あたりが設定から値を持ってきているところみたいです。
▼codelens-sample/src/CodelensProvider.ts
if (vscode.workspace.getConfiguration("codelens-sample").get("enableCodeLens", true)) {
getConfigration
関数の リファレンス も見てみると、WorkspaceConfiguration
クラスのインスタンスを返していることがわかり、その部分のリファレンス も見てみるとget
メソッドの使い方も分かってきました。
次に configration とは何かについても調べてみます。
リファレンスを探してみると、package.json に記述する設定みたいです。
参考にした拡張機能の pakcage.json を見ると configration の記述があることも確認できます。
▼codelens-sample/package.json
"configuration": {
"properties": {
"codelens-sample.enableCodeLens": {
"type": "boolean",
"default": true
}
}
}
実装してみる
これで機能追加する上で必要な情報が出揃ったので、実際に機能追加してみます。😎
今回はstatusBarText
という設定を追加してみて、ここの値をステータスバーに出すことにします。(デフォルトの値としてdefault
という文字を入れておきます。)
また、文字の表示はウインドウが立ち上がったときにしたいので、activationEvents
にonStartupFinished
を追加しています。
▼helloworld/package.json(一部抜粋)
"activationEvents": [
"onCommand:helloworld.helloWorld",
"onStartupFinished" // 追加部分(拡張機能が有効化されたときに active 関数を実行する)
],
...
"contributes": {
"commands": [
{
"command": "helloworld.helloWorld",
"title": "Hello World"
}
],
// 追加部分
"configuration": [
{
"type": "object",
"title": "helloworld",
"properties": {
"helloworld.statusBarText": {
"type": "string",
"default": "dafault",
"scope": "resource",
"description": "ステータスバーに表示する文字を設定します"
}
}
}
]
}
extension.ts にはサンプルのコードを見て学んだ API の使い方を参考に、以下を行うコードを追記します。
- ステータスバーを作る
- 文字を設定から読み込む
- ステータスバーの文字として設定する
▼helloworld/src/extension.ts
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
console.log('Congratulations, your extension "helloworld" is now active!');
let disposable = vscode.commands.registerCommand('helloworld.helloWorld', () => {
vscode.window.showInformationMessage('Hello World from HelloWorld!');
});
context.subscriptions.push(disposable);
// 追加部分
const statusBarItem = vscode.window.createStatusBarItem();
statusBarItem.text = vscode.workspace
.getConfiguration('helloworld')
.get('statusBarText', '');
statusBarItem.show();
}
export function deactivate() {}
それではデバッグモードで実行してみます。
値が表示されています🎉
起動したばっかりでは、設定画面で値を指定していないのでデフォルトの文字が表示されています。
思った通りの動作をするか見てみる
次に設定ファイルに値を記入して、表示する文字を変更してみます。
Ctrl + ,
を入力して設定画面を出して、検索ボックスにhelloworld
と入力します。
👇のように設定が出てくるので適当な文字を入れてみます。
この際どうせならアイコンも表示させてみます。(アイコンの一覧)
文字が表示されるのは拡張機能が読み込まれたときなので、再読み込みさせます。
デバッグコンソールを表示している方の VSCode ウインドウから更新ボタンを押して再度デバッグを実行してみます。
下の文字が変更されました!
アイコンもうまく表示できているみたいです!🎉
おわりに
今回は VSCode の拡張機能の作り方と、実際に作るときに参考にしたら良いドキュメントやサンプルコードを紹介しました。
これだけ多くのことができて、自由度が高いところが VSCode が使いやすいソースコードエディタとして知られている理由なんだと思います。
日々の業務で感じている僅かな苛立ちを、自分で拡張機能を作ってみて解決してみてはいかがでしょうか。
※本記事は2022年12月時点の内容です。