tmux-resurrectの復活に失敗した時の対応

· 8 min read

tmuxでウィンドウやペインのレイアウトを保存できるプラグインtmux-resurrectがあります。tmux-continuumも併せて使うことでtmux立ち上げ時に自動で保存時の状態へ復帰できますが、たまに復帰できません。

これを解決する方法と、fzfを使って任意の状態に復帰する例を紹介します。

fzfでtmuxの復活先を選ぶ例

以前に同じ題材で書いた記事では、fzfを使わずに少し手順が煩雑だったため改良しました。

tmux-resurrectで自動復帰できなかった時の対応

まずは手動での対応方法です。

実は公式ドキュメントに書いてありますがもう少し詳しく解説します。

基礎知識

tmux-resurrectはテキストファイルとして状態を保存します。ファイルは~/.tmux/resurrect/または~/.local/share/tmux/resurrectで管理されます。
save_dir.mdを読むと、このディレクトリは変更できるようです。

最新の状態はlastというファイルにシンボリックリンクされています。
このリンク先のファイルを変えることで、復帰するレイアウトを変更できます。

手順

そんなわけで、手順はつぎのとおりです。

  1. 保管されているディレクトリへ移動する
  2. 復活したいファイルを選ぶ
    a. ファイル名はタイムスタンプになっている
    b. 例:tmux_resurrect_20240512T091818.txt
  3. ln -sf ファイル名 last
    a. 例:ln -sf tmux_resurrect_20240512T091818.txt last
  4. tmux-resurrectの復帰するキーバインドを入力
    a. 例:prefix,Ctrl+r

自動復帰できないことは多くありませんが、その度にこの手順を踏むのは少し面倒です。というわけでこれをfzfを使って解決します。

これを使えばレイアウトを数種類に分けて保存し、切り替えることもできます。

tmuxの復活先を選択する関数

本記事ではZshを使っていますが、他のシェルでも似たように書けると思います。

先に全体を載せ、次の項目から小分けで解説していきます

function ftmux_resurrect() {
local pre_dir=$(pwd);
if [ -e "$HOME/.tmux/resurrect" ]; then
cd ~/.tmux/resurrect
elif [ -e "$HOME/.local/share/tmux/resurrect" ]; then
cd ~/.local/share/tmux/resurrect
else
echo "resurrect directory not found"
zle accept-line
return 1
fi
local can_bat='type bat > /dev/null'
local bat_command='bat \
--color=always \
--theme=gruvbox-dark {}'
local alt_command='cat {} | head -200'
local fzf_command="fzf-tmux -p 80% \
--preview '( ($can_bat) && $bat_command || ($alt_command) ) 2> /dev/null' \
--preview-window 'down,60%,wrap,+3/2,~3'"
local result=$(
find . -name 'tmux_resurrect_[0-9]*.txt' \
| sort -r \
| eval $fzf_command
)
if [ -n "$result" ]; then
ln -sf $result last
echo "link!"
else
echo "No link..."
fi
cd $pre_dir
zle accept-line
}
zle -N ftmux_resurrect
bindkey '^xt' ftmux_resurrect

全体像

全体像は次のとおり。関数を定義し、ZLEのウィジェットとして登録し、Ctrl+x,tで呼び出せるように設定しました。

function ftmux_resurrect() {
# 処理
}
zle -N ftmux_resurrect
bindkey '^xt' ftmux_resurrect

ディレクトリ移動

まずはディレクトリの移動です。前述のレイアウトのファイルが保管されているディレクトリへ移動します。

local pre_dir=$(pwd);
if [ -e "$HOME/.tmux/resurrect" ]; then
cd ~/.tmux/resurrect
elif [ -e "$HOME/.local/share/tmux/resurrect" ]; then
cd ~/.local/share/tmux/resurrect
else
echo "resurrect directory not found"
zle accept-line
return 1
fi

保管ディレクトリを変更している人はここも変更してください。

fzfのコマンドを用意

続いて、fzfで絞り込むコマンドとそのときにプレビューで使うコマンドの用意です。

local can_bat='type bat > /dev/null'
local bat_command='bat \
--color=always \
--theme=gruvbox-dark {}'
local alt_command='cat {} | head -200'
local fzf_command="fzf-tmux -p 80% \
--preview '( ($can_bat) && $bat_command || ($alt_command) ) 2> /dev/null' \
--preview-window 'down,60%,wrap,+3/2,~3'"

正直今回はbatを使う理由はほとんどないですが、次にfzfを使った関数を用意するときにコピペできるなぁという考えなので許してください。必要に応じて削ってください。

今回扱うファイルはファイル名がタイムスタンプになっているため、そもそもプレビューすらいらない人もいるかもしれませんね。

fzfのオプションについては別の記事で解説しています。気になる方はどうぞ。

fzf-tmuxとfzfの関係

「ちょっと待った!fzf-tmuxで誰だよその男!」
そう思った方もいるかもしれません。

実はfzfはtmuxのポップアップウィンドウで表示できるコマンドfzf-tmuxが用意されています。tmuxが使えない場合はtmuxのレイアウト指定のオプション-p 80%は無視されます。

fzf-tmuxのオプションの詳細はfzf-tmux --helpから見ることができます。

ちなみに、筆者は以前、次のようにfzf-tmuxfzfの分岐をしていました。これは無駄な分岐ということです。

local fzf_command="fzf"
if type fzf-tmux > /dev/null; then
fzf_command="fzf-tmux -p 80%"
fi

実際に絞り込む一連のコマンド

findを使ってファイルをかき集め、sortで最新のものが一番上になるようにしてからfzfに渡します。

local result=$(
find . -name 'tmux_resurrect_[0-9]*.txt' \
| sort -r \
| eval $fzf_command
)

リンク

あとはリンクと後片付けをして終了です。

if [ -n "$result" ]; then
ln -sf $result last
echo "link!"
else
echo "No link..."
fi
cd $pre_dir
zle accept-line

実行

ファイルは降順にソートしているため、だいたいの場合はCtrl+x,tで呼び出してそのままEnterを押してリンクできます。後はtmux-resurrectの復帰するキーバインドを入力するだけです。

自動復帰に失敗した状態でレイアウトを保存してしまったとき、少し前のレイアウトに戻したい場合はプレビューを見ながら任意のファイルを選択しましょう。

fzfでtmuxの復活先を選ぶ例

ちなみにresurrectって生き返らせる、とか復活させるって意味らしいです。そのまんまじゃん!