LoginSignup
9
6

More than 5 years have passed since last update.

VSCodeのPluginをつくる。

Last updated at Posted at 2018-04-14

初めに

Java9以前のアプリケーションの設定ファイル(Propertiesファイル)は、日本語(2バイトコード)をそのまま利用することができず、'¥u'から始まるコードに置き換える必要がありました。
Java9以前のアプリケーションをメンテナンスする立場になり、VSCodeを利用する上で、毎度、native2asciiするのが億劫で退屈な作業でした。

そこで、VScodeのプラグインでnative2asciiと同等の機能を作ることにしました。

まず、VSCodeのpluginを開発する環境を作ります。環境の作成方法は、@rmaさんの「Visual Studio Code はじめての拡張機能開発」をご覧ください。

方針

自分が調べた範囲では、VSCode上でコマンドをキックすることも、「Propertiesファイルを読んだ」イベントを拾うこともできそうになかったので(誰か情報ください。)、VSCodeのコマンドを利用して手動で変換(文字→コード化)リバース(コード→文字)をする方針で進めました。

コード化

以下のような感じで、文字→コード化を実現しました。

  1. ドキュメントからファイルの文字列を取得。
  2. 1行ごとに繰り返し、日本語を正規表現現で取得し配列を作成。
  3. 2.で作成した配列からコードを作りだし、日本語と、コードの連想配列を作成。
  4. 元の1行にreplaceメソッドで置き換える。
  5. 置き換えた文字列をまとめて新しいドキュメントを作成。
  6. エディタ内のドキュメントを5.で作成したドキュメントで置き換える。

なお、サロゲート文字には対応してません。

function ascii(e: vscode.TextEditor, d: vscode.TextDocument, sel: vscode.Selection[]) {
    console.log(d.getText());
    let text = d.getText();
    let newTest = text.split("\n");
    let replaced = "";
    newTest.forEach(val => {
        let reg = val.match(/([^\x01-\x7E])/g);
        if (reg) {
            let t = reg.map(code => {
                let unicode = code.charCodeAt(0).toString(16);
                return {code, value:`\\u${unicode}`};
            }).reduce( (v,obj) => {
                let {code, value} = obj;
                let reg = new RegExp(code);
                return v.replace(reg, value);
            }, val);
            replaced = `${replaced}${t}\n`; 
        } else {
            replaced = `${replaced}${val}\n`; 
        }
    });
    e.edit((builder)=>{
        if (e) {
            let startPos = e.document.positionAt(0);
            let endPos = e.document.positionAt(text.length);
            let allRange = new vscode.Range(startPos,endPos);
            builder.replace(allRange,replaced);
        }
    });
}

リバース

コード化したものと大差ありません。ユニコードから文字を作成しています。

function reverse(e: vscode.TextEditor, d: vscode.TextDocument, sel: vscode.Selection[]) {
        console.log(d.getText());
        let text = d.getText();
        let newTest = text.split("\n");
        let replaced = "";
        newTest.forEach(val => {
            let reg = val.match(/(\\u[0-9|a-f]{4})/g);
            if (reg) {
                let t = reg.map(unicode => {
                    let codeStrs = unicode.split("\\u");
                    let codePoints = parseInt(codeStrs[1], 16);
                    return {code:`\\${unicode}`, value:String.fromCharCode(codePoints)};
                }).reduce( (v,obj) => {
                    let {code, value} = obj;
                    let reg = new RegExp(code);
                    return v.replace(reg, value);
                }, val);
                replaced = `${replaced}${t}\n`; 
            } else {
                replaced = `${replaced}${val}\n`; 
            }
        });
        e.edit((builder)=>{
            if (e) {
                let startPos = e.document.positionAt(0);
                let endPos = e.document.positionAt(text.length);
                let allRange = new vscode.Range(startPos,endPos);
                builder.replace(allRange,replaced);
            }
        });
}

native2ascii

以下の関数を作成して、上記で作成した関数をコマンドで呼べるようにまとめました。
この関数を、registerCommandで呼び出せば完成です。

function native2ascii() {
    if (!vscode.window.activeTextEditor) {
        vscode.window.showInformationMessage('Open a file first to manipulate text selections');
        return;
    }   
    var items: vscode.QuickPickItem[] = [];

    items.push({ label: "ascii", description: "文字からUnicodeに変換" });
    items.push({ label: "reverse", description: "Unicodeから文字に変換" });

    Window.showQuickPick(items).then((selection) => {
        if (!selection) {
            return;
        }
        let e = Window.activeTextEditor;
        if (e) {
            let d = e.document;
            let sel = e.selections;
            switch (selection.label) {
                case "ascii":
                    ascii(e, d, sel);
                    break;
                case "reverse":
                    reverse(e, d, sel);
                    break;
                default:
           console.log("hum this should not have happend - no selection")
           break;
            }
        }
    });
}

VSCEでVSIXファイルを作る。

作成したpluginをパッケージングをします。
VSCEを利用しました。
以下のコマンドでインストールしました。

npm install -g vsce

インストールできたら、以下のコマンドでパッケージングします。
README.mdを書き換えないとパッケージングに失敗します。

vsce package

ソースコードはGitHubに保存しています。

まとめ

プラグインを作るための環境が充実しており、引っかかるところはなかった(@rmaさんに感謝)
typescriptは初めてだったのですが、ES2015を触っていたので違和感はありませんでした。
むしろ、VScodeの言語サポートがよくできていて、typescriptを本格的に使いたいと思いました。

9
6
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6