僕の考えたいいかんじのTmux セッション管理

この記事はdotfileアドベントカレンダーの16日目です！

# はじめに
私はtmuxでリポジトリごとにセッションを立ち上げて管理しています。
1リポジトリ1セッションという形です。

セッション管理をいい感じにするscriptを書いていたのですが
いい感じのができたので紹介です。

# そもそもtmux?session?
tmuxとは[ターミナルマルチプレクサ](http://linuxcommand.org/lc3_adv_termmux.php)の一つで、
  
- マウスでいい感じに操作することができ
- アタッチ, デタッチといった概念があり
- iterm2のように画面分割機能,タブ機能が存在し、さらにセッションと言う概念がある
- それらをtmux.confなどといった設定ファイルにより自由自在に設定できる

といった機能があります。  
他にも`GNU screen`などがターミナルマルチプレクサとしてあげられます。  

- [ターミナルマルチプレクサ tmux をカスタマイズする - Qiita](https://qiita.com/b4b4r07/items/01359e8a3066d1c37edc)
- [tmuxを使い始めたので基本的な機能の使い方とかを整理してみた - 完熟トマト](http://kanjuku-tomato.blogspot.com/2014/02/tmux.html)
- [tmux基本のコマンド — nato's memo 1.0 documentation](http://room6933.com/tmux/tmux-basic.html)

多くのvimmerがiterm2やTerminal.app上で直にvimを立ち上げずに
tmux上で立ち上げ操作しています。

# リポジトリをセッションで管理しよう!
iTerm2やTerminal.appにはタブ機能や画面分割機能がありますよね？
![BaVMTtN.png (1910×1268)](https://i.imgur.com/BaVMTtN.png)
1つのウィンドウの中に複数のタブを開き、その中で画面分割を行っていると思います。
tmuxにもタブ機能や画面分割機能に対応するものがあるのですが、さらにもう一つセッションというものがあります。  
iTerm2でいう**一つのウィンドウの中のタブの中の画面分割**というように
Tmuxの**セッションの中のWindowの中のペイン**というものです。  

![3jXgNqQ.png (1602×888)](https://i.imgur.com/3jXgNqQ.png)

ここで面白いのが、userが一つの端末(Terminal.appやiTerm2)などから
**どのセッションに接続するか**をいつでも自由自在に変更できるのですよね。  
![X0jVBKQ.png (1602×888)](https://i.imgur.com/X0jVBKQ.png)

ここで私は1つのリポジトリにつき1つのセッションを開いて管理しているわけです。
iTerm2などで1つのリポジトリにつき1つのウィンドウを開いているようなものですね。  



## リポジトリごとセッションで管理するpros/cons
### cons
- セッション管理が大変
- 移動が面倒くさい
- tmuxのデフォルトの移動機能はいまいち
- コマンドでやろうとするとtmux内かtmux外かでコマンドを変える必要がある

### pros
- レポジトリごとセッションで別けると整然としてる
- 1セッションごとにルートリポジトリを設定するので丁寧に設定してからセッションを立ち上げると快適
- ウィンドウを開きすぎて爆死しない
- なんか他にもあるだろうけどtmux突き詰めてくと自然にこれになる(暴論)

## セッションを快適に管理する先人たちの工夫
### 尊敬するb4b4r07氏のtmuxx
- [dotfiles/tmuxx at master · b4b4r07/dotfiles](https://github.com/b4b4r07/dotfiles/blob/master/bin/tmuxx)
自動でアタッチもしくは新規セッション立ち上げができるscript.  
シンプルで良いけどもうちょっと他の作業もscriptにやってもらいたい


### fzfでtmuxのセッションをあいまい検索する
- [tmuxのsessionをfzfで選択できるようにする。 - Qiita](https://qiita.com/hokita222/items/b5d0b168e53d737f4d37)
fzfであいまい検索することができる。  
とても良いけどもう少し快適にしたい(セッション名を意識しなければならない)(セッション名の変更は自動化できそう)

# 自分が一番必要としてるものは自分が一番作ることができる
[2357gi/ghux: Select a project from ghq list, launch (or select) a tmux session in one action.](https://github.com/2357gi/ghux)  

- fzfを用いたあいまい検索でセッションを移動することが可能
- セッション名も自動で設定してくれる
- zle-widgetを用いて直感的な操作が可能
- tmuxにすでにアタッチしているか否かを考える必要がない
- 移動先のセッションが存在するかどうか考えずに移動が可能(もしセッションが存在しなければ自動でつくる)

## how to install
Zplug等をお使いであれば

```zsh
zplug 2357gi/ghux
```
で(zplug等でも使える形式にはしたけど自分ではテストしてません...)  

そうでなければ適当にscriptを配置してsourceしてください  

```zsh:e.g.
source ~/.zsh/ghux/ghux.plugin.zsh

```

zle-widgetに対応しているので、  

```zsh
bindkey ^G ghux
```

でWidgetとして使用できます。  
zle-widgetについてはこちら
[Macがzshになるなら、ZLEを習得するっきゃない！ ｜ Developers.IO](https://dev.classmethod.jp/tool/zsh-zle-introduction/)


## 使い方
まず`~/.ghux_aliases`というファイルを作り、そこに`,`区切りで

```txt:~/.ghux_aliases
<alias名>,<セッション名>,<レポジトリのフルパス>

e.g.
Dotfiles,dotfiles,$HOME/dotfiles
```

と登録します。
その状態でghuxを起動するとfzfで先程登録したalias名が並び、
そこから選択することで`<セッション名>`のsessionが立ち上がります。
セッションのルートディレクトリも設定したフルパスが適用されるので、
新しくWindowを立ち上げたりペインを切ったりしてもディレクトリがいい感じになります。

また、**登録したセッションがすでに立ち上がっている/立ち上がっていないに関わらず**同じアクションでセッションに接続することができます。  

![5WLUece.gif (500×281)](https://i.imgur.com/5WLUece.gif)
gitでやっていること
- ghux_aliasesを編集した後, tmux外からghuxを用いてセッションを開く
- その後tmuxの別のセッションから同じコマンドで同セッションを開く
- 別セッションで該当セッションを削除した後、同じコマンドで同セッションを立ち上げる

また、`$ ghux <alias名>`にすることにより、  
fzfを挟むことなく`new-session / switch-session`することができます。

### zle-widgetに対応
zle-widgetに対応しているので、`bindkey ^G ghux`なりの設定で更にいい感じにできます。  


## ghqと連携することにより真価を発揮

### ghqとは
このscriptは`ghq`というものと一緒に使うことを前提に作成してきました。  

ローカルリポジトリを統一的に管理しようということで作られたcli toolです。  
これはgolangのリポジトリ管理のお作法をローカルリポジトリの管理にも適用しようという思想のもと作られたものです。  

簡単に言うと`~/src/`というディレクトリ以下にて一定の規則に則りリポジトリを格納するものです。  

```shell
 > tree -L 2 ~/src
/Users/2357gi/src
├── github.com
│   ├── 2357gi
|    |    ├── ghux
|    │   └── dotfiles
│   ├── Blueqat
│   ├── akanazawa
│   ├── arks22
│   ├── bogaotory
...
├── golang.org
│   └── x
```

更に詳しい説明はこちら
- [ghq: リモートリポジトリのローカルクローンをシンプルに管理する - 詩と創作・思索のひろば](https://motemen.hatenablog.com/entry/2014/06/01/introducing-ghq)
- [ghqを使ったローカルリポジトリの統一的・効率的な管理について - Kentaro Kuribayashi's blog](https://blog.kentarok.org/entry/2014/06/03/135300)
- [さいつよのターミナル環境を構築しよう - Qiita](https://qiita.com/b4b4r07/items/09815eda8ef72e0b472e#ghqgo-%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB)

### ghqとghuxの連携
先述したとおり私は1レポジトリを1tmux sessionとして運用しています。  
この運用を加速させるためにghuxを作成しました。  
ghqを用いて管理しているローカルリポジトリに限って、  
先程のように`~/.ghux_aliases`というファイルを編集することなく、ghuxから操作できます。  
![OACnexr.gif (500×321)](https://i.imgur.com/OACnexr.gif)  
*ghqにてリポジトリをcloneし、~/.ghux_aliasesを編集せずにそのままghuxでそのリポジトリのセッションを立てるデモ*

これにより、快適なtmuxライフを送ることができます。  

# オワリに
ghqを用いたローカルリポジトリの管理も、
1セッション1リポジトリの原則もとても良いので、
vimなどをtmuxと組み合わせて使用している人はぜひともghux試してみてください。

tpmでいい感じにできたらtmux pluginにしたほうがいい感じになれるかもしれない...(TODO)