giantneco’s blog

技術メモ

Visual Studio Code Extension 拡張を作成してみたメモ

最近 golang を書くのに Visual Studio Code を使っている。 で、使っていると当然不満も出てくるので拡張を書いてみることにした。 TypeScript は書き慣れていないのでその点の苦労はあったが、テンプレートや楽に試す環境ができているので割と楽に作ることができた。

一応欲しい機能は作れたのだが、その機能がすでにあることに気付いたのでとりあえず動くところまでやって終わりにしている。

準備

yoVisual Studio Code Extension のテンプレートがある。

yo を入れていない場合は次のコマンドでインストールする。

npm install -g yo generator-code

テンプレートの生成は次のようにする。

yo code

ウィザードに従って情報を入れればよい。

開発

テンプレート生成で作られたディレクトリに移動して、

code .

で workspace に拡張が入った状態で vscode を起動できる。

基本的には extension.ts をいじることになる。 拡張が読み込まれると activate が呼ばれるので、registerCommandでコマンドとして呼び出す関数を作ったり、イベントのサブスクリプトをしたりする。

デバッグする場合には、f5 で拡張を読み込んだ vscode を起動できる。

Ctrl+Shift+p で拡張で作ったコマンド(テンプレートのままだと Hello World)を指定して起動できる。

ハマったところ

拡張をつくるのは割とスムーズに行ったが、肝心の中身は慣れていない TypeScript を使う必要があったので苦労した。

やりたかったのは QuickPick を使って、ワークスペースのファイルを選択して開くということ。 (繰り返しになるが quickOpen というコマンドで完全に実現されている)

APIVisual Studio Code API Reference

このQuickPickを利用するには、showQuickPick に表示したい文字列のリストを渡すのだが、 リストをつくるのに時間がかかる場合にはThenableで包む。 非同期にやらないとエディタが泊まってしまうだろうし。

Thenable がちょっとハマった部分で、最初Tunableと読んでてググってもわからなかったり、 スペルミスに気付いて検索し直しても googleThen と解釈してやっぱりわからなかったりした。

一方、findFilesワークスペース中のファイルのリストをThenable<Uri[]>の形で得られる。 なので、showQuickPickに渡すにはThenable<Uri[]> -> Thenable<string[]>という変換ができればよいということで、これってファンクターだよねということで Thenable + functor で探したがそれっぽいのは見つからず‥

色々試してみると、.then(f: Uri[] -> string[]) とすればThenable<string>が得られることがわかった。

結局次のようなコードを書くことになった:

        var files = vscode.workspace.findFiles("*");
        vscode.window.showQuickPick(files.then((urls) => {
            return urls.map((url) => {
                return url.toString();
            });
        })).then((selectedItem) => {
            if (selectedItem) {
                var path = vscode.Uri.parse(selectedItem);
                vscode.workspace.openTextDocument(path).then(doc => {
                    vscode.window.showTextDocument(doc);
                })
            }
        });

変数の方とかは vscode 側が表示してくれていたので、実験しながらコードを書くのに非常に役に立った。 やっぱり型はあったほうがいい。

他、比較に === が必要だったりと、普段から JavaScript とか書いていないとしっくり部分があったが、 この点は vscode が優秀でちゃんと指摘してくれたのでなんとかなった。

参考