Edited at

VSCodeのPluginをつくる。

More than 1 year has passed since last update.


初めに

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を本格的に使いたいと思いました。