Linux
xmonad
tmux

tmuxでXmonadライクで直感的なキーバインドを設定する

More than 3 years have passed since last update.


対象とする人

まず、前提として以下の様な人を対象にしています。


  • vimライクなキーバインドが体に染み付いている人

  • ペインの並び替え、ウィンドウ間の移動、ウィンドウの移動を多く行い、直感的な操作が好みの人(ペインを作ってしまってからウィンドウに配置したい人とも言う)

  • tmuxのキーバインドの再設定を考えている人


キーバインドに関して考えるべきこと

tmuxにかかわらず、キーバインドに関して考えるべきことは以下の要素だと考えています。


  • プレフィックスキーは押しやすく、他のアプリケーションのキーバインドと競合しないこと

  • ウィンドウとペイン、ペインの配置の関係を直感的に理解できるキーバインド

  • 操作とキーの意味の対応がつけられるようにしてあること

個人的にはさらに以下の条件をつけます。


  • Prefix + キー という2段階のキー入力(しかもプレフィックスはキーの同時押し)ではなく、(メタキー+キー)の組み合わせで操作できるものは、できる限りこの形式でキーを登録する。

以上の条件を満たすように、キーバインドを考えていきましょう。


プレフィックスキー

プレフィックスキーの設定にはその人の性格というか好みが現れるような気がします。つまり、何を重視しますか、ということです。僕の場合、先程の条件であげたように、押しやすい位置にあり、他のアプリケーションのキーバインドと競合しないことを条件としているので、ターミナル上でよく使うアプリケーションであるVimのキーバインドと競合しないか、ということを考える必要があります。

ググって見る限り、よくある設定としては、C-aC-zC-tC-o、"`"などがあるかもしれません。押しやすさを考えるなら、ホームポジションに近い方がいいでしょう。ただし、これらは既にキーバインドがある場合があるので、もし設定する場合には、Vimで:help CTRL-Tなどとしてデフォルトの設定を確認しておくといいでしょう。僕の場合、押しやすさと、キーバインドの使用率を考慮して、プレフィックスはC-gに割り当てました。Vimでは現在のファイル名とカーソルの位置の行番号や文字数を表示するキーバインドに割り当てられていますが、:set rulerしてあるので、全く使うことはないので問題ありません。他のキーの問題点は



  • C-a

    shellの行頭に移動のキーバインドと競合。よく使うので駄目。


  • C-z

    シェルをバックグラウンド処理にするのに使うキーバインドなので駄目。


  • C-t

    自分はこのキーをVimで新しいタブを開くのに使っているので使えない。"t"muxであることと押しやすさからすれば次候補だった。


  • C-o

    Vimで以前カーソルのあった位置に戻るのにC-iとセットで使うので。


  • C-h,j,k,l

    Vimのインサートモードでのカーソル移動に使うので駄目。

  • "`"

    押しにくくないですか?それとVimではmark全般はこのキーに依っているので駄目。

というわけで、押しやすさと、他のアプリケーションと競合しないことからC-gをプレフィックスにします。~/.tmux.confに以下を追記。

unbind-key C-b

# prefix key ^b -> ^g
set -g prefix C-g
bind-key C-g send-prefix


ウィンドウ・ペインの作成・削除、ペインの分割・移動、ペイン間の移動

以下に設定ファイルに書いた説明をのせ、それぞれに関してキーバインドの説明をしていきます。


# Prefix key: ^g
#
# Abbreviation:
# - [key]
# - {key} <- with Prefix key
# - (key) <- with Alt (or in MacOS, Command key)

略記は"[]"で囲ったキーはそのキーそのものを表しており、"()"は、メタキー(Linux、WindowsならAlt、MacならOpt)プラス何かキーを押すことを表しています。

基本的にはAltキーを押しながら操作する形にしており、Prefix + 何かキーという2段階の操作にはしていません。これは特にペイン間の移動やリサイズ時に威力を発揮するので、これだけでも設定する価値はあるかもしれません。


1セッション内のウィンドウとペインの構造関係

#

# Structure in one session:
#
# ------------------
# | (Left,Right) ↓(num) OR click status bar ↓ (Enter)
# window1 <------> window2 window3 window4
# ===============================================================
# pane1 pane1 pane1 pane1
# ↕ (j,k)
# pane2 - - - pane2 - - - -> (pane2)
# | [Shift+Right]
# (pane3) <- - pane3
# [Shift+Left] ↓ (x) ↓ (X)
# x x
#

