左プロンプトに git のブランチとステータスを、右プロンプトに git リポジトリとそれ以外のディレクトリを色分けして表示
下記を参考に、自分なりにやってみたんだけど・・・
show current git branch on zsh prompt (2) - Bart's Blog
function git_branch() { local git_dir branch git_dir=$(git rev-parse --git-dir 2> /dev/null) || return if test -d "$git_dir/../.dotest"; then branch="$(git symbolic-ref HEAD 2>/dev/null)" elif test -f "$git_dir/.dotest-merge/interactive"; then branch="$(cat "$git_dir/.dotest-merge/head-name")" elif test -d "$git_dir/.dotest-merge"; then branch="$(cat "$git_dir/.dotest-merge/head-name")" elif test -f "$git_dir/MERGE_HEAD"; then branch="$(git symbolic-ref HEAD 2>/dev/null)" else branch="$(git symbolic-ref HEAD 2>/dev/null)" || \ branch="$(git describe --exact-match HEAD 2>/dev/null)" || \ branch="$(cut -c1-7 "$git_dir/HEAD")..." fi echo -n "${branch#refs/heads/}" } function git_state() { local git_dir state git_dir=$(git rev-parse --git-dir 2> /dev/null) || return if test -d "$git_dir/../.dotest"; then if test -f "$git_dir/../.dotest/rebasing"; then state="rebase" elif test -f "$git_dir/../.dotest/applying"; then state="am" else state="am/rebase" fi elif test -f "$git_dir/.dotest-merge/interactive"; then state="rebase-i" elif test -d "$git_dir/.dotest-merge"; then state="rebase-m" elif test -f "$git_dir/MERGE_HEAD"; then state="merge" else test -f "$git_dir/BISECT_LOG" && state="bisect" fi echo -n "${state}" } function git_top_dir() { local git_dir git_dir=$(git rev-parse --git-dir 2> /dev/null) || return case $git_dir in .git) git_dir="$(pwd)/.git";; esac echo "${${git_dir:h}/$HOME/~}" } function rprompt_dir { local git_dir git_dir=${$(git_top_dir)%% } local short short="${PWD/$HOME/~}" if test -z "$git_dir" ; then echo -n "$short" return fi local lead rest lead=$git_dir rest=${${short#$lead}#/} echo -n "$lead%{$fg[cyan]%}/$rest" } function lprompt_git_state { local branch state branch=$(git_branch) state=$(git_state) if test -z "$branch" ; then return fi if test "$state" ; then state=":$state" fi echo -n "%{$fg[cyan]%}(${branch}${state})" } setopt prompt_subst autoload -U colors colors PROMPT='${WINDOW:+"[$WINDOW]"}%{$fg[green]%}`whoami`%{$fg[blue]%}@%{$fg[red]%}`hostname -s``lprompt_git_state`%{$fg[green]%}%#%{$reset_color%} ' RPROMPT='%{$fg[yellow]%}[`rprompt_dir`%{$fg[red]%}:%!%{$fg[yellow]%}]%{$reset_color%}'
予想通りプロンプト表示が重かった。さて、最適化するか。
最適化してみた
関数を一つにまとめて、プロンプトは環境変数を参照するようにし、chpwd と preexec で環境変数に値を設定するように変更した。とても軽くなったので満足。
ただ・・・、zsh-templates を使う予定だったのに、手元の OSX 10.4 + zsh 4.3.6 で動作しなかったのが謎。(帰宅後に OSX 10.5 + zsh 4.3.6 で確認してみよ)
.zshrc.prompt
function _git_compute_vars() { export __ZSH_GIT_STATE= export __ZSH_GIT_DIR= local git_dir state branch git_dir=$(git rev-parse --git-dir 2> /dev/null) || return if test -d "$git_dir/../.dotest"; then if test -f "$git_dir/../.dotest/rebasing"; then state="rebase" elif test -f "$git_dir/../.dotest/applying"; then state="am" else state="am/rebase" fi branch="$(git symbolic-ref HEAD 2>/dev/null)" elif test -f "$git_dir/.dotest-merge/interactive"; then state="rebase-i" branch="$(cat "$git_dir/.dotest-merge/head-name")" elif test -d "$git_dir/.dotest-merge"; then state="rebase-m" branch="$(cat "$git_dir/.dotest-merge/head-name")" elif test -f "$git_dir/MERGE_HEAD"; then state="merge" branch="$(git symbolic-ref HEAD 2>/dev/null)" else test -f "$git_dir/BISECT_LOG" && state="bisect" branch="$(git symbolic-ref HEAD 2>/dev/null)" || \ branch="$(git describe --exact-match HEAD 2>/dev/null)" || \ branch="$(cut -c1-7 "$git_dir/HEAD")..." fi branch="${branch#refs/heads/}" if test "$state" ; then state=":$state" fi case $git_dir in .git) git_dir="$(pwd)/.git";; esac export __ZSH_GIT_STATE="%{$fg[cyan]%}(${branch}${state})" export __ZSH_GIT_DIR="${${git_dir:h}/$HOME/~}" } function _prompt_compute_vars() { _git_compute_vars local git_dir git_dir=${${__ZSH_GIT_DIR}%% } local short short="${PWD/$HOME/~}" if test -z "$git_dir" ; then export __ZSH_RPROMPT_DIR="$short" return fi local lead rest lead=$git_dir rest=${${short#$lead}#/} export __ZSH_RPROMPT_DIR="$lead%{$fg[cyan]%}/$rest" } function _git_preexec_update_vars() { case "$(history $HISTCMD)" in *git*) _git_compute_vars ;; esac } setopt prompt_subst autoload -U colors colors _prompt_compute_vars PROMPT='${WINDOW:+"[$WINDOW]"}%{$fg[green]%}${USER}%{$fg[blue]%}@%{$fg[red]%}`hostname -s`${__ZSH_GIT_STATE}%{$fg[green]%}%#%{$reset_color%} ' RPROMPT='%{$fg[yellow]%}[${__ZSH_RPROMPT_DIR}%{$fg[red]%}:%!%{$fg[yellow]%}]%{$reset_color%}'
.zshrc 抜粋
function chpwd () { _reg_pwd_screennum _prompt_compute_vars _color_ls } function preexec () { _git_preexec_update_vars }