zshでbundle exec(とrake)を補完
SLP Advent Calendar 2013 - Adventarの13日目.
(この記事を書いたのは12.03(火)だけど.)
今月からSLPのCEMプロジェクトに参加して,Ruby on Railsで開発している.
そこでbundlerを使ってるのだが,bundle exec以降で補完されないのが辛い.
調べてみた
Googleでbundle execを省略する方法を調べてみた.
どちらもaliasとして展開するもので,補完ではない.
それに,OSのgemではなくbundlerから使うことを明示したい.
ということで,初めてzshの補完関数を書いてみた.
事前準備
bundler実行時に--binstubsで実行ファイルのインストール先を指定しておく.
$ bundle install --path=vendor/bundler --binstubs=vendor/bin
rakeの補完
rakeを実行することが多いので,rakeの補完も実行できるようにする.
ここでは都合上,先にrakeの補完関数を書いておく.
zshでのrakeの補完 - znzの日記 - Rubyistを参考に,以下の点を変更した.
- rakeをbundle exec rakeに変更.
- 「Generating .rake_tasks...」を出力しない.
- 補完のグループ「rake」を定義するために.rake_tasksの文字をエスケープ.
_rake_refresh () { if [[ ! -f .rake_tasks ]]; then return 0; else return $([[ Rakefile -nt .rake_tasks ]]) fi } _rake () { if [[ -f Rakefile ]]; then if _rake_refresh; then bundle exec rake --silent --tasks | cut -d " " -f 2 > .rake_tasks sed -i -e 's/:/\\\:/g' -e 's/\[/\\[/g' -e 's/\]/\\]/g' .rake_tasks fi _values "rake" $(<.rake_tasks) fi }
bundle execの補完
beでbundle execを実行できるように関数を定義する.
(alias be='bundle exec'では補完されなかった.)
be () { bundle exec $* }
bundle execで実行されるファイルはvendor/bin以下にあるので,
lsで一覧を取得して補完候補にする.
補完の手順は以下の通り.
- be直後(CURRENT=2)の場合,vendor/bin以下の実行ファイルを補完する.
- 「be rake」の場合,_rakeを実行してrakeを補完する.
- 上記以外は通常のファイル名で補完を行う.
_be () { if [[ -d vendor/bin ]]; then _arguments '*: :->' if [[ $CURRENT == 2 ]]; then _values "bundle exec" `\ls -1 vendor/bin` elif [[ $CURRENT == 3 && $line[1] == "rake" ]]; then _rake else _files fi fi } compdef _be be
まとめ
思っていたよりも簡単に補完できるようになった.
bundle execを省略して,かつ補完できて満足.
ただ,初めての自作補完関数なのでスマートではないかも.
他にいい方法があれば教えて下さい.
.zshrcの本体はコチラ.
ちなみに,クリスマスの予定はギッシリ埋まってます(白目).