Open13

はじめての VSCode 拡張作成

kattsunkattsun

モチベーション…達人プログラマーで紹介されている一般原則に ETC原則というものがあり、

ファイルを保存するたびに「ETC?」というメッセージを表示するようにし、今入力したコードが変更しやすいものになっているかを考えられるようにしてください。
毎回だと気が変になるというのであれば、10回に1回でもよいでしょう。

これ↑を VSCode で実践したいと思ったため。

kattsunkattsun

やってみるか。

プロジェクトの作成はYeoman(yo)を使用するのが一番簡単です。Yeomanでは予め用意した雛形に則ってプロジェクト初期化を行えるモジュールです。
まずgenerator-codeをグローバルインストールします。これをYoemanで使用するとVS Code拡張のプロジェクトの雛形を生成できます。

npm install -g generator-code
% npm install -g generator-code

added 226 packages in 22s

63 packages are looking for funding
  run `npm fund` for details
npm notice
npm notice New minor version of npm available! 10.7.0 -> 10.8.1
npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.8.1
npm notice To update run: npm install -g npm@10.8.1
npm notice
Reshimming asdf nodejs...
kattsunkattsun
npx yo code を実行する
% npx yo code
Need to install the following packages:
yo@5.0.0
Ok to proceed? (y) y

npm warn deprecated are-we-there-yet@1.1.7: This package is no longer supported.
npm warn deprecated npmlog@2.0.4: This package is no longer supported.
npm warn deprecated gauge@1.2.7: This package is no longer supported.
(node:56554) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)

     _-----_     ╭──────────────────────────╮
    |       |    │   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
  New Language Pack (Localization)
  New Web Extension (TypeScript)
  New Notebook Renderer (TypeScript)

出たなおっさん。
|200

kattsunkattsun

Which bundler to use? どうしよう。webpack と esbuild って何が違うんだろう?

? Which bundler to use? (Use arrow keys)
❯ unbundled
  webpack
  esbuild
kattsunkattsun
webpack、babel、esbuildをちゃんと理解したい。より

webpack、babel、esbuildをちゃんと理解したい。

👉FW内部で誰が何のビルド/変換処理を担っているのか → webpack/babelとは?
👉ここ2,3年で台頭してきたesbuildは何がいいのか。

✅webpackが1つのファイル(main.js)にバンドルにしている主な理由は
ES6導入のimport/exportを、バンドルしてES5でも使える形に変換するため。
ES6導入のimport/export構文をブラウザ上で使えるようになった今、必ずしもwebpackで1つのmain.jsにまとめる必要はない。

babelとは
✅JavaScriptのコンパイラ/トランスパイラ。
✅主な目的はES6+コード(Promise/Template Literal)をES5-friendlyコードへの変換。

✅esbuildは、各Content(JS/TS/JSX/JSON/etc)に対して変換処理を担うLoaderが用意されており、各Loaderはesbuildに「JSファイルはこんな感じで変換してくれ」と伝える感じ。

esbuild、なぜ速い?
△ ESModulesを利用するため、一部しかバンドルしないから。
〇 Go言語で書かれている=ネイティブコードであるから。
〇 並行処理で利用可能なCPUコアを使った高速処理。
〇開発時のバンドルのみesbuildを使った事前バンドルを行うため。

うーん、よくわからんな。結局何が違うんだ?まあ esbuild にするか。早いらしいし。

セットアップ結果
? What type of extension do you want to create? New Extension (TypeScript)
? What's the name of your extension? etc-reminder
? What's the identifier of your extension? etc-reminder
? What's the description of your extension?
? Initialize a git repository? Yes
? Which bundler to use? esbuild
? Which package manager to use? npm

Writing in /Users/kattsun/etc-reminder...
   create etc-reminder/.vscode/extensions.json
   create etc-reminder/.vscode/launch.json
   create etc-reminder/.vscode/settings.json
   create etc-reminder/.vscode/tasks.json
   create etc-reminder/package.json
   create etc-reminder/tsconfig.json
   create etc-reminder/.vscodeignore
   create etc-reminder/esbuild.js
   create etc-reminder/vsc-extension-quickstart.md
   create etc-reminder/.gitignore
   create etc-reminder/README.md
   create etc-reminder/CHANGELOG.md
   create etc-reminder/src/extension.ts
   create etc-reminder/src/test/extension.test.ts
   create etc-reminder/.vscode-test.mjs
   create etc-reminder/.eslintrc.json

Changes to package.json were detected.

