こんにちは、CX事業本部 IoT事業部の若槻です。
今回は、編集中のファイルに応じて指定のURLをブラウザで開くVS Code拡張機能を作ってみました。
ユースケースはかなりエッジケースとなりますが、VS Code拡張機能開発の参考までに。
やってみた
プロジェクト作成
generator-codeをグローバルインストールして、yoで使えるようにします。
$ npm install -g generator-code
yoを実行してVS Code拡張用のプロジェクトを作成します。
$ npx yo code
_-----_ ╭──────────────────────────╮
| | │ Welcome to the Visual │
|--(o)--| │ Studio Code Extension │
`---------´ │ generator! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `
? What type of extension do you want to create? New Extension (TypeScript)
? What's the name of your extension? vs-devio-opener
? What's the identifier of your extension? vs-devio-opener
? What's the description of your extension?
? Initialize a git repository? Yes
? Bundle the source code with webpack? Yes
? Which package manager to use? npm
変なおじさんが出てきていくつかオプションを聞かれます。今回は上記のようにしました。
実行を完了すると、指定したエクステンション名(vs-devio-opener
)のプロジェクトディレクトリが作成できました。
拡張機能のデバッグ方法
拡張機能のデバッグ方法を確認してみます。
まず初期化後に既定で作成されたファイル内容を見てみます。
extension.ts
では、拡張機能で実際に実行される処理を記述します。実行するとHello World from vs-devio-opener!
というメッセージを表示する処理をvs-devio-opener.helloWorld
というコマンドとして登録していますね。
src/extension.ts
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
// This method is called when your extension is activated
// Your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
// Use the console to output diagnostic information (console.log) and errors (console.error)
// This line of code will only be executed once when your extension is activated
console.log(
'Congratulations, your extension "vs-devio-opener" is now active!'
);
// The command has been defined in the package.json file
// Now provide the implementation of the command with registerCommand
// The commandId parameter must match the command field in package.json
let disposable = vscode.commands.registerCommand(
'vs-devio-opener.helloWorld',
() => {
// The code you place here will be executed every time your command is executed
// Display a message box to the user
vscode.window.showInformationMessage('Hello World from vs-devio-opener!');
}
);
context.subscriptions.push(disposable);
}
// This method is called when your extension is deactivated
export function deactivate() {}
package.json
では、extension.ts
で登録したコマンドをHello World
というタイトルで実行できるようにしています。
package.json(抜粋)
{
"activationEvents": [
"onCommand:vs-devio-opener.helloWorld"
],
"main": "./dist/extension.js",
"contributes": {
"commands": [
{
"command": "vs-devio-opener.helloWorld",
"title": "Hello World"
}
]
},
}
上述の拡張機能をデバッグ実行してみます。
VS Codeのデバッガーで[Run Extension]をクリック。
Command Paletteで[Run Extension]を選択。
すると別ウィンドウが開くので、Command PaletteでHello World
を実行します。
通知欄にメッセージが表示されました。デバッグで動かせましたね。
実装
今回の目的の機能を実装していきます。
必要なモジュールをインストールします。
npm i open
extension.ts
を修正します。編集中のファイルと同じパスにあるconfig.json
から取得したスラッグを使用して記事URLを開く処理を記載します。
src/extension.ts
import * as vscode from 'vscode';
import * as open from 'open';
import * as fs from 'fs';
export function activate(context: vscode.ExtensionContext) {
var disposable = vscode.commands.registerCommand(
'vscode-context.openDevio',
() => {
const currentFilePath = vscode.window.activeTextEditor?.document.fileName;
if (currentFilePath) {
const splitted = currentFilePath?.split('/');
splitted.pop();
splitted.push('config.json');
const joined = splitted.join('/');
const config = JSON.parse(fs.readFileSync(joined, 'utf8'));
const postName = config.postName;
const url = `https://dev.classmethod.jp/articles/${postName}`;
vscode.window.showInformationMessage(url);
open(url);
}
}
);
context.subscriptions.push(disposable);
}
package.json
を修正します。コマンドを実行するための項目をコンテキストメニューに追加します。"when": "editorFocus"
によりエディターにフォーカスが当たっている時にのみコンテキストメニューに追加されます。
package.json(抜粋)
"activationEvents": [
"onCommand:vscode-context.openDevio"
],
"main": "./dist/extension.js",
"contributes": {
"commands": [
{
"command": "vscode-context.openDevio",
"title": "Open DevIO"
}
],
"menus": {
"editor/context": [
{
"when": "editorFocus",
"command": "vscode-context.openDevio",
"group": "myGroup@1"
}
]
}
}
}
デバッガーで動かして問題なければ実装は完了です。
VS Code拡張として利用する
実装した拡張機能を実際にVS Codeで利用してみます。
次のコマンドを実行します。
npx vsce package
するとプロジェクトフォルダ内にvsixファイルが生成されます。
$ ls vs-devio-opener-0.0.1.vsix
vs-devio-opener-0.0.1.vsix
[install from VSIX]で生成したvsixファイルを読み込みます。
これによりファイルエディターがアクティブ時にコンテキストメニューにコマンドが追加されるようになりました。
ちなみに同パスに下記のファイルが作成済みの場合。
config.json
{
"postName": "create-a-vs-code-extension-that-opens-a-specified-url-in-a-browser-according-to-the-file-being-edited",
"title": "編集中のファイルに応じて指定のURLをブラウザで開くVS Code拡張機能を作る",
"createdAt": "2022/11/11T22:57:17",
"updatedAt": "2022/11/11T22:57:17"
}
コマンドを実行すると、`https://dev.classmethod.jp/articles/create-a-vs-code-extension-that-opens-a-specified-url-in-a-browser-according-to-the-file-being-edited/`が自動で開かれました。
これで期待通りのVS Code拡張を作ることができました!
参考
- Vscode拡張機能を開発してみた
- VSCode Extensions(拡張機能) 自作入門 〜VSCodeにおみくじ機能を追加する〜 - Qiita
- [TypeScript] Axiosのtry/catchでの例外オブジェクトを型付けする | DevelopersIO
以上