かつて、どこかで「プログラマが徳川将軍の名前を覚えられないのはshellで補完できないからだ」という言説を見かけ、それを解消するべくbashで徳川幕府の将軍名を補完できるshogun-completionというものを作成しました。
当時課題だった問題2点に対応すべく、このたび改良版を公開しました。
鎌倉幕府対応
以前の実装では徳川幕府のみにしか対応していなかったので、オプションにkamakuraを入力した上で補完をすると、鎌倉幕府の歴代将軍を補完できるように修正しました。
shogunコマンドの実装
以前の実装は実在しないshogunコマンドに対する補完、という実装だったのですが、このたびshogunコマンドも実装しました。開発言語にはgolangを用いています。ごーしょーぐんとでも呼んでください。
shogunコマンドの引数に将軍名を入力すると、何代目であるかの情報を出力します。これで以前の実装では対応できなかった、「当該将軍が何代目であるかわからない」という問題にも対応できました。
bashにおける補完の限界
実のところ、zshの補完であればもっと高度なことができます。将軍名を補完する際にそれが何代目であるかの情報を表示するといったことも可能です。
じゃあbashでできないかというと、頑張ればできそうではあります。”bash autocompletion: add description for possible completions“というStackOverflowのやり取りに一例がありました。以下はそのコードの転載です。
_telnet() { COMPREPLY=() local cur cur=$(_get_cword) local completions="10.10.10.10 - routerA 10.10.10.11 - routerB 10.20.1.3 - routerC" local OLDIFS="$IFS" local IFS=$'\n' COMPREPLY=( $( compgen -W "$completions" -- "$cur" ) ) IFS="$OLDIFS" if [[ ${#COMPREPLY[*]} -eq 1 ]]; then #Only one completion COMPREPLY=( ${COMPREPLY[0]%% - *} ) #Remove ' - ' and everything after fi return 0 } complete -F _telnet -A hostnames telnet
ローカル変数completionsに行区切りで補完したい情報を代入しています。その結果を、IFSに改行のみを設定したうえで、compgenに処理させています。これで、入力にマッチする補完候補のみが配列としてCOMPREPLYに代入されます。さらに配列の数が1つだった場合、文字列” – “以下の部分を切り取って返します。その結果、この例では入力したいIPアドレスのみが実際には補完される、というわけです。
このアプローチを自分も試してみたのですが、bashのバージョンのせいか、IFS=”\n”とした状態でもcompgenの出力全体を代入された1個の配列にしかなりませんでした。IFSを使わない方法も試してみたのですが、思うように複数個の配列にできなかったのでそこで断念しました。あと、当該記事にも書かれていますが、IFSの変更は影響が大きいのでむやみにやらない方がいいようです。