初めに
Java9以前のアプリケーションの設定ファイル(Propertiesファイル)は、日本語(2バイトコード)をそのまま利用することができず、'¥u'から始まるコードに置き換える必要がありました。
Java9以前のアプリケーションをメンテナンスする立場になり、VSCodeを利用する上で、毎度、native2asciiするのが億劫で退屈な作業でした。
そこで、VScodeのプラグインでnative2asciiと同等の機能を作ることにしました。
まず、VSCodeのpluginを開発する環境を作ります。環境の作成方法は、@rmaさんの「Visual Studio Code はじめての拡張機能開発」をご覧ください。
方針
自分が調べた範囲では、VSCode上でコマンドをキックすることも、「Propertiesファイルを読んだ」イベントを拾うこともできそうになかったので(誰か情報ください。)、VSCodeのコマンドを利用して手動で変換(文字→コード化)リバース(コード→文字)をする方針で進めました。
コード化
以下のような感じで、文字→コード化を実現しました。
- ドキュメントからファイルの文字列を取得。
- 1行ごとに繰り返し、日本語を正規表現現で取得し配列を作成。
- 2.で作成した配列からコードを作りだし、日本語と、コードの連想配列を作成。
- 元の1行にreplaceメソッドで置き換える。
- 置き換えた文字列をまとめて新しいドキュメントを作成。
- エディタ内のドキュメントを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を本格的に使いたいと思いました。