bash-completionで独自の補完関数を作成する方法(gistyのサブコマンドを補完するやつ書いてみた)
歳のせいか最近記憶力が落ちてるので補完に頼ってみることにした。
以下を行なうにはbash-completionパッケージが必要です。
macportsだと
sudo port install bash-completion
でインストールされるはず。
バージョン1
とりあえず、サブコマンドを全部登録してみました版
_gisty() { COMPREPLY=(list post private_post sync sync_delete pull_all about help) } complete -F _gisty gisty
上記を/opt/local/etc/bash_completion.d/の配下にgistyという名前で保存
以下のように設定ファイルを読み込み
$ . /opt/local/etc/bash_completion
"gisty "と打ってtab
を押すと
about list private_post sync help post pull_all sync_delete
と補完候補が表示されるようになる。
ようは、COMPREPLY
という変数に補完候補の配列を格納する関数を書くだけで良いということ。
それをshellが拾って補完候補として使用するという仕組み。
バージョン2
ただ、このままだとつねに全ての補完候補が表示されてしまうので、入力した文字の一部で
補完候補を絞り込むようにしてみる。
_gisty() { COMPREPLY=( $( \ compgen -W "list post private_post sync sync_delete pull_all about help" \ ${COMP_WORDS[COMP_CWORD]} \ ) ) }
compgen
という組み込みコマンドを使うと文字列のリストを絞り込むことができる。
このcompgen
の最後の引数${COMP_WORDS[COMP_CWORD]}
は「現在のカーソル位置のワード」を表している。
COMP_WORDS
がコマンドラインで入力している文字列を単語の単位で配列にしたもの。
COMP_CWORD
はその配列の中での現在位置を表している。
試しにgisty p
まで入力してtab
を押すと、
post private_post pull_all
という感じで、先頭が"p"で始まるサブコマンドだけが表示される。
これで入力した文字で補完候補を絞り込むことができるようになった。
バージョン3
サブコマンドに応じてファイル名を補完するようにしてみる。
gisty の opst または private_post コマンドはポスト対象のファイル名を受け取るようになっているので、これらのサブコマンドを入力した場合は、ファイル名の補完を行なうようにしてみる。
これを保存/反映したのち、gisty post
の後でtab
補完してみると、ファイルの一覧が表示されはず。
コードを見てみる。
prev="${COMP_WORDS[COMP_CWORD-1]}"
は一個前の単語をprevという変数に格納することを表していてる。
case "${prev}" in post|private_post) COMPREPLY=( $(compgen -f ${cur}) ) return 0 ;;
上記のところで、一個前の単語がpostまたはprivate_postだった場合はcompgen -f ${cur}
の結果を補完リストに表示するようになっている。
ここでの-fは「ファイルの補完」を表している、compgenで使用可能な組み込みの補完候補はほかにもいろいろあるのでman bash
で調べてみるといい。
これでとりあえずgisty用の補完関数ができた。
意外と簡単でしょ。