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

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

全体像

簡略化した全体像は次のとおりです。

function ftmux_resurrect() {
# 処理
}
zle -N ftmux_resurrect
bindkey '^xt' ftmux_resurrect
  1. 関数を定義
  2. ZLEのウィジェットとして登録
  3. Ctrl+x,tで呼び出せるように設定

ディレクトリ移動

ここから、実際にスクリプトを解説します。

まずはディレクトリの移動です。前述の「レイアウトファイルの保管ディレクトリ」へ移動します。

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で絞り込むコマンドと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が実行されます。

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って生き返らせる、とか復活させるって意味です。そのまんまじゃん!