【スクショ解説付き】zshでgitのブランチ名をステータスに応じて色付き表示させる簡易設定

# はじめに

zshのターミナル上にgitのブランチ情報をステータスに応じて色付きで表示させるようにしました。

類似記事はたくさんあるのですが、凝りすぎててオーバースペックな設定だったり、痒いところに手が届かない設定だったりと設定ファイルを作成するのに苦労しました。

今回は、開発をする上で最低限これだけは備わっていてほしいと思った機能を持った設定ファイルについて、簡単な解説とともに記載をしようと思います。

なお、`.zshrc`を編集せずに**サクっとgitのステータスを表示させたいのであればoh-my-zshを利用することをオススメします。**

oh-my-zshのインストール方法については<a href="https://nishinatoshiharu.com/install-ohmyzsh/" target="_blank">『イケてるターミナルをコマンド1つで作れるoh-my-zsh!gitのブランチ名だって表示できる!』</a>で解説しているので興味がある方はご覧になってください。



# 今回作成する設定ファイルの概要

今回は以下のような要件を満たす設定ファイルを作成しました。

- gitで管理されているディレクトリ下でのみ色付きでブランチ名を表示させる
- zshの右側にブランチ名を表示させる

また、ファイルを新規作成(もしくは編集)してからcommitが完了するまでの以下の4つの状態に対してそれぞれ色分けをしました。

- gitに管理されていないファイルがある状態(=新規で作成したファイルがある)
  - 赤色で?マークと共にブランチ名を表示
- `git add`されていないファイルがある状態
  - 赤色で+マークと共にブランチ名を表示
- `git commit`されていないファイルがある状態
  - 黄色で!マークと共にブランチ名を表示
- 全てcommitされてクリーンな状態
  - 緑色でブランチ名を表示

また、`git add`されていないものと`git commit`されていないものがある時のように、上記の状態が複数存在する場合があると思います。
複数の状態が存在している場合にはクリーンな状態からより遠いもの(箇条書きでいうとより上の項目)の状態を優先させて表示させるようにしました。

さらに以下の状態も考慮しました。

- コンフリクトが起こった状態
  - 赤色で!(no branch)と表示


# 完成形
ターミナル上では以下のような感じで表示されます。

![スクリーンショット 2016-12-08 22.47.14.png](https://qiita-image-store.s3.amazonaws.com/0/140792/62a42b7f-4bcf-e933-38d9-f38d8759a45c.png)

コンフリクトした場合は以下のようになります。
![スクリーンショット 2016-12-08 23.05.18.png](https://qiita-image-store.s3.amazonaws.com/0/140792/28a4af9b-0701-91d1-e432-05ca2ef794af.png)


# 設定ファイル

設定ファイルは以下のようになっています。

ロジックですが、ブランチ名については`git branch`の実行結果から取得し、ブランチの状態については`git status`の実行結果から取得するようにしています。

今回の設定ファイルは[gist](https://gist.github.com/nishina555/4639d315799aae855d128e9cfe541367)にあげておきました。

```zsh:.zshrc

# ここはプロンプトの設定なので今回の設定とは関係ありません
if [ $UID -eq 0 ];then
# ルートユーザーの場合
PROMPT="%F{red}%n:%f%F{green}%d%f [%m] %%
"
else
# ルートユーザー以外の場合
PROMPT="%F{cyan}%n:%f%F{green}%d%f [%m] %%
"
fi


# ブランチ名を色付きで表示させるメソッド
function rprompt-git-current-branch {
  local branch_name st branch_status

  if [ ! -e  ".git" ]; then
    # gitで管理されていないディレクトリは何も返さない
    return
  fi
  branch_name=`git rev-parse --abbrev-ref HEAD 2> /dev/null`
  st=`git status 2> /dev/null`
  if [[ -n `echo "$st" | grep "^nothing to"` ]]; then
    # 全てcommitされてクリーンな状態
    branch_status="%F{green}"
  elif [[ -n `echo "$st" | grep "^Untracked files"` ]]; then
    # gitに管理されていないファイルがある状態
    branch_status="%F{red}?"
  elif [[ -n `echo "$st" | grep "^Changes not staged for commit"` ]]; then
    # git addされていないファイルがある状態
    branch_status="%F{red}+"
  elif [[ -n `echo "$st" | grep "^Changes to be committed"` ]]; then
    # git commitされていないファイルがある状態
    branch_status="%F{yellow}!"
  elif [[ -n `echo "$st" | grep "^rebase in progress"` ]]; then
    # コンフリクトが起こった状態
    echo "%F{red}!(no branch)"
    return
  else
    # 上記以外の状態の場合は青色で表示させる
    branch_status="%F{blue}"
  fi
  # ブランチ名を色付きで表示する
  echo "${branch_status}[$branch_name]"
}

# プロンプトが表示されるたびにプロンプト文字列を評価、置換する
setopt prompt_subst

# プロンプトの右側(RPROMPT)にメソッドの結果を表示させる
RPROMPT='`rprompt-git-current-branch`'
```

# おわりに

以上の設定でzshのターミナル上にgitのブランチ情報をステータスに応じて色付きで表示できるようになりました。

今回は`git status`の結果を利用してブランチのステータスの色分けしましたが、類似の記事をみると`vcs_info`を利用したものが多く、今回の設定は正直あまり賢くない方法かなと思っています。
`vcs_info`を利用した方法については以下の記事の解説がとてもわかりやすかったです。
[zshのターミナルにリポジトリの情報を表示してみる]
(http://tkengo.github.io/blog/2013/05/12/zsh-vcs-info/)
しかし、この設定では「gitに管理されていないファイルがある状態」の情報を識別することができなかったので、`git status`をベースにした設定を採用しました。

もっと簡潔に(賢く)書ける設定をご存知でしたらフィードバックをいただければと思います。

# 参考
[zshのターミナルにリポジトリの情報を表示してみる]
(http://tkengo.github.io/blog/2013/05/12/zsh-vcs-info/)
[[Zsh][Git] git のブランチ名を zsh の右プロンプトに表示＋ status に応じて色もつけてみた ](http://d.hatena.ne.jp/uasi/20091017/1255712789)