よくある設定
ウィンドウを左右に移動させる一般的な設定はこれ。
bind -n M-S-Left swap-window -t -1\; prev
bind -n M-S-Right swap-window -t +1\; next
問題
上記の設定だと、端で反対側のウィンドウと入れ替わってしまう。
例えば [A] B C D で A を左に移動したら B C D [A] のように循環させたいのに、単純に swap-window -t -1 を使うと以下のようになる。
[A] B C D
↓ Aを左に移動
D B C [A] # AとDが入れ替わってしまう
また move-window は既存のインデックスと衝突すると index in use エラーになる。
解決策
端にいるときだけ、ウィンドウ数 - 1 回だけ反対方向に swap を繰り返す。
bind -n M-S-Left if-shell -F '#{==:#{window_index},0}' 'run "for i in \$(seq 1 #{e|-:#{session_windows},1}); do tmux swap-window -d -t:+1; done"' 'swap-window -d -t:-1'
bind -n M-S-Right if-shell -F '#{==:#{window_index},#{e|-:#{session_windows},1}}' 'run "for i in \$(seq 1 #{e|-:#{session_windows},1}); do tmux swap-window -d -t:-1; done"' 'swap-window -d -t:+1'
解説
if-shell -Fで tmux のフォーマット式として評価#{==:#{window_index},0}で現在のウィンドウが先頭かどうかを判定#{e|-:#{session_windows},1}でsession_windows - 1(最後のインデックス)を計算swap-window -d -t:-1の-dでフォーカスを維持-t:-1/-t:+1で相対位置を指定(コロン必須)- 端にいる場合は
runでシェルを呼び出し、ループで反対方向に swap を繰り返す
一言
tmux の設定は毎回試行錯誤になる。move-window が素直に動いてくれればよかったのだが、相対指定やインデックスの扱いが微妙で結局 swap-window のループに落ち着いた。