zshでgitの状態(編集有り / 未commit / 未push)を表示する

表示イメージ

  • testという名前のブランチにいるので右のほうに「@test」と出ている
  • 次に vi .vimrc とファイルを編集したので「@test-」というように「-」で編集した(unstageな)ファイルがあることを示す
  • 次に git add .vimrc で編集したファイルをステージングすると「@test+」というように「+」でステージングされたファイルがあることを示す
  • 最後に git commit でステージングされたファイルをコミットすると「@test?」というように「?」で未pushのコミットがあることを示す

というようにします。

事前準備

zshのバージョンが 4.3.10 以降である必要がありますので、古いようでしたら事前にupdateが必要です。

.zshrc への設定追加

  • Gitと連携する部分
# gitのブランチ名と変更状況をプロンプトに表示する 
autoload -Uz is-at-least
if is-at-least 4.3.10; then
  # バージョン管理システムとの連携を有効にする 
  autoload -Uz vcs_info
  autoload -Uz add-zsh-hook

  zstyle ':vcs_info:*' enable git
  zstyle ':vcs_info:git:*' check-for-changes true
  zstyle ':vcs_info:git:*' stagedstr "+"
  zstyle ':vcs_info:git:*' unstagedstr "-"
  zstyle ':vcs_info:git:*' formats '@%b%u%c'
  zstyle ':vcs_info:git:*' actionformats '@%b|%a%u%c'

  # VCSの更新時にPROMPTを自動更新する
  function _update_vcs_info_msg() {
    psvar=()
    LANG=en_US.UTF-8 vcs_info
    [[ -n "$vcs_info_msg_0_" ]] && psvar[1]="$vcs_info_msg_0_"
    psvar[2]=$(_git_not_pushed)
  }
  function _git_not_pushed() {
    if [ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ]; then
      head="$(git rev-parse HEAD)"
      for x in $(git rev-parse --remotes)
      do
        if [ "$head" = "$x" ]; then
          return 0
        fi
      done
      echo "?"
    fi
    return 0
  }
  add-zsh-hook precmd _update_vcs_info_msg
fi
  • RPROMPT(右側のほう)に表示させる部分
RPROMPT="%{${fg[green]}%}%1v%2v [%~]%{${reset_color}%}"

%1v が、上記設定の psvar[1] に代入した部分(ブランチ名と+-)を表示するところ
%2v が、上記設定の psvar[2] に代入した部分(?)*1を表示するところ

*1:未pushのコミットがあるかどうか