tmuxのペインのステータスラインにgitのブランチとかディレクトリとか表示する(プロンプトはもう古い)

スクリーンショット 2018-03-19 23.27.38.png

前置き(とても長いので読み飛ばしてもよい)

いつの間にか,tmuxのペインごとにステータスラインを表示できるようになっていた

https://github.com/tmux/tmux/blob/master/CHANGES#L329
これは大事件である(と思う).
みんなターミナルのプロンプトにディレクトリはもちろん,gitのブランチとか表示させるのはやってると思う.けど,時々,深層のディレクトリに移動したりすると,このプロンプトがどんどん膨らんできてスペースがなくなる時があった.そこで僕は,プロンプトではなくステータスラインにそういった情報を表示できたらスマートなんではないのか、と1年前くらいに考えた.
しかし,例えば,一つウィンドウに複数のペインが収まっていて,そのそれぞれのペインのカレントディレクトリが異なる,なんてのは当たり前にある話で,そういう状況を包括的にいい感じに処理してステータスラインにディレクトリを表示するなんてのは,今までは,非常に煩雑で,非現実的な話だった.僕は,それを実行するにはペインごとにステータスラインが表示できるようにするしかないと考えて,tmuxをネストしたり,いろいろな試行錯誤をした(んで諦めた).

けれど,僕が全くこの分野に触れていなかったここ一年の間にtmuxはめざましい進化を遂げたらしく,いつの間にかその"ペイン毎にステータスラインを表示する"と云う仕様が公式で実装された.神.
(というか,これが実装されたver2.3がリリースされたのは2017年1月のことらしい,結構革命的な話だと思うんだけど,ほとんど話題になっていなかったので少し驚いた,みんなもっとtmuxをいじってほしい.)

gitとかディレクトリとか表示する

ということで本題.要するにプロンプトじゃなくてステータスラインに種々の情報を表示していこうや,ということである.
作るのは上の画像のこの部分.
スクリーンショット 2018-03-19 23.57.36.png

実は結構煩雑なので頑張ってほしい.

手順

  • .tmux.conf

以下のコードをあなたの.tmux.confに付け足してください.

.tmux.conf
set-option -g pane-border-status bottom
set-option -g pane-border-format "#[fg=black,bg=blue] #P #(tmux-pane-border #{pane_current_path})"
set-option -g pane-border-fg colour023
set-option -g pane-active-border-fg blue
  • .zshrc

以下のコードをあなたの.zshrcに付け足してください.
もともとprecmd関数を使っている人はその中にif~fiのとこだけ付け足してね.

.zshrc
function precmd() {
  if [ ! -z $TMUX ]; then
    tmux refresh-client -S
  fi
}
  • tmux-pane-border

まずは,コマンドラインで

touch tmux-pane-border

などとして,tmux-pane-borderファイルを新しく作成してくだい.次に,そこに以下のコードをコピペしてください.

tmux-pane-border
#!/bin/zsh

if git_status=$(cd $1 && git status 2>/dev/null ); then
  git_branch="$(echo $git_status| awk 'NR==1 {print $3}')"
  case $git_status in
    *Changes\ not\ staged* ) state="#[bg=colour013,fg=black] ± #[fg=default]" ;;
    *Changes\ to\ be\ committed* ) state="#[bg=blue,fg=black] + #[default]" ;; 
    * ) state="#[bg=green,fg=black] ✔ #[default]" ;;
  esac
  if [[ $git_branch = "master" ]]; then
    git_info="#[underscore]#[bg=black,fg=blue] ⭠ ${git_branch} #[default]${state}"
  else
    git_info="#[underscore]#[bg=black,fg=colour014] ⭠ ${git_branch} #[default]${state}"
  fi
else
  git_info=""
fi

directory="#[underscore]#[bg=black,fg=cyan]$1#[default]"

echo "$directory$git_info"

そうしたら、コマンドラインで

chmod a+x tmux-pane-border

などとして,tmux-pane-borderに実行属性を付与してください.あとはtmux-pane-borderファイルを/usr/local/binなどのパスの通ったディレクトリに置いてください(あるいはシンボリックリンクを貼ってください).

解説

  • .tmux.conf

ウィンドウ毎のステータスラインと同じ感じに書くっぽい.だいたいわかると思うので説明が必要なとこだけ説明します,わからない方はこの辺を読んでください.

set-option -g pane-border-format "#[fg=black,bg=blue] #P #(tmux-pane-border #{pane_current_path})"

ここですが,#(tmux-pane-border #{pane_current_path})で、自作コマンド(後述)のtmux-pane-borderを,#{pane_current_path}を引数に実行しています..tmux.confでは,#()の中にコマンドを入れることで,そのコマンドの出力の一行目をとってくることができます.#{pane_current_path}ってのは,そのままです,#Pとか#Wとかそういうヤツと同じです.

  • .zshrc

tmuxを起動していれば,プロンプトを更新するたびにtmuxのステータスラインを更新する,という設定です.

  • tmux-pane-border

このコマンドは,.tmux.confから実行されることだけを考えています.
引数に渡されたカレントディレクトリに対して,gitのリポジトリがあればgit statusしてその結果を返します.内容については,これもまあよくあるやつなので特に解説はしません.

その他

まともな環境が揃っていれば,👆の3つのコードをいい感じにコピペして,コマンドを実行可能にすれば動くと思います.気に入らないところがあれば自由に改変して使ってください,不具合があればコメントしていただけるとありがたいです.ここからは思ったことを書きます(本当にどうでもいいので読まなくてもいいよ).

・tmuxのアタッチとかセッションの管理を奇跡的に簡略化するtmuximumというプラグインがある,是非使ってほしい.

tmuxのステータスバーにssidとかバッテリーとか音量とかload averageとか出す方法もあるらしい,是非みてほしい

・ディレクトリ表示やgitのステータスを完全にステータスラインに移行させてしまうのは実はデメリットもある.例えば、過去の作業ログを見るとき,あるコマンドを実行したのがどこのブランチだったか,どのディレクトリだったかわからなくなってしまう.あと,僕みたいにプロンプトを全て手書きで作っている人なら移行は割と楽だけれど,powerlineとか使ってたら大変なのかもしれない(使ったことないからわからない).

・それと関連して,完全に移行するとなると,tmuxを起動していないときは普通にプロンプトにディレクトリやブランチを表示する設定を書かなきゃいけない.僕はこれももう書いたけれど,そこまで大変ではなかった.

・もともとペインの境界線だったのをステータスラインにしているので,無駄にスペースを占有されないのが素晴らしい.

・できればこれらのコードをプラグイン化して,zplugとかtpmとかで管理できるようにしたかったが,zshrcへの記述が必要だったりするのでやめた.

・precmdでステータスラインを更新しているので,少し重くなるかもしれない.僕の環境ではほとんど影響はなかったのでたぶん気にするほどでほどではない.

tmuxの公式のマニュアルを読むと知らないことがいっぱい書いてある,様々な発見があったので読んでみてほしい.

・タイトルの,プロンプトはもう古い,というのは冗談です