#TL;DR
VSCode拡張機能おすすめ記事がバズる度に**「確かに便利なんだけど 自分が求めているのと違うんだよね〜」**となる人向けに
いっそのこと自分で拡張機能つくろうぜ👀
というのがこの記事の趣旨。
そしてVSCodeの拡張機能は思っている以上に簡単に作れるってことを全人類に知って欲しい!!
(拡張機能開発を活発化してIDE最強の座を揺るぎないものにするのが目ry Jetbrainsは高いよ 重いよ)
また、JS初心者のいい題材にもなると思う!?
例題としてステータスバーにSlack通知ボタンを配置して、即座にコード(任意のメッセージ)を送信できる拡張機能を挙げる。
#開発環境構築
VSCodeが提供しているAPIを使うことでわりかし簡単にいじれる。また、面倒な開発環境も数コマンドで整ってしまう。
(Node.js環境構築済み前提 まだな人はMacならHomebrewからのnodenv経由 WindowsならWSLにてUbuntuからのnodenv経由がおすすめ 詳細はry)
開発言語は、JavaScriptまたはTypeScriptが使える。
公式ドキュメント
https://code.visualstudio.com/api
####必要なツールの導入
#npm派閥
npm install -g yo generator-code
#yarn派閥
yarn global add yo generator-code
####プロジェクトの雛形生成
yo code
上記コマンドを実行すると対話ツールが起動し、プロジェクトの雛形ディレクトリが生成される。
_-----_ ╭──────────────────────────╮
| | │ Welcome to the Visual │
|--(o)--| │ Studio Code Extension │
`---------´ │ generator! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `
? What type of extension do you want to create? (Use arrow keys)
❯ New Extension (TypeScript)
New Extension (JavaScript)
New Color Theme
New Language Support
New Code Snippets
New Keymap
New Extension Pack
(Move up and down to reveal more choices)
今回はJSで拡張機能を作りたいので
New Extension (JavaScript)
カーソルキー⬆️⬇️で選択してエンター
以降の設問も同様に対応する
拡張機能の名前設定ここでは**「hoge-extension」**とする。
これがそのままディレクトリ名になる
? What's the name of your extension? hoge-extension
あとの設問はとりあえずそのまま
最後の質問のnpm/yarnは適時選択
? What type of extension do you want to create? New Extension (JavaScript)
? What's the name of your extension? hoge-extension
? What's the identifier of your extension? hoge-extension
? What's the description of your extension?
? Enable JavaScript type checking in 'jsconfig.json'? No
? Initialize a git repository? Yes
? Which package manager to use?
npm
❯ yarn
#実装
処理は基本的にプロジェクト直下にあるextension.jsが起点になる。
既にHello Wordをするコマンドの実装がサンプルとして書かれているのでそれを元に改造する。
(サンプルコードについては公式のチュートリアルを参照 https://code.visualstudio.com/api/get-started/your-first-extension)
今回のソースコードはこちら https://github.com/delmontz/hello-vscode
const vscode = require('vscode');
const request = require('request');
function activate(context) {
//任意のコマンドID
const cmd_id = 'slack_cmd';
//コマンドの登録
// 第一引数:コマンドID 第二引数:コールバック
const cmd = vscode.commands.registerCommand(cmd_id, () => {
vscode.window.showQuickPick(['自分で入力', 'ファイル内容送信', '選択部分を送信']).then((selected) => {
//アクティブなエディタのドキュメントを取得
const activeEditor = vscode.window.activeTextEditor;
const doc = activeEditor && activeEditor.document;
if(selected === '自分で入力'){
//入力欄を表示させる
vscode.window.showInputBox({
prompt: 'Slackへ通知します',
placeHolder: '入力してね'
}).then((value) => {
sendSlack(value);
});
}else if(selected === 'ファイル内容送信'){
//エディターの内容を読み込んで送信
sendSlack(doc.getText());
}else if(selected === '選択部分を送信'){
//選択範囲を取得
const ref = activeEditor.selection;
sendSlack(doc.getText(ref));
}
});
});
context.subscriptions.push(cmd);
// ステータバーにボタン登録
// 第一引数:表示位置 第二引数:優先度
const button = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);
button.command = cmd_id;
button.text = 'slackで送信';
context.subscriptions.push(button);
//登録しただけだと表示されないので明示的に表示させる
button.show();
}
function sendSlack(message){
request.post({
uri: 'https://hooks.slack.com/services/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',
headers: { 'Content-Type': 'application/json' },
json: {
username: 'VSCode',
icon_emoji: ':ghost:',
text: message
}
});
}
exports.activate = activate;
//機能を無効にした時の処理?
function deactivate() {}
module.exports = {
activate,
deactivate
}
#おおざっぱに解説
###コマンドの登録
まず主体となる処理を行うコマンドを作る。
コマンドはコマンドパレットを開く時に実行できるあのコマンドのこと。
ただし今回はユーザから任意に呼び出しができない内部処理で使うだけのコマンドを作る。
ユーザーが任意でコマンドパレットから呼び出しをするときは最初のサンプルコードにあるように明示的にpackage.jsonに登録する必要がある。
"contributes":
"commands": [{
"command": "extension.helloWorld",
"title": "Hello World"
}]
},
commandには公開するコマンドのコマンドID
titleはコマンドパレットに表示される部分です。
何も公開しない場合は空にしとく。
"main": "./extension.js",
"contributes": {
},
"scripts": {
実装に関しては、VSCode API一覧にあるregisterCommand関数を使うことで登録できる。
コマンドIDは好きにしておk。
抜粋
//コマンドの作成
// 第一引数:コマンドID 第二引数:コールバック
const cmd = vscode.commands.registerCommand(cmd_id, () => {});
//コマンドの登録
context.subscriptions.push(cmd);
ステータスバーにアイテムを追加し任意のコマンドを紐付け、そこからクリックして実行するようにする。「slackで送信」
createStatusBarItem関数を使い、引数でアイテムの表示位置(右か左)と優先度(同じ右側での順番)を設定できる。
細かいアイテムの動作はプロパティで設定する。
抜粋
// ステータバーにボタン登録
// 第一引数:表示位置 第二引数:優先度
const button = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);
button.command = cmd_id;
button.text = 'slackで送信';
context.subscriptions.push(button);
//登録しただけだと表示されないので明示的に表示させる
button.show();
###注意点
上記の実装だけだとステータスバーにアイテムが表示されない!!
VSCodeの拡張機能は、必要なときに必要な拡張機能のみが有効になるよう実装するようだ。
例えばpython(.py)でしか意味のない拡張は、
package.json内のactivationEventsに下記のように登録する。
"activationEvents": [
"onLanguage:python",
]
今回の拡張機能は常に有効にするためワイルドカードを使う。
最終的なものがコチラ
{
"name": "hoge-extension",
"displayName": "hoge-extension",
"description": "",
"version": "0.0.1",
"engines": {
"vscode": "^1.33.0"
},
"categories": [
"Other"
],
"activationEvents": [
"*"
],
"main": "./extension.js",
"contributes": {
},
"scripts": {
"postinstall": "node ./node_modules/vscode/bin/install",
"test": "node ./node_modules/vscode/bin/test"
},
"devDependencies": {
"typescript": "^3.3.1",
"vscode": "^1.1.28",
"eslint": "^5.13.0",
"@types/node": "^10.12.21",
"@types/mocha": "^2.2.42"
}
}
#入力アイテム
あとは各種入力アイテムを使い実装する。
####QuickPick
リスト選択
vscode.window.showQuickPick(['自分で入力', 'ファイル内容送信', '選択部分を送信']).then((selected) => {});
vscode.window.showInputBox({
prompt: 'Slackへ通知します',
placeHolder: '入力してね'
}).then((value) => {
sendSlack(value);
});
今回は使わなかったけどView Container/Tree Viewなんかもある
#実行&デバッグ
実装できたらF5キー or VSCodeデバッガーより実行すると新たなVSCodeが立ち上がりそこで実行される。
#公開
完成したらマーケットプレイスで公開してみんなに使ってもらおう!!
vsceというツールでコマンド一発公開できる!!!
公式サイトに画像付きで詳しく手順が書いてのでご覧ください
https://code.visualstudio.com/api/working-with-extensions/publishing-extension#get-a-personal-access-token
または、有志の方々の記事を参照してね☆
「Visual Studio Code の拡張機能を開発してみよ」
https://ryuta46.com/1190
「VS CodeのエクステンションをMarketPlaceに公開する」
https://qiita.com/YuichiNukiyama/items/ffcb32188f473b92133d
「Visual Studio Codeの拡張機能を作って公開するまでの流れ」
https://qiita.com/maxfie1d/items/3aca4491f43cb7de4917
#おわりに
簡単に言えば、Node.js環境で公式が提供しているAPIをいじくりまわすことで拡張機能開発できるのでお手軽!!
ただしAPI以上のことをするのは難しい・・・
元々の目的はタブごとに別々で背景色をいじりたかったけど、タブ背景色プロパティは全部のタブ共通で無理ぽよ・・・・なとか
そうなると実際にVSCode本体のソースコードをいじらないといけないぽい