VSCodeでマクロ(スクリプト)を実現する方法【拡張作成編】

この記事は公開から4年以上経過しています。

有償/無償問わず最強のテキストエディタVisualStudioCodeに唯一足りないスクリプトマクロ機能を簡単に実現する方法。

手っ取り早く簡単に秀丸マクロやExcelVBAのようなマクロ機能を使いたい場合はVSCode Macros拡張がオススメです。
作成したマクロは拡張開発同等の実装(サブセット)なので後から拡張への転用も可能!拡張開発の入門としても最適です。

独自コマンドを用いたマクロ拡張などもありますが、独自仕様に学習コストをかけるよりも、初心者からプロまで幅広く使えるプログラミング言語JavaScriptで拡張の作り方を覚えたほうが、効率が良く汎用的で応用もきくため、今回は「TSV形式テキストの選択範囲をC#のタプル型の配列リスト定義に変換する」簡単なVSCode拡張を例に作り方を紹介します。

ちなみに、記事で紹介するコードは私がMicrosoft製テストケース生成ツールPICTでファイル出力したペアワイズテストケースから自動単体テスト用テストデータを生成するために即席で作成したものです。

本記事の目的は、一見ハードルが高そうなVSCode拡張開発が簡単にできることの紹介です。作成したVSCode拡張をマーケットプレイスに公開したり再配布する場合には、他にも色々な知識や設定が必要になります。

開発手順

本例はLinuxのコンソールで説明していますが、WindowsのコマンドプロンプトやGitBashなどでも同様です。

予めNode.jsが導入(インストール)されている必要があります。

  1. VSCode拡張を作成するために必要なyo(YEOMAN)generator-codevsceパッケージを、以下のnpmコマンドでグローバルインストールする。※要root(管理者)権限。

    npm install -g yo generator-code vsce
  2. 適当なVSCode拡張作成用の作業ディレクトリを作成してそこにカレントディレクトリを移動して、以下のコマンドでVSCode拡張のテンプレート生成ウィザードを起動する。

    yo code

    または

    npx yo code
  3. ここで作成するVSCode拡張のウィザード設定は、以下のとおり(今回は分かりやすいようにJavaScriptベースで作成)。

    file

  4. ウィザードが完了すると作業用ディレクトリ内に拡張ID名のディレクトリが作成されるので、それをVSCodeでを開く(※中のファイルではなくディレクトリを開く)。

    file

  5. VSCodeのエクスプローラツリーから拡張の本体ソースextension.jsを開き、以下のように編集(コピー&ペースト)する。

    // The module 'vscode' contains the VS Code extensibility API
    // Import the module and reference it with the alias vscode in your code below
    const vscode = require('vscode');
    
    // this method is called when your extension is activated
    // your extension is activated the very first time the command is executed
    
    /**
     * @param {vscode.ExtensionContext} context
     */
    function activate(context) {
    
        // The command has been defined in the package.json file
        // Now provide the implementation of the command with  registerCommand
        // The commandId parameter must match the command field in package.json
        let disposable = vscode.commands.registerCommand('tsv2cs.run', function () {
            // The code you place here will be executed every time your command is executed
            // ↓ここから拡張の自前ロジック
            // アクティブなエディタを取得
            const editor = vscode.window.activeTextEditor;
            if (editor) {
                // エディタのドキュメント/選択範囲/選択テキストを取得
                const document = editor.document;
                const selection = editor.selection;
                const selectedText = document.getText(selection);
                // ドキュメントのEOLを取得
                const documentEOL = {
                    1: '\n',
                    2: '\r\n'
                } [document.eol];
    
                // 行列挙用のジェネレーター関数
                const getLine = function* (text) {
                    let line = '';
                    for (const s of text) {
                        if (!documentEOL.includes(s))
                            line += s;
                        else {
                            yield line;
                            line = '';
                        }
                    }
                    return line;
                };
    
                // TSVをC#のタプル形式に変換
                const lines = getLine(selectedText);
                let replaced = '';
                let lineSuffix = '';
                while (1) {
                    const line = lines.next();
                    if (line.value !== '')
                        replaced += lineSuffix + '(' + line.value.replace(/([^\t]+)/g, '"$1"').replace(/\t/g, ',') + ')';
                    if (!line.done)
                        lineSuffix = ',' + documentEOL;
                    else
                        break;
                }
    
                // エディタの選択範囲のテキストを変換後のテキストに置換
                editor.edit(editBuilder => {
                    editBuilder.replace(selection, replaced);
                });
            }
            // ↑ここまで拡張の自前ロジック
        });
    
        context.subscriptions.push(disposable);
    }
    exports.activate = activate;
    
    // this method is called when your extension is deactivated
    function deactivate() {}
    
    module.exports = {
        activate,
        deactivate
    }
  6. VSCodeのエクスプローラツリーからパッケージ情報package.jsonを開き、以下の設定を編集する。

    • /publisherに、拡張の発行者名(任意の名称)を設定する(指定しないとvsce実行時にエラーになる)。
    • /engines/vscodeに、拡張と互換性があるVSCodeのバージョンを設定する(例は1.50.0以上が対象)。
    • /activationEvents/onCommandに、onCommand:+extension.jsvscode.commands.registerCommand()のコマンド名を設定する。
    • /contributes/commands/commandに、extension.jsvscode.commands.registerCommand()で第一引数に指定したコマンド名を設定する。
    • contributes/commands/titleに、コマンドパレットから実行する際のコマンド名を設定する。

    file

拡張の実行とデバッグ

  1. VSCode上でF5キーを押下して拡張機能開発ホストモードのVSCodeを起動する。

  2. 拡張機能開発ホストモードのVSCodeに以下の置換サンプルテキストを入力し、全文を選択状態にしておく。

    foo⇥bar
    baz⇥qux

    ※単語区切りの「⇥」は、TABコード(TAB文字)

  3. 拡張機能開発ホストモードのVSCodeでコマンドパレット(F1)を開いて開発手順3で入力した拡張IDtsv2csを選択して、デバッグモードで拡張を実行する(ブレークポイントを設定してデバッグが可能だが、エディットコンティニューではないためデバッグ中にソースを編集した場合はデバッグのリスタートが必要)。

    拡張実行前
    file

    拡張実行後
    file

VSIXファイルの作成とインストール

  1. README.mdを適宜編集する。未編集のままではvsce実行時にエラーになるので、とりあえず今回は先頭の拡張のタイトルだけ残して全て削除。

  2. 以下のコマンドを実行して、VSCode拡張パッケージファイル(VSIX)を作成する(カレントに作成される)。

    vsce package

    または

    npx vsce package

    以下のようにpackage.jsonにリポジトリ項目がないと言われるが、今回はローカルインストール用なのでyでスキップする。

    WARNING  A 'repository' field is missing from the 'package.json' manifest file.
    Do you want to continue? [y/N] y
  3. 最後にVSCodeのコマンドパレット(F1)からExtensions: Install from VSIX...を選択して作成した拡張をインストールすれば終了。下図のようにインストール済拡張に自作拡張が表示されるので、今後は自作の拡張コマンドがいつでも実行できるようになる。

    file

私自身はVSCode拡張の作成に若干ハードルが高い印象をもっていましたが、実際作ってみると、とても簡単でした。面倒な単調作業はどんどんコンピュータに任せて、ガンガン生産性を上げて楽に仕事ができるようにしていきましょう。

参考ウェブサイトなど

以上です。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする