Hyper の Extension の作り始め方 - とくにデバッグの仕方

Windows に乗り換えてからターミナルソフトとして何を使うかをずっと悩んでいます。 Mac のときはずっと iTerm2 一択で特に不自由なく使えていたのですが、Windows 用となると Windows Terminal なんかも気になりますが、現時点(2019年6月中旬時点)では GitHub の README

The Windows Terminal is in the very early alpha stage, and not ready for the general public quite yet.

と書かれているので、興味はありますが仕事で使うにはちょっとまだやめておいたほうが良さそうです。

ということで、ConEmu、ConsoleZ、MobaXterm をインストールしてしばらく試用してみました。それらの中では MobaXterm が一番しっくり来たのですが、一つだけどうしても欲しい機能が見つけられませんでした。 その機能は iTerm2 にはあってとても便利につかっていたのですが、それはコンソールに出力された文字列のパターンに反応して任意のコマンドを実行する、というものです。

そんな機能何に使うの!?というツッコミは甘んじて受けますが、これがないと仕事の効率がめちゃめちゃ下がるんです。

なのでもし拡張機能とかが自分で作れるなら、そのくらい作るんだけどなーと思っていました。

そんなときにふと同僚が Hyper を使っているのを見て、私も Mac 版は少し触ったことはあったのですが Windows 版もあるということを知って少し試してみました。

Hyper は標準のままでは私の欲しい上記の機能は存在していませんし、既存の Extension にもそのようなものは存在しないようですが、Extension を自分で作れるという点が他の Terminal と違うところです。

というわけで Extension を作ってみました。

前置きが長くなりましたが、例によっていろんな罠にハマりましたのでその時の試行錯誤の記録を残しておきます。

1. 準備

まず当然 Hyper をインストールします。インストール方法は割愛(公式からダウンロードするだけです)。

自作のプラグインはいきなり npm パッケージにして公開するわけにも行きませんから、Local plugin という形で開発しますので、その準備をします。

Windows の場合は %USERPROFILE%\AppData\Roaming\Hyper\.hyper_plugins\local の下に好きな名前でフォルダをひとつ作ります。 その下に index.js と package.json を作ります。

index.js にはプラグインのコード本体を書いていきます。まずは以下のような内容のボイラープレートを書いておきましょう。

console.log('hello');
exports.middleware = (store) => (next) => (action) => {
  console.log(action);
  next(action);
}

package.json は普通に name とか version とかを書いておきます。

hyper の Preferences を編集します。メニューから Edit > Preferences と選択するか、Ctrl+, を押すか、%USERPROFILE%\AppData\Roaming\Hyper\.hyper.js を直接編集して、一番下の方にある localPlugins の配列に先程作ったフォルダの名前(フォルダ名のみ)を指定して保存します。

2. Hyper から Hyper を起動してプラグインを開発・デバッグ

Hyper プラグインデバッグの仕方を誰も書いてくれていなかったのでかなり試行錯誤しましたが、プラグイン開発時は以下のようにすると良さそうです。

  1. まずは普通に Hyper を起動します。(スタートメニューとかから)
  2. 起動した Hyper のターミナルから、hyper コマンドでもう一つ Hyper を起動します。予め %USERPROFILE%\AppData\Local\hyper\app-x.y.z\resources\bin (x.y.z は適宜環境に合わせてください)に PATH を通しておく必要があるかもしれません。 最初に起動した方の Hyper を親 Hyper、親から起動した方を子 Hyper と呼ぶことにします。
  3. 親 Hyper にはプラグインがロードされたとかのメッセージが表示されます。これは子 Hyper 側でロードされたプラグインの情報です。プラグインに syntax error があったりするとここに表示されます。index.js に書いた、console.log('hello'); もここに出力されます。
  4. 子 Hyper 側で Developer tools を開きます。Ctrl+Shift+I で開くか、メニューから選択します。Hyper から呼ばれるプラグインの関数で console.log() するとこちらのコンソールに出力されます。console.log(action); の内容はこちらに出力されます。
  5. index.js を書き換えたら、子 Hyper で Ctrl+Shift+U を押して Plugin を更新します。親 Hyper にエラーなどが出力されていないことを確認したら、子 Hyper で Ctrl+Shift+R を押してリロードします。これで開発中のプラグインの新しいバージョンがロードされた状態になりますので動作確認等を行うことができます。

3. あとは自分の作りたい機能をバリバリ実装

見た目を変えたい場合は decorateXxx 系の関数を実装して export、コンソール上でやり取りされる文字列のデータが欲しいときは middleware() を実装して export という感じかと思います。 middleware() 内では基本的には 引数の action.type に応じて switch していろいろな処理を実装することになると思います。 表示する文字列をどうこうしたいときは SESSION_ADD_DATA など。 プラグイン固有の設定は .hyper.js の config 直下に プラグイン名 のキーを作ってそこに入れておき、ソース側では middleware() の action.type が CONFIG_LOAD もしくは CONFIG_RELOAD のときに action.config から読み取っておくと良いようです。 基本的には middleware() 関数を抜ける前に next(action) を呼び出します。state をいじってべつの action を起動することもできそう。

ここから先は検索すればいろいろ情報が出てきますし、公開されているプラグインなどのコードを参考にすれば大体のことはわかるのではないでしょうか。

我ながら説明が雑ですねw