Running npm install for you to install the required dependencies.
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated rimraf@3.0.2: Rimraf versions prior to v4 are no longer supported
npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
npm warn deprecated glob@8.1.0: Glob versions prior to v9 are no longer supported

added 379 packages, and audited 380 packages in 30s

127 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

Your extension etc-reminder has been created!

To start editing with Visual Studio Code, use the following commands:

     code etc-reminder

Open vsc-extension-quickstart.md inside the new extension for further instructions
on how to modify, test and publish your extension.

For more information, also visit http://code.visualstudio.com and follow us @code.


? Do you want to open the new folder with Visual Studio Code? Open with `code`
kattsunkattsun

Run Extention を実行してみるが、何もおこらない…。

VS Codeのデバッガーで[Run Extension]をクリック。
すると別ウィンドウが開く

って書いてるのにな…。

kattsunkattsun

package.json を確認。"activationEvents": [], だった。

activationEventsでは、どのコマンドがどのイベント発生時に呼び出される(アクティベートされる)かを定義します。

と書いてあるので入れてみる。

  "activationEvents": [
    "onCommand:etc-reminder.helloWorld"
  ],

すると "This activation event can be removed as VS Code generates these automatically from your package.json contribution declarations." という注意書きがでてきた。

Activation Events | Visual Studio Code Extension API によると

Note: Beginning with VS Code 1.74.0, commands contributed by your extension do not require a corresponding onCommand activation event declaration for your extension to be activated.

ということらしい。onCommand は定義しなくてよさそうだ (ちなみに現バージョンは Version: 1.90.0 (Universal))。

kattsunkattsun

Run Extention を実行してみるが、何もおこらない…。

一回 VSCode を開き直して Run Extention を実行したら別ウインドウが開いた。よかった。

kattsunkattsun

ChatGPT にファイルを保存したときに activate するためのコードの書き方を聞いた。vscode.workspace.onDidSaveTextDocument を教えてもらったが、例示されたコードに [[registerCommand]] がなかったので動かずに時間を少し溶かしてしまった。

vscode.window.showInformationMessage()でメッセージ表示をする処理を、vscode.commands.registerCommandで登録しています。このコマンドの登録処理は必須となります。

(from: かんたん!VS Code拡張機能開発 | DevelopersIO)

↓ で動いた

export function activate(context: vscode.ExtensionContext) {
  vscode.workspace.onDidSaveTextDocument((document: vscode.TextDocument) => {
    vscode.window.showInformationMessage(`${document.fileName} is ETC?`);
  });

  const disposable = vscode.commands.registerCommand('etc-reminder.remindEtc', () => {
    vscode.window.showInformationMessage('etc-reminder is activated!');
  });

  context.subscriptions.push(disposable);
}
kattsunkattsun

一旦やりたい挙動は実現できたので拡張機能として使える準備をする。

README をデフォルトから変更する (Usage を書きたかったが、いったん WIP にしておく)。
この状態で、npx vsce package を実行してみる。

次のvsce packageを実行してプロジェクトをパッケージします。vsceはVisual Studio Code Extension Managerです。

実行結果
% npx vsce package
Need to install the following packages:
vsce@2.15.0
Ok to proceed? (y) y

npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
npm warn deprecated vsce@2.15.0: vsce has been renamed to @vscode/vsce. Install using @vscode/vsce instead.
(node:16325) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
Executing prepublish script 'npm run vscode:prepublish'...

> etc-reminder@0.0.1 vscode:prepublish
> npm run package


> etc-reminder@0.0.1 package
> npm run check-types && npm run lint && node esbuild.js --production


> etc-reminder@0.0.1 check-types
> tsc --noEmit


> etc-reminder@0.0.1 lint
> eslint src --ext ts

[watch] build started
[watch] build finished
 WARNING  A 'repository' field is missing from the 'package.json' manifest file.
Do you want to continue? [y/N] y
 WARNING  LICENSE.md, LICENSE.txt or LICENSE not found
Do you want to continue? [y/N] y
 DONE  Packaged: /Users/kattsun/ghq/github.com/kattsun44/etc-reminder/etc-reminder-0.0.1.vsix (6 files, 2.8KB)

vsix ファイルの作成を確認。

% ls -lA | grep vsix
-rw-r--r--    1 kattsun  staff    2863 Jun  8 14:06 etc-reminder-0.0.1.vsix
kattsunkattsun

[Extentions] > "…" > [Install from TSIX] をクリックし、上記ファイルを選択

Completed installing etc-reminder extension from VSIX.

インストールできた!使えるようになった!けど文章が畳まれて "ETC?" が読めねえ