Posted at

まだVSCode拡張機能探しで消耗してるの? VSCodeの拡張機能は意外と簡単につくれるよ!!


TL;DR

VSCode拡張機能おすすめ記事がバズる度に「確かに便利なんだけど 自分が求めているのと違うんだよね〜」となる人向けに

いっそのこと自分で拡張機能つくろうぜ👀

というのがこの記事の趣旨。

そしてVSCodeの拡張機能は思っている以上に簡単に作れるってことを全人類に知って欲しい!!

(拡張機能開発を活発化してIDE最強の座を揺るぎないものにするのが目ry Jetbrainsは高いよ 重いよ)

また、JS初心者のいい題材にもなると思う!?

例題としてステータスバーにSlack通知ボタンを配置して、即座にコード(任意のメッセージ)を送信できる拡張機能を挙げる。

May-18-2019 22-04-18.gif


開発環境構築

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

以下のファイル構成のプロジェクトが作られる

image.png


実装

処理は基本的にプロジェクト直下にあるextension.jsが起点になる。

既にHello Wordをするコマンドの実装がサンプルとして書かれているのでそれを元に改造する。

(サンプルコードについては公式のチュートリアルを参照 https://code.visualstudio.com/api/get-started/your-first-extension)

今回のソースコードはこちら https://github.com/delmontz/hello-vscode


extension.js

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
}



おおざっぱに解説


コマンドの登録

まず主体となる処理を行うコマンドを作る。

コマンドはコマンドパレットを開く時に実行できるあのコマンドのこと。

image.png

ただし今回はユーザから任意に呼び出しができない内部処理で使うだけのコマンドを作る。

ユーザーが任意でコマンドパレットから呼び出しをするときは最初のサンプルコードにあるように明示的にpackage.jsonに登録する必要がある。


package.json

    "contributes": 

"commands": [{
"command": "extension.helloWorld",
"title": "Hello World"
}]
},

commandには公開するコマンドのコマンドID

titleはコマンドパレットに表示される部分です。

何も公開しない場合は空にしとく。


package.json

    "main": "./extension.js",

"contributes": {
},
"scripts": {

実装に関しては、VSCode API一覧にあるregisterCommand関数を使うことで登録できる。

コマンドIDは好きにしておk。


extension.js

抜粋

//コマンドの作成
// 第一引数:コマンドID 第二引数:コールバック
const cmd = vscode.commands.registerCommand(cmd_id, () => {});
//コマンドの登録
context.subscriptions.push(cmd);



ステータスバーにアイテムを追加

image.png

ステータスバーにアイテムを追加し任意のコマンドを紐付け、そこからクリックして実行するようにする。「slackで送信」

createStatusBarItem関数を使い、引数でアイテムの表示位置(右か左)と優先度(同じ右側での順番)を設定できる。

細かいアイテムの動作はプロパティで設定する。


extension.js

抜粋

// ステータバーにボタン登録
// 第一引数:表示位置 第二引数:優先度
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",
]

今回の拡張機能は常に有効にするためワイルドカードを使う。

最終的なものがコチラ


package.json

{

"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

リスト選択

image.png

vscode.window.showQuickPick(['自分で入力', 'ファイル内容送信', '選択部分を送信']).then((selected) => {});


InputBox

入力ボックス

image.png

vscode.window.showInputBox({

prompt: 'Slackへ通知します',
placeHolder: '入力してね'
}).then((value) => {
sendSlack(value);
});

今回は使わなかったけどView Container/Tree Viewなんかもある

image.png


実行&デバッグ

実装できたらF5キー or VSCodeデバッガーより実行すると新たなVSCodeが立ち上がりそこで実行される。

image.png


公開

完成したらマーケットプレイスで公開してみんなに使ってもらおう!!

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本体のソースコードをいじらないといけないぽい