初めてのオレオレ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 のやつとかを参考にするといいと思います。