コマンドラインを拡張しやすくするヤツ書いた
gitなど既存のコマンドラインを拡張して新しいサブコマンドを追加する方法はいくつか考えられる。
git alias
gitの場合はgit alias
を使うことで簡単にサブコマンドを追加できる。gitのとき限定。
ラッパー
github/hubのような既存のコマンドラインをラップしたスクリプトを書き、alias hub=git
のようにalias
することで既存の機能を保ちつつ機能を追加できる。
問題点としては、複数のラッパーによる拡張が難しくなる。例えば、ここでbub
というgit
のラッパーを書いたとする。git
にhub
の機能とbub
の機能を拡張したい。hub
は入力されたサブコマンドがhub
になければgit
にフォワードしている。なので、hub
とbub
を同時に拡張するにはbub
をhub
のラッパーとして実装することになってしまう。依存関係をハードコーディングすることになるため、まったくスケーラブルじゃない。
命名規則とext
command subcommand
と入力されたらcommand-subcommand
を実行するように名前解決する仕組みがよさそうだと思う。例えば、git pr
というコマンドはまずgit-pr
を探し、あれば実行し、なければgit pr
を実行する(そしてエラーになる)。gem uninstall all
というコマンドはgem-uninstall-all
、gem-uninstall all
、gem uninstall all
の順に探索されて見つかり次第実行される。
このような命名規則を基に名前解決するツールを書いた。
$ go get github.com/naoty/ext
$ go get github.com/naoty/gem-uninstall-all
$ alias gem="ext gem"
$ gem uninstall all # Run gem-uninstall-all
正直、いろんな問題がありえそうだが、昨日思いついたままに書いたものなので、まだ想定できてない。gem-uninstall-rails
というコマンドがあったらrailsをアンインストールできないとかありそう。
上の例で、hub
とbub
を同時に拡張したい場合にext
を使うと以下のようにできる。
$ go get github.com/naoty/hub-bub
$ alias git="ext hub"
$ git bub # Run `hub-bub`
残念ながら、hub
を使いたい場合はこうするしかないような気がする。
追記(2015-07-23)
gitには、git subcommand
をgit-<subcommand>
として名前解決して実行する機能があったことをさっき知った。なので、gitに限って言えばextのようなツールは不要だと思う。
$ cd $HOME/bin
$ vi git-hello
#!/bin/sh
echo "Hello, world!"
$ chmod +x git-hello
$ git hello
Hello, world!