VSCodeのPluginをつくる。

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

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

まず、VSCodeのpluginを開発する環境を作ります。環境の作成方法は、[@rma](https://qiita.com/rma)さんの「[Visual Studio Code はじめての拡張機能開発](https://qiita.com/rma/items/8c53077d1355ab8fa4c6)」をご覧ください。

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

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

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

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

``` typescript
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);
        }
    });
}
```

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

```typescript
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で呼び出せば完成です。

```typescript
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を利用しました。
以下のコマンドでインストールしました。

```bash
npm install -g vsce
```

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

```bash
vsce package
```

ソースコードは[GitHub](https://github.com/walkmane99/native2ascii_vscode_plugin)に保存しています。

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