初めてのオレオレbash補完

さて、ひとつ前のエントリは釣りだったわけですが、本題のbash補完を初めてやってみました。ちょっとした物だったら割と簡単に書けたので、共有。

目標

自作コマンド(仮にsugyanとします)はこんな感じのI/Fだとします。

  • sugyan subcommand [args]
    • いくつかのsubcommandは次にくる引数が限られる
      • 例えばsugyan momocloの後にはkanako renichan shiorin ahrin momoka
    • sugyan listでそういう補完の一覧が色々出せる
      • sugyan list commandでsubcommandの一覧
      • sugyan list momocloでももクロ一覧
      • 一応sugyan listcommand momocloが返る
    • あとはいつものbashのままにファイルとかを補完して欲しい

実際叩くと、

$ sugyan list
command momoclo
$ sugyan list command
momoclo list help
$ sugyan list momoclo
kanako renichan shiorin ahrin momoka
$ sugyan momoclo ahrin
love love love

こんな感じのコマンドに対して

$ sugyan [TAB]
momoclo list help 
$ sugyan momoclo [TAB]
kanako renichan shiorin ahrin momoka

的な補完を作りたいとします。

こんな感じ

PATHにsugyanが通ってる前提で(前のエントリ参照)、以下のようなbashrcを読み込んであげればいい感じになります。

解説(間違ってたらすいませんすいません><)

まず22行目のcompleteという関数がbashの組み込みで、補完するための色々をしてくれるようです。-Fで実際に補完する関数として直前で定義したものを指定しています。また、オプションでdefaultを与えておくとマッチするものがなかった時にデフォルトの挙動をしてくれます(bashdefaultの方はよく分かってませんが一応書いてます!)

で、実際の補完する関数の中身ですが、COMP_WORDSという配列の中にコマンドラインの引数が入ってて、今どこにいるかをCOMP_CWORDが示しているので、5,6行目で現在と一個前を取得してます。これらを使って、COMPRELYという配列に補完候補をぶち込んであげればいい感じです。

で、まずそもそもsubcommand一覧を出すために、COMP_CWORDが1の時はsugyan list commandを実行した結果を使います。一旦変数に格納して、その後compgenという組み込み関数で実際の補完結果にしてます。-Wというオプションは候補をスペース区切り?のリストで渡しつつ、curも渡してあげるとよしなに補完対象を選んでくれます。

あとはmomoclolistについてはさらに補完対象が絞られるので同じことを次のelifの中でやってます。

おわりに

やってみたら意外と簡単でした。補完対象とかは、大抵自分で作ったコマンドが知ってると思いますので、一覧を出すようなオプションを準備してあげると簡単にbash補完が作れます。

もっと込み入ったことをやりたい場合、色々ググってみたり、bash_completionとか、gitのやつとかを参考にするといいと思います。