ペイン間の移動は(j),(k)で行います。Vimと同じように{h},{j},{k},{l}でも移動できます。

# move between panes

# (xmonad like)
bind-key -n M-j select-pane -t :.+
bind-key -n M-k select-pane -t :.-
# (vim window like)
bind-key h select-pane -L
bind-key j select-pane -D
bind-key k select-pane -U
bind-key l select-pane -R

ウィンドウ間の移動は(Left),(Right)か(num)で移動します。

# move between window

bind-key -n M-Right next-window
bind-key -n M-Left previous-window

新しいウィンドウを作成するには(Enter)です。

# create new window

bind-key -n M-Enter new-window

ペインを削除するには(x)、ウィンドウを削除するには(X)です。if文を使うことで、最後のペイン、最後のウィンドウであるときにだけ確認メッセージを表示させることができます。

# if session has > 1 windows in current, kill-pane without confirmation.

# But confirm before killing pane when it is the last pane in the window.
bind-key -n M-x if "tmux display -p \"#{window_panes}\" | grep ^1\$" \
"confirm-before -p \"Kill the only pane in the window? It will kill this window too. (y/n)\" kill-pane" \
"kill-pane"

# if session has > 1 windows in current, kill-window without confirmation.
# But confirm before killing window when it is the last window in the session.
bind-key -n M-X if "tmux display -p \"#{session_windows}\" | grep ^1\$"\
"confirm-before -p \"Kill the only window in this session? It will kill the session too. (y/n)\" kill-window" \
"kill-window"

アクティブなペインを隣のウィンドウに移すのは[S-Left],[S-Right]です。新しいウィンドウに移す場合、デフォルトの通り{!}です。

# join pane

bind-key -n S-Right join-pane -t :+
bind-key -n S-Left join-pane -t :-

アクティブなペインをある番号のウィンドウに移すには(S-num)です。

# switch windows Alt+number

bind-key -n M-! join-pane -t :1
bind-key -n M-'"' join-pane -t :2
bind-key -n M-'#' join-pane -t :3
bind-key -n M-'$' join-pane -t :4
bind-key -n M-% join-pane -t :5
bind-key -n M-& join-pane -t :6
bind-key -n M-"'" join-pane -t :7
bind-key -n M-( join-pane -t :8
bind-key -n M-) join-pane -t :9


ウィンドウ内でのペインの操作

#

# In a window:
#
# +---------------+------------+
# |pane1 |pane3 |
# | | |
# | | |
# +---------------+ |
# |pane2 | |
# | | |
# | | |
# +---------------+------------+
#
# split pane:
# - vertically : (|)
# - horizontally : (-)
# select pane : (j,k) OR click the pane with mouse
# shift pane : (J,K)
# kill pane : (x)
# change layout : (Space)
# fullscreen : (f)
# resize pane:
# (a)
# ↑
# (h) ← + → (l)
# ↓ OR drag pane-border with mouse
# (z)
# join to another window : [Shift+Left/Right]
# join to another window : (Shift+num)
#

ウィンドウの分割は(-),(|)でそれぞれ文字の形の通りに分割します。またVim的に{s},{v}でも分割できます。tmuxとVimで見かけのオプションの文字が違うのは混乱のもと。

# split window (easily remember)

bind-key -n M-- split-window -v
bind-key -n M-| split-window -h
# vim like
bind-key s split-window -v
bind-key v split-window -h

ペインのスワップ(ペイン番号をずらす)は、(J),(K)

# swap pane

bind-key -n M-J swap-pane -D
bind-key -n M-K swap-pane -U

アクティブなペインを最大化するには(f)

# maximize pane ("f"ull screen)

bind-key -n M-f resize-pane -Z

ペインのレイアウトを変更するには(Space)

# next layout

bind-key -n M-Space next-layout

ペインのリサイズをするには、(a),(z),(h),(l)で上下左右に境界を動かすことができます。

# resize panes (xmonad like)

bind-key -n M-h resize-pane -L 1
bind-key -n M-z resize-pane -D 1
bind-key -n M-a resize-pane -U 1
bind-key -n M-l resize-pane -R 1


まとめ

直感的なキーバインドを設定し、tmuxを使った作業が捗るようになりました。ぜひ現在のキーバインドに引っ掛かりを感じている人は、これを機に設定を見なおしてみるといいかもしれません。

こちらにあげてありますので、参考にしてください。

(この記事を書いた時点から変更されています)