zsh で Git の作業コピーに変更があるかどうかをプロンプトに表示する方法
2012/12/13 追記
zsh 4.3.11 以降の新しい機能を使って改良しました。 -> 「zsh の vcs_info に独自の処理を追加して stash 数とか push していない件数とか何でも表示する - Qiita」
Git を使ってファイルを編集した場合、それをいったんインデックスに追加(add)してその後コミットってのが基本的な流れになる。なんかいろいろやってると、ちゃんと add したのかどうかわかんなくなることがある。
そういうときは status コマンド使えばいいんだけど、以前エントリ書いた zsh の vcs_info の機能を使うといい感じにプロンプトに表示できるようになるので紹介する。
zshrc の書き方
こんな風に zshrc に書いておけば OK。
autoload -Uz add-zsh-hook autoload -Uz colors colors autoload -Uz vcs_info zstyle ':vcs_info:*' enable git svn hg bzr zstyle ':vcs_info:*' formats '(%s)-[%b]' zstyle ':vcs_info:*' actionformats '(%s)-[%b|%a]' zstyle ':vcs_info:(svn|bzr):*' branchformat '%b:r%r' zstyle ':vcs_info:bzr:*' use-simple true autoload -Uz is-at-least if is-at-least 4.3.10; then # この check-for-changes が今回の設定するところ zstyle ':vcs_info:git:*' check-for-changes true zstyle ':vcs_info:git:*' stagedstr "+" # 適当な文字列に変更する zstyle ':vcs_info:git:*' unstagedstr "-" # 適当の文字列に変更する zstyle ':vcs_info:git:*' formats '(%s)-[%b] %c%u' zstyle ':vcs_info:git:*' actionformats '(%s)-[%b|%a] %c%u' fi function _update_vcs_info_msg() { psvar=() LANG=en_US.UTF-8 vcs_info [[ -n "$vcs_info_msg_0_" ]] && psvar[1]="$vcs_info_msg_0_" } add-zsh-hook precmd _update_vcs_info_msg RPROMPT="%1(v|%F{green}%1v%f|)"
例
こんな感じで、リポジトリに変更がある場合はプロンプトに + とか - とか表示される。
check-for-changes についてもうちょっと詳しく
check-for-changes ってのは zsh のバージョン 4.3.10 から入った vcs_info の機能で、今いるリポジトリにローカルで変更を加えたかどうかを通知してくれる仕組み。
設定方法は以下。
まず最初に、4.3.10 ってのはけっこう新しいバージョンなので、まだそれより古いって人もいると思う。そのときは使えないんだけど、せめて変なエラーメッセージが出ないようにしておこう。
autoload -Uz is-at-least if is-at-least 4.3.10; then # この部分はバージョン 4.3.10 以降で有効になる fi
こんな風に書いておくと、古いバージョンの時は何も設定されずにエラーが出なくなる。1つの zshrc をいろんな環境で使ってる人はこう書いておいた方がいいよ。ちなみに Mac の Snow Leopard にデフォルトで入ってる zsh は 4.3.9 (残念)。
ここまでが準備。次に肝心の中身だけど、まずはこんな風に書いてその設定を有効にする。
zstyle ':vcs_info:git:*' check-for-changes true
現時点では check-for-changes は Git でしか動かないので、Git の場合のみ有効にしてる。Mercurial(hg) 対応は今やってるとこみたい。そのうち使えるようになるだろう。
で、実際に表示する文字列を設定する。
# インデックスに追加された場合に表示される文字列 zstyle ':vcs_info:git:*' stagedstr "+" # 作業コピーに変更があった場合に表示される文字列 zstyle ':vcs_info:git:*' unstagedstr "-"
"+"、"-" は適当な文字列に置き換えよう。デフォルトではそれぞれ "S"、"U" になってるので、そのままでいい人は書かなくても OK。
最後に、プロンプトに表示するフォーマットを指定する。
zstyle ':vcs_info:git:*' formats '(%s)-[%b] %c%u' zstyle ':vcs_info:git:*' actionformats '(%s)-[%b|%a] %c%u'
%c
が stagedstr
、%u
が unstagedstr
に置き換えられる。ここも適当に変更してかっこいいプロンプトにしよう。
パフォーマンスについて
この check-for-changes の機能は便利なんだけど、リポジトリのサイズによってはかなり遅くなる可能性がある(って man に書いてある)。なのでデフォルトでは無効になっている。
実際にどのくらい遅くなるのか試してみた。zsh の git リポジトリ(git://zsh.git.sf.net/gitroot/zsh/zsh)で確認。
まずは check-for-changes なしの場合
% time (vcs_info) (; vcs_info; ) 0.01s user 0.03s system 102% cpu 0.043 total
次に check-for-changes ありの場合
% time (vcs_info) (; vcs_info; ) 0.08s user 0.03s system 103% cpu 0.104 total
合計で2倍ぐらい時間かかってる。
僕が見た感じでも、ちょっと遅くなってるのが分かる。使って困るというほどでもないけど、あんまり遅すぎるようだったら無効にしよう。
参考
いい感じのプロンプトになったと思う。もっと細かく調整したい人は man zshcontrib の GATHERING INFORMATION FROM VERSION CONTROL SYSTEMS を見てね。