トップ «前の日記(2012-03-03) 最新 次の日記(2014-01-04)» 編集

活動日誌


2012-03-06

[zsh] GitやMercurialのワークツリーのルートに下線を引く

2012-03-06-vcs-info.gif

今使っている zsh の右プロンプトにはカレントディレクトリを表示しているのですが、 Git や Mercurial のワークツリー(ワーキングディレクトリ)の中にいるときは、そのルートディレクトリに下線を引くようにしています。

これがなかなか気に入っているので紹介します。

以下では主要な部分だけ抜き出して解説しています。 zsh 設定ファイルの全体は github にアップしています。https://github.com/kyanagi/dot.zsh.d

まず、vcs_info の設定で formats に %r を設定しておき、リポジトリ名を取得できるようにします。 次の例だと、$vcs_info_msg_2_ で取得できるようになります。 http://zsh.sourceforge.net/Doc/Release/User-Contributions.html#Configuration

zstyle ':vcs_info:*' formats '%F{white}%c%u%s%f%F{white}:%f%F{green}__branch-name__%f' '%b' '%r'

次に、RPROMPT の設定です。

local rprompt
rprompt=(
  "%F{$prompt_color}["
  "\${vcs_info_msg_0_:+\${vcs_info_msg_0_} }%f" # VCS の情報があれば表示
  "%F{$prompt_color}"
  # $PWD は ~ が展開されているので ~ に戻し、リポジトリ名の部分に下線を付ける。
  # リポジトリ名は $vcs_info_msg_2_ に入っている。
  "\${\${PWD/#\$HOME/~}/\${vcs_info_msg_2_}/%U\${vcs_info_msg_2_}%u}"
  " %*]%f"
)
RPROMPT=${(j..)rprompt}

rprompt に配列を作ってから連結しているのはコメントを書くためです。 (j.. については http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion-Flags を参照)

いろいろと書いていますが、今回の記事に関係するのは

"\${\${PWD/#\$HOME/~}/\${vcs_info_msg_2_}/%U\${vcs_info_msg_2_}%u}"

の部分です。

以下ではこの内容をもう少し詳しく説明します。

プロンプトに変数の内容を表示する

右プロンプトに $PWD の値を出したいとします。

RPROMPT="$PWD"

とすると、(このコマンドを入力したときのカレントディレクトリが /var/tmp として)実際には

RPROMPT=/var/tmp

と展開されて実行されるので、その後ディレクトリを移動しても表示は常に /var/tmp のままになります。

右プロンプトの表示ごとにその瞬間の $PWD を表示するには、RPROMPT に「$PWD」という文字列を設定する必要があるので

RPROMPT="\$PWD"

としなくてはいけません。

設定解説

以上をふまえた上で、実際に右プロンプトの設定内容を見てみます。

~/tmp に tdiary-core をチェックアウトし、tdiary-core/spec/core に移動した状況を考えます。

各変数の内容は以下のような感じです。

変数 内容
$PWD /Users/ani/tmp/tdiary-core/spec/core
$HOME /Users/ani
$vcs_info_msg_2_ tdiary-core

まず、$PWD は ~ が展開されているので ~ に戻します。

${PWD/#$HOME/~} ~/tmp/tdiary-core/spec/core

(${name/pattern/repl} は name の pattern を repl に置換して展開するという意味です。# で始まるパターンは文字列の先頭を意味します。 http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion

次に、リポジトリ名 tdiary-core を下線付きにします。 リポジトリ名は $vcs_info_msg_2_ に入っています。 プロンプトで下線を引くには %U ... %u で囲います。

よって、$vcs_info_msg_2_ を %U${vcs_info_msg_2_}%u で置換します。

${${PWD/#$HOME/~}/${vcs_info_msg_2_}/%U${vcs_info_msg_2_}%u} ~/tmp/%Utdiary-core%u/spec/core

最後に、これを右プロンプトの表示ごとに解釈するため、$ をエスケープします。

\${\${PWD/#\$HOME/~}/\${vcs_info_msg_2_}/%U\${vcs_info_msg_2_}%u}

これで当初の設定どおりとなります。

なお、リポジトリ名と同じ名前のディレクトリがワークツリーより上にあった場合、そちらの方に下線が引かれてしまいます。 しかしこれはレアケースだと思いましたので、簡単のため特に対応していません。 (真面目にやるなら vcs_info formats の %R でフルパスが取れるので、それを使えば対処できると思います)

追記

RPROMPT の内容は以下のように修正しました。

"${${${PWD/#\$HOME/~}/\/${vcs_info_msg_2_}\///%U${vcs_info_msg_2_}%u/}/%\/${vcs_info_msg_2_}//%U\${vcs_info_msg_2_}%u}"

リポジトリ名が foo であるとき、カレントディレクトリが /foobar/foo だと foobar の foo に下線が引かれていたので、 下線はディレクトリ全体に対して置換するように修正しました。

読みづらいですが、リポジトリ名を foo とすると、まず /foo/ を /%Ufoo%u/ に置換し、 次に文字列末尾の /foo を /%Ufoo%u に置換しています。


2005|02|03|04|05|06|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|03|04|05|06|10|
2008|04|10|
2009|10|
2010|05|08|
2012|01|02|03|
2014|01|
トップ «前の日記(2012-03-03) 最新 次の日記(2014-01-04)»