rcmdnk's blog

Brew-file update: completion, wrapper commands
Percentage of Completion Method: in less than 300 words (English Edition)

Bashの補完についてZshの補完について でシェルの補完について書きましたが、 これらに従ってBrew-fileの中にコマンド補完用のスクリプトを追加しました。

補完用ファイル

補完用のファイルはetc/bash_completion.d/brew-file 及びshare/zsh/site-functions/_brew-fileですが、 _brew-fileの方はbrew-fileの方へのリンクになっていて同じものです。

それぞれBash用、Zsh用ですが、同じような事をするので まとめて必要なところだけ中で分岐させる様にしています。

Bashの補完についてZshの補完について で書いたとおり、これらはFormulaの中で

1
2
3
4
5
6
7
8
9
  def install
    bin.install 'bin/brew-file'
    (bin+'brew-file').chmod 0755
    (prefix+'etc').install 'etc/brew-wrap'
    if build.with? "completions"
      bash_completion.install "etc/bash_completion.d/brew-file"
      zsh_completion.install "share/zsh/site-functions/_brew-file"
    end
  end

と言った形でそれぞれ/usr/local/etc/bash_completion.d//usr/local/share/zsh/site-functions/へインストールされる様になっています。

Bashの場合は Bash-Completion: http://bash-completion.alioth.debian.org/ をインストールして、.bashrcとかに

1
2
3
4
brew_completion=$(brew --prefix 2>/dev/null)/etc/bash_completion
if [ $? -eq 0 ] && [ -f "$brew_completion" ];then
  source $brew_completion
fi

と書いておけばOK。

Zshの場合には

1
2
3
4
5
6
7
8
for d in "/share/zsh-completions" "/share/zsh/zsh-site-functions";do
  brew_completion=$(brew --prefix 2>/dev/null)$d
  if [ $? -eq 0 ] && [ -d "$brew_completion" ];then
    fpath=($brew_completion $fpath)
  fi
done
autoload -U compinit
compinit

という感じで書いておけばOKです。 (zsh-completionsの方はzsh-completions をインストールしている場合ですが、ない場合はこれは無くてzsh-site-functions だけでOKです。)

brew自身やbrew fileと言った場合にも補完するようにする

上の設定ではbrew-fileというコマンドに対してだけ補完をするので、 brew fileと、brewコマンドのサブコマンドとして使った場合には 適用されません。

これにはbrewコマンドの補完を上書きしてあげないといけないので、 これ用の設定を etc/brew-wrap に追加してあります。

1
2
3
4
## wrap brew (brew-wrap in brew-file)
if [ -f $(brew --prefix)/etc/brew-wrap ];then
  source $(brew --prefix)/etc/brew-wrap
fi

という設定を上の補完用のファイルの読み込みの後に置いてください (Bash/Zsh両方とも同じ)。

brew用の補完は_brewという関数で決められていて、 brew-fileの補完は_brew_fileという関数で決められています。

brew-wrap の中身を見てもらうと、 これらの関数が定義されてる時、 新たに_brew_completion_wrapという関数を作って、 これを改めてbrewコマンドの補完用関数として定義している事がわかると思います。

やってることは、まず、最初のbrew で補完しようとする時、 通常外部のサブコマンドは補完されませんが、fileも補完される様にしました。

$ brew <Tab>
--cache       abv           configure     fetch         link          missing       remove        unlink        uses
--cellar      audit         create        file          linkapps      options       rm            unlinkapps
--config      cat           deps          help          list          outdated      search        unpin
--env         cleanup       diy           home          ln            pin           tap           untap
--prefix      commands      doctor        info          log           prune         test          update
--repository  config        edit          install       ls            reinstall     uninstall     upgrade
$ brew

な感じでfileも加わる様になります。

さらに、brew file と打った後はbrew-fileに対する 補完と同じ物が補完されるように設定してあります。

このためにetc/bash_completion.d/brew-file の方でも 補助関数の中で第一(コマンド自身)、第二引数がbrewfileと来た時には 1つずつ引数をずらして扱う様にする機能を入れています。

これでbrew fileと打つ時のもfileは補完され、 さらにbrew fileと打った後もそれ用の補完が効くようになります。

$ brew file <Tab>
brew          casklist      commands      help          install       push          update
cask_upgrade  clean         edit          init          pull          set_repo      version
$ brew file

こんな感じ。-で始まる様な引数は-を打った後にだけ効くようにしてあります。

homebrew-fileのwrapper関数を’brew init’等一部コマンドを直接使える様にアップデート の所でbrewコマンドに対して直接init等のサブコマンドを与えても 動くようにしたりしましたが、 この辺まで補完に入れてしまうとごっちゃになりそうだったので 今のところはbrewと打った段階ではこれらのサブコマンドは 補完される様にはなってません。 (brew initと打ってもらえれば補完はされませんが、実行すればbrew file initと同じ動作はします。)

一応Bash(4.3.33)、Zsh(5.0.5)で動く事は確認しましたが、 特にZshは普段使わないので何か不具合があった場合は GitHubのIssueなり適当な手段で教えていただけるとありがたいです。

Sponsored Links
Sponsored Links

« Zshの補完について ブラウザのAdobe Flash PlayerがError #2046なエラーで動かなくなった時の対処法 »

}