2021.7.15
VSCodeでJISコード(ISO-2022-JP)を使いたい!拡張機能の実装方法
20新卒の岩谷です。
以前、JISコード(ISO-2022-JP)で書かれたHTMLメルマガのコードのチェックを行ったのですが、VSCodeはJISコードに対応しておらず、別のエディタを利用する必要があり、少し不便に感じました。
そこで、VSCodeでもJISコードを扱えるように拡張機能を作成してみました。
今回は、その拡張機能の実装方法についてまとめていきたいと思います。
はじめに
拡張機能の開発、デバッグ、公開などの方法についてはインターネット上に多数の記事が公開されていますので、詳しくはそちらを参照いただければと思います。
今回の拡張機能の開発はTypeScriptで行いました。開発にはVSCode APIを利用します。
作成した拡張機能のソースは、https://github.com/YouAreNotDefined/ConvertToISO-2022-JPです。
拡張機能の設定
開発の前に以下のコマンドで雛形を作成します。
npm i yo generator-code
yo code
ファイルが作成されるので修正していきます。拡張機能の設定にはpackage.jsonを以下のように修正します。コメントアウトで説明を入れています。
{
"name": "converttoiso-2022-jp",
"displayName": "ConvertToISO-2022-JP",
"description": "",
"publisher": "kazuki",
"version": "0.0.1",
"repository": {
"type": "git",
"url": "https://github.com/YouAreNotDefined/ConvertToISO-2022-JP"
},
"engines": {
"vscode": "^1.46.0"
},
// 拡張機能のカテゴリを設定します。カテゴリは設定できる値が決まっているので、リファレンスを見ながら決めていきます。
"categories": [
"Formatters",
"Snippets",
"Linters",
"Other"
],
// 検索されるときに見つけやすくなるように関連するキーワードを5つまで設定します
"keywords": [
"ISO-2022-JP",
"ISO2022JP",
"JIS",
"character encoding",
"encoding",
"encode",
"decode",
"decoding"
],
// 拡張機能が起動する際の設定を書きます。今回はonCommandで割り当てられている値が呼び出された時に起動するようにしています
"activationEvents": [
"onCommand:convertISO2022JP.command"
],
// 拡張機能のエントリーファイルです
"main": "./out/extension.js",
"contributes": {
// コマンドパレットで”Convert ISO-2022-JP”を実行した際にactivationEventsで設定した値が呼び出されるように設定します
"commands": [
{
"command": "convertISO2022JP.command",
"title": "Convert ISO-2022-JP"
}
]
},
// 略
}
詳しくは以下をご参照ください。
https://code.visualstudio.com/api/references/extension-manifest
コーディング
src内のextension.tsを修正していきます。このextension.tsが拡張機能のエントリーです。
今回はファイルを3つに分けて書き、extension.ts内でimportして実装します。
また、JISコードを変換するためにencoding-japaneseというモジュールをインストールします。
npm i encoding-japanese
以下がソースコードになります。コメントアウトで説明を入れています。
・extension.ts
import * as vscode from 'vscode'; // VSCodeのモジュールをインポート
import { Model } from './model'; //Modelクラスインポート
import { StatusBar } from './setStatusBar'; //statusBarクラスインポート
// activateメソッド : 拡張機能が起動したときに実行されます。
export function activate(context: vscode.ExtensionContext) {
StatusBar.init(); //statusBarクラスのinitメソッド
// package.jsonのactivationEventsで設定したコマンドを登録します
let disposable = vscode.commands.registerCommand('convertISO2022JP.command', () => {
const editor = vscode.window.activeTextEditor; //VSCodeで開いているタブ(エディタ)を取得
if (!editor) return;
// isAvailableメソッドで変換可能な文字コードか判定。OKならconvertFileを実行
if (Model.isAvailable('JIS')) Model.convertFile();
else if (Model.isAvailable('UTF8')) Model.convertFile('JIS');
else vscode.window.showInformationMessage('This character code is disabled'); //右下の通知にメッセージを表示させます
});
//disposable変数に格納したコマンドをpush。拡張機能が使用されなくなったときにリソースの開放をします。
context.subscriptions.push(disposable);
}
//activateメソッドの逆
export function deactivate() {}
・model.ts
import * as vscode from 'vscode';
import { convert, detect, codeToString, Encoding } from "encoding-japanese"; //encoding-japaneseモジュールのインポート
import { readFileSync, writeFileSync } from "fs"; //fsモジュールのインストール
import { StatusBar } from './setStatusBar';
export class Model {
private static get readFile() {
//開いているファイルを読み込む
return readFileSync(this.fileUri!);
}
private static get charCode() {
//detect関数でファイルの文字コードを取得
return detect(this.readFile).toString();
}
private static get fileUri() {
//開いているファイルのURIを取得
return vscode.window.activeTextEditor?.document.uri.fsPath;
}
static isAvailable(charCode: Encoding) {
// 文字コード引数(JISかutf8)と同じならtrue、違うならfalse
return this.charCode === charCode ? true : false;
}
// 引数toにデフォルトで'UNICODE'を設定
static convertFile(to: Encoding = 'UNICODE') {
if (!this.fileUri) return;
StatusBar.encoding();
// convert関数で読み込んだファイルをtoで指定した文字コードの配列に変換
const charArray = convert(this.readFile, {
to,
// from: 'AUTO'で自動で元の文字コードを判別します
from: 'AUTO'
});
// 配列を文字列に変換
const text = codeToString(charArray);
// 変換後の文字列を書き込みます
writeFileSync(this.fileUri, text);
StatusBar.notEncoding();
}
}
・setStatusBar.ts
import * as vscode from 'vscode';
export class StatusBar {
private static _statusBarItem: vscode.StatusBarItem;
private static get statusBarItem() {
if (!StatusBar._statusBarItem) {
//createStatusBarItemでエディタ下に表示されるステータスバーを作成します。StatusBarAlignment.Rightで右下に並べます。200は優先順位で大きい値にするほど左側に表示されます。
StatusBar._statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 200);
this.statusBarItem.color = '#ffffff';
this.statusBarItem.show();
}
return StatusBar._statusBarItem;
}
static init() {
//package.jsonで指定したコマンドをステータスバーにも設定します。これでステータスバーをクリック後に拡張機能が実行されます
this.statusBarItem.command = 'convertISO2022JP.command';
StatusBar.encoding();
setTimeout(() => {
StatusBar.notEncoding();
}, 1000);
}
static encoding() {
//変換中のステータスバーの表示を設定します
StatusBar.statusBarItem.text = 'Converting...';
}
static notEncoding() {
//通常時のステータスバーの表示を設定します
StatusBar.statusBarItem.text = 'Convert ISO-2022-JP';
}
static dispose() {
//ステータスバーの破棄とリソースの開放を行います
StatusBar.statusBarItem.dispose();
}
}
おわりに
以上で実装は終わりになります。
あとは、vsceコマンドでパッケージングを行い、マーケットプレイスに公開するか、パッケージファイルを書き出してインストールするかになります。
公開、パッケージングの方法については紹介されている記事がありますので、ここでは省きます。
少しでも参考になれば幸いです。
最後までお読みいただきありがとうございました。
この記事を書いた人
岩谷 和紀
EMCカンパニー所属2020年入社。業務ではECサイトの運用コーダー。 北海道出身でサッカーと甘いものと北海道が好き。