初書:2021/04/28
mac : 11.2.3
vscode : 1.55.1
前書き
まだtypescriptを記述できない頃に試した拡張機能開発
今回再び拡張機能を作ろうと思ったのだが、前回の記事を見様見真似で書いても上手くいかないことがあり、
作成している言語も若干違うし改めてメモっていこうという次第である。
前提
node.jsとnpm、yo、generator-codeはインストール済みとする。
(yo、generator-codeは前回の記事でインストールしているので、そちら参照)
環境の作成
作成したいフォルダの下で、下記コマンドを実行する。
% yo code
以降出てくる質問はtypescriptを選択する以外は前回と同じ
前回で知らなかったことメモ
この先も基本的には前回の記事で一通り作成できるのだが、それ以外にも気づいたこととかをメモしていく。
package.jsonのactivationEvents
前回何も考えずにとりあえず置き換える精神で置いた気がするが、これ意外に重要だった。
参考:Visual Studio Code 拡張機能のアクティベート activationEvents
これは、拡張機能を起動するタイミングを記述するものらしい。
最初から全ての拡張機能を読み込んでいてはvscodeも重たくなるよね、ということで任意に読み込むタイミングを制御できる。
前回はコマンドそのまま記述したが、あれは「そのコマンドが実行されたら拡張機能を読み込む」という意味となる
つまり、
コマンドパレットからコマンドを実行
→拡張機能のactivateが呼ばれる
→コマンドが実行される
という感じになる。
これは記述次第でタイミングを変更することができ、また複数のタイミングを指定可能。
例えば
*
だとvscodeが起動した時(あまり使うべきではないが)
onLanguage:typescript
だと.tsファイルが開いた時
onCommand:xxxx
だとxxxxコマンドが実行された時
などという意味になる。
まぁ、今回もコマンド実行時に起動させればいい拡張機能なのだが。
npm run compileとnpm run watch
typescriptは直接実行できないので、javascriptへコンパイルする必要がある。
typescriptを選択すると、上記二つのコマンドがpackage.jsonに追加されるので、特に設定せずとも利用可能。
・・・なのだが、テスト実行するときに勝手にコンパイルが走るので、特に使う機会がない気がする。
あとこれら実行しても一見変化がないのだが、/srcのファイルが/outに出力されていた(tsconfigに書いてある)
ユーザー情報の保存
よくみるsettings.jsonのやつ。
参考:VSCodeの拡張機能開発でユーザー設定を変えながら単体テストする - Qiita
設定する場所はpackage.json
のcontributes
の中
"configuration":[
{
"title": "package_title", // ユーザー設定を開いた時の左側のリストに出てくる名前
"properties": {
"package_title_2.variable" : { // settings.jsonで指定する時の名前
"type" : "string", // 保存形式
"default" : "", // デフォルト値
"description": "description" // 説明。ユーザー設定の項目とかsettings.jsonでカーソル置くと出てくる
}
}
}
]
(package_title_2.variable
とそれぞれの値は変更可能。またpackage_title
とpackage_title_2
は重複可能)
コード内で取り出すときは、
vscode.workspace.getConfiguration("package_title_2").variable;
という感じで取り出せる。variableのところは流石に予測変換してくれないが。
メッセージを表示し、ついでにボタンも表示する
右下に出てくるあれ。
vscode.window.showInformationMessage("メッセージの表示");
これで表示できる。
エラー表示は、vscode.window.showErrorMessage
を使えば同様に可能。
更に、メッセージにボタンを追加して表示する場合は、
vscode.window.showInformationMessage("メッセージの表示","了解").then(e => {
if(e === "了解"){
// 動作
}
});
という風にすれば、了解
というボタンが増え、押すとthen以降が呼ばれる。
その時に引数に押されたボタンの表示内容が入るので、それに応じて分岐する。
(ちなみに×で消してもthenが呼ばれる。その際eにはundefinedが入っている)
ちなみに・・・
自動的に閉じる方法を調べたが存在していないらしい。
自動的に閉じるには、setStatusBarMessage
を使うしかない模様。(左下のバーに表示されるので正直気付かないが)
Auto dismiss messages · Issue #2732 · microsoft/vscode
urlを開く
urlからブラウザを開ける方法。
vscode.env.openExternal(vscode.Uri.parse("url"));
ちなみに昔のバージョンに対応する場合は、別のアプローチが必要。
javascript - How to open browser from Visual Studio Code API - Stack Overflow
データストレージに保存
settings.json
とは別で、内部データを保存しておきたい時に使えるもの。
ワークスペース、グローバルスペースに保存する方法があり、それぞれキーと値の組み合わせで保存するものと、ファイルに書き込む方法がある。
ちなみにここではキーと値の組み合わせであるglobalState
しか説明しない(なぜならglobalStateしか使っていないから)が、ファイルに書き込むタイプの一つであるstoragePathが非推奨になっていたので、こちら側は別で試してみる必要がありそう。
とりあえずAPIドキュメントを見てみると、
globalState: Memento & {setKeysForSync}
A memento object that stores state independent of the current opened workspace.
だそう。使い方とか一切分からないのだが、このAPIドキュメントはどうやって読むのか未だに謎。
ということで他で調べてみる。調べた結果:
保存する場合はvscode.ExtensionContext.globalState.update(key,value)
、読み込む場合はvscode.ExtensionContext.globalState.get<string>(key);
を使用するらしい。ちなみにvscode.ExtensionContext
はactivate
の引数。
export function activate(context: vscode.ExtensionContext) {
let savedata = context.globalState.get<number>("loadtime") ?? 0; // 初回読み込みはundefinedになる。保存されていないから。
savedata++;
context.globalState.update("loadtime",savedata);
}
これは拡張機能がアクティブになった回数を記録するコード。例文なので必要性は考えていない。
Common Capabilities | Visual Studio Code Extension API
公開してみる
自分用としてやる分は前回やったので、今回はテスト含めて実際に公開を試みてみる。
その時のメモ
使ってないパッケージをアンインストールする(手動)
手動です。package.jsonの"dependencies"欄を確認し、使用していないパッケージがあればアンインストール。
拡張機能はファイルサイズが大きくなることが好ましくなく、vsixファイルを作成するときにファイル数が多いとWARNINGが出るのでやっておく。
esbuildを使う
圧縮系操作。上のWARNINGで提示してきたので使ってみる。
Bundling Extensions | Visual Studio Code Extension API
インストール
まずはインストール
% npm i --save-dev esbuild
package.jsonの追加
次にpackage.jsonのscriptに以下を追加(変更)する。元々あったscriptsの中身は消していい。残してもいいけど。
"scripts": {
"vscode:prepublish": "npm run -S esbuild-base -- --minify",
"esbuild-base": "esbuild ./src/extension.ts --bundle --outfile=dist/main.js --external:vscode --format=cjs --platform=node",
"esbuild": "npm run -S esbuild-base -- --sourcemap",
"esbuild-watch": "npm run -S esbuild-base -- --sourcemap --watch",
"test-compile": "tsc -p ./"
},
(outfileが下のリンクと異なるので注意。)
とりあえずnpm run esbuild
を叩いてみると、import * as xx from "xx";
を使ういくつかでエラーがあった。
tsconfig.jsonに"esModuleInterop" : true
をつけ、いくつか記述方法を変えればいいらしいが、詳しくは他の方に任せる。
esModuleInterop オプションの必要性について - Qiita
次にmain
の書き換え。出力先が変化したので、こちらもそれに対応する必要がある。
- "main": "./out/extension.js",
+ "main": "./dist/main.js",
.vscodeignoreの変更
次に、.vscodeignore
を変更する必要がある。これはパッケージ化する時に除外するファイルを選択する、.gitignore
のvscode版
今回不要になるのは、node_modules
とout/
ので、それぞれ追記する。
デバッグの修正
パッケージ化はこれで問題ないのだが、ここで問題になるのがデバッグ側。
普段使う▶︎で実行しても上手く行かなくなる。1
これは、普段は実行時にコンパイラが走っているのだが、これで生成されたファイル群はoutディレクトリの中に生成され、package.json
のmain
に指定されたファイルではないからである。
これを一致させる方法の一つとして、実行時に走るコンパイラをesbuild
に変更する。
まずコマンドパレット(com + shift + P)から、タスクの構成「Tasks : configure task」を選択し、npm: esbuild
を選択する。
すると、.vscode/tasks.json
に何かが追加される。
その後、.vscode/launch.json
を開き、configurations
の``"name": "Run Extension"側の
preLaunchTask`を`npm: esbuild`に書き換える。
これで無事にデバッグ側のmain.jsを元にデバッグされるようになる。
アイコンの登録
拡張機能を公開するなら、やはりアイコンくらいは設定しておきたい。
ということでアイコンを作成する。作成方法は任せる。サイズは128×128のpngである必要があるらしい。
ちなみに自分は以下のサイトを有り難く使わせていただいた。
アプリアイコン風デカ文字ロゴ- - つぶデコジェネレーターメーカー
作成したら、ディレクトリに置いておき、package.jsonに以下を追加する。
"icon" : "icon.png",
この際、アイコンは、HTTPS プロトコルのリポジトリがこの package.json で指定されている必要があります。
という警告が出るのだが、無視しても構わない模様。ただ、若干気になる。
Azure DevOps Servicesに登録する
拡張機能を公開するにはAzure DevOps Servicesに登録する必要がある。
なおログインはマイクロソフトアカウントオンリー2
登録できたら、右上の人のアイコン(user settings)からPersonal Access Tokens
を選択
New Token
を選択し、パーソナルアクセストークンを生成する。
Nameは任意、OrganizationはAllに、Expirationは任意、Scopesはcustomにして、Marketplace(ない場合はShow all scopesを選択)のManage
をチェックし、create
これでパーソナルアクセストークンが生成された。
次に管理ページにアクセスし、こちらもアカウント登録。
Nameは公開名、IDはユニークなIDを作成し、他は任意の模様。
アカウントが作成できたら、次はvsceでログインをする。
% vsce login <publisher name>
※<publisher name>はおそらく管理ページで作成したIDに相当すると思われるが、NameとIDを同じにしてしまったためどちらか不明。誰か判明したらコメントください。
Personal Access Token for publisher
と表示されれば、先ほど取得したパーソナルアクセストークンを入力。
これで準備は完了。ちなみにAzure DevOps Servicesへの登録方法は以下に記載されているものを参考にしている。
拡張機能の公開| Visual Studio Code Extension API
公開する
あとはpackage.json
の特にversionとか.vscodeignore
とかREADME
とかCHANGELOG.md
をしっかり書いたかとかを確認して、大丈夫そうなら実際に公開する
% vsce publish
DONE Published xxx
と出れば無事公開完了。反映には少し時間がかかるので少し待ってから確認。(管理ページの方は即反映されている)
更新する
公開の時と同じ
% vsce publish x.x.x
x.x.x
には設定するバージョンか、もしくはmajor
、minor
、patch
を指定することも可能。
終わりに
他にも見つけたら追加していく予定。(次拡張機能を開発するのはいつになるやら・・・。)
APIが結構ややこしいので作成に手間取るが、意外に楽しい。
ちなみに今回開発したのはこちら→ 【vscode・qiita】vscodeからqiitaに投稿する拡張機能を作ってみた - Qiita
参考サイト
Visual Studio Code API コマンド編 -vscode.commands-
VSCodeデバッグ前に任意のタスクを実行させる - SE(たぶん)の雑感記
VSCode拡張機能の開発~リリース(公開)編~|hatena75|note
APIドキュメント:VS Code API | Visual Studio Code Extension API