tmux のステータスラインにフロントエンドナイズな情報を表示する

@arks22 さんの [tmuxのペインのステータスラインにgitのブランチとかディレクトリとか表示する(プロンプトはもう古い)](https://qiita.com/arks22/items/db8eb6a14223ce29219a) を読んで、これいい！便利！！と思ったので試してみました。私はフロントエンドエンジニアなので、どうせならフロントエンドナイズ（というか自分用）にカスタムして使いたいと思います。node のバージョンとか表示できたらいいなあ...と常に思っていたんです。

# この記事を書いた環境

- macOS Catalina
- zsh v5.5.1
- tmux v3.0α

# ステータスラインの情報収集用のコマンド

元記事とはちょっと順番が違いますが、ステータスラインに乗せる情報集めのコマンドから作ります。

```bash
$ vi ~/.tmux/tmux-pane-border
```

ファイルの中身は下記の内容です。

```bash
#!/bin/zsh

bg_blue="#[fg=colour0,bg=colour12]"
bg_lightblue="#[fg=colour7,bg=colour33]"
fg_blue="#[fg=colour27,bg=colour16]"
fg_red="#[fg=colour198,bg=colour16]"

# gitの情報を収集
if git_status=$(cd $1 && git status 2>/dev/null ); then
  git_branch="$(git branch --contains| awk 'NR==1 {print $2}')"

  # release/master で作業しているか
  if [[ $git_branch = "release" || $git_branch = "master" ]]; then
    fg_git=$fg_red
  else
    fg_git=$fg_blue
  fi
 
  # git status コマンドの出力テキストからステータスを判定
  case $git_status in
    *Changes\ not\ staged* ) git_status="+" ;;
    *Changes\ to\ be\ committed* ) git_status="++" ;; 
    *currently\ editing\ a\ commit\ while\ rebasing* ) git_status="in progress(rebase)" ;;
    *interactive\ rebase\ in\ progress* ) git_status="in progress(rebase)" ;;
    *currently\ cherry-picking\ commit* ) git_status="in progress(cherry-pick)" ;;
    * ) git_status="---" ;;
  esac

  if [[ $git_status == "---" ]]; then
    fg_git_status=$fg_blue
  else
    fg_git_status=$fg_red
  fi
else
  git_branch="---"
  fg_git=$fg_blue
  git_status="---"
  fg_git_status=$fg_blue
fi

# node のバージョン
node_version=$(node -v)

# package.json の情報を収集
if package_name=$(cd $1 && ls package.json 2>/dev/null ); then
  package_name="$(node -e "console.log(require('$1/package.json')['name'])")"
else
  package_name="---"
fi

# 連結して出力
echo "$bg_blue NODE $fg_blue $node_version $bg_blue PACKAGE $fg_blue $package_name $bg_lightblue BRANCH $fg_git $git_branch $bg_lightblue STATUS $fg_git_status $git_status "
```

コマンドを直接叩くと、ステータスラインに表示するテキストが確認できます。

```bash
$ chmod a+x ~/.tmux/tmux-pane-border
$ ~/.tmux/tmux-pane-border $(pwd)
# こんな情報が出てくればOK
# #[fg=colour0,bg=colour12] NODE #[fg=colour27,bg=colour16] v12.13.0 ...
```

# tmux にコマンドの在り処を教える

コマンドの出力結果をステータスラインに表示するように設定します。

```bash
// ~/.tmux.conf
set-option -g pane-border-status bottom
set-option -g pane-border-format "#[fg=colour7,bg=colour19] #S[#P] #(~/.tmux/tmux-pane-border '#{pane_current_path}')"
set-option -g pane-border-style fg="colour20",bg="colour0"
set-option -g pane-active-border-style fg="colour20",bg="colour20"
```

> 補足：元記事で紹介されているようにコマンドのパスを通してみたのですが、どうもうまく動いてくれなかったので絶対パスに変更しています。

# シェルのプロンプト表示のタイミングでステータスラインをリフレッシュ

zsh のプロンプト表示のフックを使って、ターミナル内で tmux が起動していたらステータスラインを更新するよう設定します。

```bash
// ~/.zshrc
function precmd() {
  if [ ! -z $TMUX ]; then
    tmux refresh-client -S
  fi
}
```

> 参考）precmd のドキュメント
> http://zsh.sourceforge.net/Doc/Release/Functions.html

# tmux で使える色や特殊文字

tmux の設定に色や特殊文字の指定がチラホラありますが、これらをカスタムする時に @nojima さんの記事がとても参考になりました。
[tmux の status line の設定方法](https://qiita.com/nojima/items/9bc576c922da3604a72b)

# 完成！

<img width="700" src="https://user-images.githubusercontent.com/15980747/71682142-20821700-2dd2-11ea-824f-cf62fc9681ce.png">

ステータスラインに表示しているのは、このような情報です。フロントエンドナイズできたと思いませんか？？

- セッション名とペインの番号
- `NODE` アクティブな node のバージョン
- `PACKAGE` package.json から拾ったパッケージ名
- `BRANCH` git のブランチ名
- `STATUS` gitの状態

## うっかり防止機能付き

うっかり master や release ブランチにコミットしないように、これらのブランチをチェックアウトしている時は警告色で表示します。

<img width="800" src="https://user-images.githubusercontent.com/15980747/71682174-31328d00-2dd2-11ea-9cca-bc3146ab20bd.png">

rebase や cherry-pick でコンフリクトにすぐ気づけるように、処理が完了していない間は警告色で表示します。

<img width="800" src="https://user-images.githubusercontent.com/15980747/71682186-3d1e4f00-2dd2-11ea-96bb-71647c402625.png">

> ~~記事を書きながら rebase の操作中はブランチ名が in と表記されてしまう事に気づきました。いずれ修正しようと思います。~~
> 2020/01/09 tmux-pane-borderのGitブランチに関する判定を変更しました。
> （前） `git_branch="$(echo $git_status| awk 'NR==1 {print $3}')"`
> （後） `git_branch="$(git branch --contains| awk 'NR==1 {print $2}')"`


# おわり

これで tmux のセッション名をパッケージ名にせっせと揃える作業や、node のバージョン違いによるエラーから解放されそうです！ヤッタ！