tmuxを使おう

![ink (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4244/fa8ebfca-d643-7216-6b8f-550d16df1ffd.png)

私が4年前にweb業界に転職する前はJavaのデスクトップアプリケーションを開発していたのですが、他の人の黒い画面を見ては「あの黒い画面に表示されている枠はなんなんや？」と思っていました。実際に使ってみると生産性が3倍（当人の感覚）になりました。

特に開発環境はIDE派の方は、tmuxを使うことでCUI環境もIDEのように見せられます。 早速見ていきましょう。

## tmuxとは？

https://github.com/tmux/tmux

tmux は Terminal Multiplexer の略です。multiplexerとは多重化する、という意味です。一つのターミナル環境の中に複数ターミナルを作成できるのが tmux です。わかりやすいですね。

### インストール方法

homebrew でも入るので

```
$ brew install tmux
```

で良いでしょう。

## 基本的な使い方

tmux で登場する概念をざっと図にすると下記のようになります。

![plantuml.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4244/b2f7a840-baed-7d39-4032-2f9d000fa6a1.png)


tmux が入っているホストで

```
tmux
```

というコマンドを叩くと tmux の session まで立ち上がります。

ここで `<prefix> d` とすると session を detach し、tmuxの session を抜けます。 `<prefix>` は何も設定していない場合は `Ctrl+b` です。
ですので、この表記の場合は `Ctrl+b` を押したあとに `d` を押してください。セッションは抜けられたでしょうか？

現在実行中のセッションがいくつあるか確認してみましょう。

```
tmux list-sessions
0: 1 windows (created Sun May 31 16:03:47 2020)
```

こんな形で起動中のセッションが表示されます。もとのセッションに接続したい場合は

```
tmux attach <-t sesssion-name>
```

としましょう `<>` で囲んだ部分はオプションです。必要に応じてセッション名を入力してください。

### Window と Pane の操作

ところで、tmuxコマンドは tmux セッションの中でも実行可能です。

```
tmux new-window
```

とすると新たなWindowが開きます。 

```
tmux select-window -t 0
```

とすると、元のWindowに切り替わります。

```
tmux split-window -h
```

とすると、Windowが縦に2分割され、Pane（枠）が作成されます。操作対象のPaneも切り替えられます。

```
tmux select-pane -L
```

で左側のPaneに戻ります。`exit` すると実行中のプロセスが完了するので、Pane を閉じます。

### tmux コマンド操作をショートカットする

続いて、`<prefix> :` と入力した後、 `select-window -t 1` としてみましょう。Windowが切り替わるはずです。

`<prefix> :` はtmuxの中から tmux server にコマンドを送るショートカットです。`<prefix> :` としたあとに `list-sessions` と入力するとセッション一覧が表示されます。

tmux のセッションの中から tmux コマンドを実行する場合は `<prefix> :` を使いましょう。

### 設定ファイルを使ってWindowやPaneの操作ができるショートカットを作る

まずは `<prefix>`が `ctrl+b`  だと不便なので、`ctrl+a` に置き換えてみましょう。 tmux の設定ファイルは `~/.tmux.conf` に置きます。

```:~/.tmux.conf
set -g prefix C-a
unbind C-b

# C-a*2でtmux内のプログラムにC-aを送る
bind C-a send-prefix
```

とおいた後、 `tmux source-file ~/.tmux.conf` とするか、 `<prefix> :` の後、 `source-file ~/.tmux.conf` としましょう。

`<prefix>` が `ctrl+a` に置き換わります。 tmux.conf の中で `Ctrl+` という操作は `C-` と表記します。tmux内のコマンドに `Ctrl-a` が送れないと困るので、 `bind C-a send-prefix` も定義しておきましょう。 `ctrl+a` を2回操作すると tmux 内のプロセスに `Ctrl-a` が送られます。

この後設定ファイルにどんどん追加していくので、この設定ファイルの読み込みもショートカットにしましょう。`~/.tmux.conf` に次の一行を追加します。

```:~/.tmux.conf
bind r source-file ~/.tmux.conf \; display "Reloaded!"
```

再度、`tmux source-file ~/.tmux.conf` とするか、 `<prefix> :` の後、 `source-file ~/.tmux.conf` とします。すると、`<prefix> r` が設定ファイルの更新ショートカットに変わります。試しにやってみてください。ステータスバーに `Reloaded!` と表示されたはずです。tmux を使っていて繰り返し行うようなコマンドは、随時 `~/.tmux.conf` に追記して育てていくと良いでしょう。

私が使っている Window と Pane の操作を楽にする設定を書いてみると、

```:~/.tmux.conf
# Launch login shell
set-option -g default-shell "${SHELL}"
set -g default-command "${SHELL}"

# | でペインを縦に分割する
bind | split-window -h -c '#{pane_current_path}'

# - でペインを横に分割する
bind - split-window -v -c '#{pane_current_path}'

# c で新しいウィンドウを作成する
bind c new-window -c '#{pane_current_path}'

# Vimのキーバインドでペインを移動する

bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

# Window setting

bind -r C-h select-window -t :-
bind -r C-l select-window -t :+

bind-key -n M-< swap-window -t -1
bind-key -n M-> swap-window -t +1

# VimのキーバインドでPaneをリサイズする
bind -r H resize-pane -L 5
bind -r J resize-pane -D 5
bind -r K resize-pane -U 5
bind -r L resize-pane -R 5

# マウス操作を有効にする
setw -g mouse
```

こんな感じです。 私がよく使うキーバインドをまとめると、

| キーバインド | 操作 |
----|----
| `<prefix> [` | コピーモードを開始。現在のPane内のコンテンツのスクロールやbufferへのコピーを行う。コピーはスペースで開始 |
| `<prefix> ]` | bufferの内容を貼り付ける |
| `<prefix> c` | Windowを作成する |
| `<prefix> 1` | Windowを1を開く。1の部分は 0-9 までの数字を指定できる。要するにWindow切り替えのキーバインド |
| `<prefix> -` | Pane を作成し、横に分割する |
| `<prefix> |` | Pane を作成し、縦に分割する |
| `<prefix> z` | 操作対象の Pane のみ表示する / 他の Pane も合わせて表示する（トグル） |
| `<prefix> h` | 操作対象の Pane を左に切り替える |
| `<prefix> j` | 操作対象の Pane を下に切り替える |
| `<prefix> k` | 操作対象の Pane を上に切り替える |
| `<prefix> l` | 操作対象の Pane を右に切り替える |
| `<prefix> H` | 操作対象の Pane を左に広げる |
| `<prefix> J` | 操作対象の Pane を下に広げる |
| `<prefix> K` | 操作対象の Pane を上に広げる |
| `<prefix> L` | 操作対象の Pane を右に広げる |

という感じです。 `bind c new-window -c '#{pane_current_path}'` で登場する `-c #{pane_current_path}` は 現在のPaneのpath(pane_current_pathという変数)を `new-window` コマンドの `-c` オプションに与えています。言い換えると `新しいWindowを現在選択中のPaneのパスで開く` ということです。利用可能な変数等は `man tmux` を開くと良いでしょう。

## 快適な tmux 生活を支えるユーティリティ

### tmux plugin manager(tpm)

https://github.com/tmux-plugins/tpm

tmux は割と簡単に拡張ができるので、プラグインが配布されています。

### ステータスバーの表示をカスタマイズ

いい感じのステータスバー表示がほしい方は tmux themepack を入れれば手に入ります。

https://github.com/jimeh/tmux-themepack

自前でカスタマイズされたい方は、 `set -g status-left`, `set -g status-right`, `set-window-option -g window-status-format`, `set-window-option -g window-status-current-format` 等で表示するコンテンツを指定し、色やスタイルを指定していくと良いでしょう。

### Window / Paneを管理する tmuxinator

https://github.com/tmuxinator/tmuxinator

tmuxinator は yaml を書いて Window / Pane を一括管理するツールです。
一点欠点があるとすれば、 ruby に依存しているツールです。開発環境で使っているrubyとバッティングすることがあります。
中を見ると愚直に `tmux` コマンドを打っていくだけなので、 go か rust で開発してバイナリを配布すると良さそうですよね。

### tmux上に表示された Git SHAs 等をサクッとコピーする tmux-thumbs

デフォルトの設定だと `<prefix> space` を押すと、 Git SHA っぽい文字列だったり、IPアドレスっぽい文字列をさくっと buffer(コピーするための領域)にコピーしてくれるツールです。

## FAQ

### 書籍はないの？

今の所日本語で詳細がまとまった書籍はないようです。（技術書展とかであるのかな）

洋書だと

- [tmux 2](https://pragprog.com/book/bhtmux2/tmux-2)
- [The tao of tmux](https://leanpub.com/the-tao-of-tmux/read)

私は `tmux 2` を読んで学びましたが、 `The tao of tmux` も一つずつ使い方が学べそうです。