macOSのターミナルで複数タブの履歴を分けたい

Mac

まあ、タイトルの通りなんだけども、ttys000からttys004みたいな感じでタブを複数同時に開いているものの、それぞれのタブで作業する内容はほぼ固定されていて、macOSを再起動した後にも同じ作業を履歴から実行したい。タブ毎にhistoryを保存し、それを次回起動時に読み出す方法は無いんかなぁ、ということで弄くり回したところ、結構厄介な問題があることが分かった。

履歴の保存のフロー

まず、zshがどのようにhistoryを保存しているかというと、~/.zsh_sessions/に$TERM_SESSION_ID.historynewというファイルを作成し、これは$HISTFILEに設定されている。

% echo $HISTFILE
/Users/rifujita/.zsh_sessions/7BB7882E-5A7F-48FC-B619-DA5894386606.historynew

で、そのプロセス(tty)が終了すると、~/.zsh_sessions/に、$TERM_SESSION_ID.historyと$TERM_SESSION_ID.sessionというファイルに記録する。

% cat .zsh_sessions/7BB7882E-5A7F-48FC-B619-DA5894386606.session 
echo Restored session: "$(/bin/date -r 1729569658)"

% cat .zsh_sessions/7BB7882E-5A7F-48FC-B619-DA5894386606.history 
exit
cd .zsh_sessions
...

2つのタブを開いて作業すると、たぶん以下のように動作する。

  1. ttys000が起動、.zsh_historyを読み込む
  2. ttys001が起動、.zsh_historyを読み込む
  3. ttys000でコマンド[1]を実行、メモリ上のhistoryに保存される
  4. ttys001でコマンド[2]を実行、メモリ上のhistoryに保存される
  5. ttys000を終了、.zsh_history + コマンド[1]がttys000の$TERM_SESSION_ID.historyに保存される。
  6. ttys001を終了、ttys000の$TERM_SESSION_ID.history + コマンド[2]がttys001の$TERM_SESSION_ID.historyに保存される。ここで、ttys001で実行していないコマンド[1]がhistoryに混入する。

むぅ、なんでマージしちゃうんだ…。unsetopt share_historyしても、この挙動は変わらなかった。

trapしよう

ちょっと考え方を変えて、そもそものzshの履歴保存のフローをイジることを諦め、ttyの終了時に独自の方法で履歴を保存することを考えた。.zprofileに以下を追加する。

MYTTY=`basename $(tty)`
last_session_history=$(ls -t -1 $HOME/.zsh_sessions/${MYTTY}*.history | head -n 1)
cp -f $last_session_history $HOME/.zsh_history
trap 'history | sed "s/^ *[0-9]* *//" > $HOME/.zsh_sessions/$MYTTY-$TERM_SESSION_ID.history' EXIT

1行目で、タブが対応しているttyを取得する。
2行目で、前回の終了時に保存された履歴の最も新しいhistoryファイルを見つける。
3行目で、上で見つけたhistoryファイルを、.zsh_historyとして上書きコピーする。
4行目は、タブの終了時(ttyからの切断時)に、historyコマンドを実行し、tty名-セッションID.historyというファイルに保存する。これは、次回起動時に、そのtty用のhistoryファイルとなる。

スクショが撮れないので、タブではなくマルチウインドウでやってみたのが以下。まず、ttys000で存在しないコマンド”1″を、ttys001で”2″、ttys002で”3″を実行し、ターミナル.appを終了する。

ターミナル.appを起動して、ウインドウを複数開いて、historyコマンドを実行する。

tty毎に履歴を保存できていることが分かる。

追記:I wanted to separate the command histories for each tabs / windows with zsh on macOS.