以前、「リモートtmuxでコピーできない原因はmoshだった件 」という記事を書きました。そのときは、mosh + tmux + OSC 52 の組み合わせは不安定なので、素直にSSHへ寄せるのがよさそう、という結論でした。
その後、設定を見直したところ、今回の環境では mosh + tmux でも端末側の範囲選択から Cmd-C コピーが問題なくできました。結論から言うと、効いたのは mouse off と allow-passthrough on の組み合わせです。
先に結論
目的は、tmux内でも端末側の通常の範囲選択を使い、必要なエスケープシーケンスを外側の端末へ通せるようにすることです。前提として、tmux 3.3以降では passthrough sequence を使うには allow-passthrough の設定が必要です。
set -g mouse off
set -g allow-passthrough on
自分の環境では、この2行で mosh + tmux のまま、iTerm2側の範囲選択から Cmd-C でコピーできるようになりました。
.tmux.conf を複数環境で共有していて、古いtmuxでも読み込ませる可能性がある場合は、q 付きにしておく方が安全です。古いtmuxが知らないオプションを見ても、エラーで止まりにくくなります。
set -g mouse off
set -gq allow-passthrough on
allow-passthrough all という指定もありますが、これは tmux 3.4 以降の話です。tmux 3.3 も考えるなら、まずは on にしておくのが無難です。
なぜ mouse off が効いたのか
まず、mouse off です。
tmuxで mouse on にしていると、ペインの選択、スクロール、範囲選択などのマウスイベントをtmuxが受け取ります。これはtmux上でマウス操作をしたい場合には便利です。
一方で、端末アプリ側の普通の範囲選択を使いたい場合には邪魔になることがあります。今回やりたいのは、tmuxのコピーモードではなく、外側の端末でドラッグ選択して Cmd-C する運用です。
tmux FAQ でも、tmuxのmouseは基本的に「全部受け取る」か「全部受け取らない」かで、端末側の選択と細かく分担するものではない、という説明になっています。
つまり、mouse off はこういう意味です。
- tmuxがマウスイベントを全部奪わない
- 外側の端末が通常の範囲選択を扱える
- 端末側の Cmd-C コピー運用に戻せる
自分の場合、ここがかなり重要でした。tmuxのmouse操作は便利ですが、コピーだけを見ると端末側に任せた方が安定する場面があります。
また、mouse off にしてtmux側のマウス選択サポートを使わなくても、端末アプリ側が範囲選択とコピーをきちんとサポートしていれば、実用上はほぼ問題ありません。むしろ、手元の端末で見えている文字列をそのまま選択して Cmd-C できるので、通常のコピー操作としてはこの方が自然です。
なぜ allow-passthrough on が効いたのか
次に、allow-passthrough on です。
tmuxには、内側のアプリが外側の端末へエスケープシーケンスを通すための passthrough sequence があります。形式としては、ざっくり次のような形です。
この例は概念を示すためのものです。実際には、内側のアプリやプラグインがOSC 52などのエスケープシーケンスをこの形で包み、tmuxの外側にある端末へ渡そうとします。
|
|
tmux 3.3 以降では、この passthrough sequence を使うには allow-passthrough を on または all にする必要があります。
tmux CHANGES
には、tmux 3.3 で passthrough escape sequence を制御するオプションが追加され、デフォルトは off になった、という変更があります。また、tmux man page
にも allow-passthrough の説明があります。
今回のケースでは、OSC 52 をtmux越しに通す問題と、端末側のマウス選択をtmuxが奪う問題が同時に絡んでいた可能性が高いです。
そのため、mouse off だけでもなく、allow-passthrough on だけでもなく、両方を入れることで安定したのだと思います。
tmuxのバージョン感
allow-passthrough まわりは、tmuxのバージョンで挙動が変わります。ざっくり整理すると、次のようになります。
| tmuxバージョン | allow-passthrough |
メモ |
|---|---|---|
| 3.2a以前 | なし | オプション自体がないため、共有設定では注意が必要です |
| 3.3 | on が使える |
passthrough sequence を通すには設定が必要です |
| 3.4以降 | on / all が使える |
all では invisible pane でも通せるようになっています |
.tmux.conf を1台だけで使うなら、使っているtmuxのバージョンに合わせれば十分です。
複数のLinuxサーバやmacOS環境で同じ設定を使い回すなら、tmux 3.3を基準にして set -gq allow-passthrough on にしておくのが扱いやすいと思います。
.tmux.conf に入れるなら
実際に .tmux.conf に入れるなら、まずはこのくらいで十分です。
この設定は、tmuxのマウス操作を諦める代わりに、端末側の通常選択を優先する構成です。tmux 3.3未満でも設定ファイルを共有する前提なら、allow-passthrough には q を付けています。
# 端末側の通常選択を使う
set -g mouse off
# tmux 3.3+ で passthrough sequence を許可する
# 古い tmux と設定を共有するため q を付ける
set -gq allow-passthrough on
設定後は、新しいtmuxセッションを開くか、既存セッションで設定を読み直します。
このコマンドは、現在のtmuxサーバに .tmux.conf を再読み込みさせるためのものです。設定ファイルのパスがデフォルトの ~/.tmux.conf である前提です。
|
|
確認するときは、moshで接続した先のtmux内で適当な長いテキストを表示し、端末側でドラッグ選択して Cmd-C してみます。macOSなら、手元のエディタなどに貼り付けられれば成功です。
注意点
この設定は、自分の環境ではうまく効きました。ただし、万能ではありません。
まず、mouse off にすると、tmux側のマウス操作は使いにくくなります。ペインの選択、リサイズ、スクロールなどをマウスでやっていた人にはトレードオフがあります。
ただし、端末アプリ側の範囲選択が十分に使えるなら、少なくともコピー操作については大きな問題になりにくいです。今回の目的は「tmuxをマウスで操作すること」ではなく、「表示されている文字列を手元のMacへ素直にコピーすること」なので、端末側に任せる構成で割り切れます。
次に、OSC 52自体の形式問題や、端末アプリ側の対応状況が消えるわけではありません。OSC 52をどこで生成しているか、どの端末で受けているか、moshがどこまで透過しているかによって結果は変わります。
また、mosh はSSHと同じではありません。UDPベースでローミングに強い一方、端末制御シーケンスまわりではSSHと完全に同じ挙動を期待しない方がよさそうです。
今回の設定は、あくまで「tmuxの外側にある端末の通常選択を使う」運用に寄せています。tmux内のコピーモードやOSC 52連携を完璧に直す、というより、日常的なコピー操作を安定させるための設定です。
まとめ
以前は、mosh + tmux + OSC 52 は不安定なのでSSHへ寄せる、という結論にしていました。
ただ、今回の環境では次の設定で、mosh + tmux のまま Cmd-C コピーできました。
set -g mouse off
set -gq allow-passthrough on
ポイントは2つです。
mouse offで、端末側の通常選択を使えるようにするallow-passthrough onで、tmux越しの passthrough sequence を許可する
tmuxのmouse操作を重視するなら合わないかもしれません。逆に、自分のように「リモートtmux上の表示を、手元の端末で普通に選択してコピーしたい」という運用なら、端末側の選択機能だけで実用上ほぼ十分です。かなり実用的な落としどころだと思います。