diff --git a/docs/restoring_bash_history.md b/docs/restoring_bash_history.md index 2b6af17a..edc95728 100644 --- a/docs/restoring_bash_history.md +++ b/docs/restoring_bash_history.md @@ -1,39 +1,89 @@ -tmux-ressurect no longer restores shell history for each pane, as of [this PR](https://github.com/tmux-plugins/tmux-resurrect/pull/308). +tmux-resurrect no longer restores shell history for each pane, as of [this PR](https://github.com/tmux-plugins/tmux-resurrect/pull/308). -As a workaround, you can use the `HISTFILE` environment variable to preserve history for each pane separately, and modify -`PROMPT_COMMAND` to make sure history gets saved with each new command. +As a workaround, you can use the `HISTFILE` environment variable to preserve history for each pane separately (and modifing +`PROMPT_COMMAND` to make sure history gets saved with each new command), then use tmux-resurrect hooks to save/restore the histfile -Unfortunately, we haven't found a perfect way of getting a unique identifier for each pane, as the `TMUX_PANE` variable -seems to occasionally change when resurrecting. As a workaround, the example below sets a unique ID in each pane's `title`. -The downside of this implementation is that pane titles must all be unique across sessions/windows, and also must use the `pane_id_prefix`. +Add this to your .bashrc +```bash +# If in a TMUX pane, setup special history handling +if [ -n "$TMUX_PANE" ]; then + # Pick a history directory and make sure it exists + HISTDIR=$HOME/.bash_history.d + mkdir -p "$HISTDIR" + + # Set history file to a file using the TMUX pane id + export HISTFILE="${HISTDIR}/tmux_pane_${TMUX_PANE}" + + # Setup so that after each command we: + # 1. Append current history to histfile + # 2. Clear current cached history info from memory + # 3. Read history from the histfile + export PROMPT_COMMAND="history -a;history -c;history -r;${PROMPT_COMMAND}" +fi +``` -Any improvements/suggestions for getting a unique, persistent ID for each pane are welcome! +Then make some scripts (or merge into one, dealer's choice) to handle saving/restoring the histories. +For this example, I'll assume you have these scripts placed in the root directory. Don't do that. +post-save-all.sh ```bash -pane_id_prefix="resurrect_" +#!/usr/bin/env bash -# Create history directory if it doesn't exist -HISTS_DIR=$HOME/.bash_history.d -mkdir -p "${HISTS_DIR}" +RESURRECT_DIR="$HOME/.local/share/tmux/resurrect" -if [ -n "${TMUX_PANE}" ]; then +save_files() { + SAVE_DIR=$RESURRECT_DIR/$1 + FILE_PREFIX=$2 - # Check if we've already set this pane title - pane_id=$(tmux display -pt "${TMUX_PANE:?}" "#{pane_title}") - if [[ $pane_id != "$pane_id_prefix"* ]]; then + rm -r "$SAVE_DIR" 2>/dev/null - # if not, set it to a random ID - random_id=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16) - printf "\033]2;$pane_id_prefix$random_id\033\\" - pane_id=$(tmux display -pt "${TMUX_PANE:?}" "#{pane_title}") - fi + for PANE_INFO in $(tmux list-panes -aF "#{pane_id}=#{session_id}:#{window_index}.#{pane_index}"); do + PANE_ID=$(echo $PANE_INFO | cut -f 1 -d'=' | cut -d% -f 2) + IN=${FILE_PREFIX}${PANE_ID} + if ! [[ -e "$IN" ]]; then continue; fi - # use the pane's random ID for the HISTFILE - export HISTFILE="${HISTS_DIR}/bash_history_tmux_${pane_id}" -else - export HISTFILE="${HISTS_DIR}/bash_history_no_tmux" -fi + PANE_INDEX=$(echo $PANE_INFO | cut -f 2 -d'=') + OUT=$SAVE_DIR/$PANE_INDEX + if [[ -e "$OUT" ]]; then rm -r "$OUT"; fi + + mkdir -p $(dirname "$OUT") + cp -p -r "$IN" "$OUT" + done +} -# Stash the new history each time a command runs. -export PROMPT_COMMAND="$PROMPT_COMMAND;history -a" +save_files "history" "$HOME/.bash_history.d/tmux_pane_" +``` + +pre-restore-pane-processes.sh +```bash +#!/usr/bin/env bash + +RESURRECT_DIR="$HOME/.local/share/tmux/resurrect" + +restore_files() { + SAVE_DIR=$RESURRECT_DIR/$1 + FILE_PREFIX=$2 + + for PANE_INFO in $(tmux list-panes -aF "#{pane_id}=#{session_id}:#{window_index}.#{pane_index}"); do + PANE_ID=$(echo $PANE_INFO | cut -f 1 -d'=' | cut -d% -f 2) + OUT=${FILE_PREFIX}${PANE_ID} + if [[ -e "$OUT" ]]; then rm -r "$OUT"; fi + + PANE_INDEX=$(echo $PANE_INFO | cut -f 2 -d'=') + IN=$SAVE_DIR/$PANE_INDEX + if ! [[ -e "$IN" ]]; then continue; fi + + mkdir -p $(dirname "$OUT") + cp --preserve -r "$IN" "$OUT" + done +} + +restore_files "history" "$HOME/.bash_history.d/tmux_pane_" +``` + +Finally, add the following to your .tmux.conf +```bash +# Don't actually put these in the root folder! +set -g @resurrect-hook-post-save-all "/post-save-all.sh" +set -g @resurrect-hook-pre-restore-pane-processes "/pre-restore-pane-processes.sh" ```