Compare commits

...

31 Commits

Author SHA1 Message Date
Bruno Sutic cff343cf9e
Merge pull request #474 from georgeanderson/master
Update description of default session location
2023-03-06 11:20:22 +01:00
George Guimares 4c1c0dcf85 Updated description of default session location.
- Include alternate location
- Include reference to `${XDB_DATA_HOME}` env variable
2023-03-05 20:58:11 -06:00
Bruno Sutic 6df04051fe
Merge pull request #469 from ktprograms/restore-arguments-misc-fixes
Restore with command arguments misc fixes
2023-01-31 10:40:52 +01:00
kt programs 299c4aa8ce docs: add info on asterisk (*) restore option 2023-01-30 10:50:07 +08:00
kt programs b8ff2ea08b _get_proc_restore_command: use "," as sed delimiter
When command_arguments contains a path, there are too many delimiters
for sed, which causes it to not replace properly.

The result of this is that the original command gets executed without
remapping and/or expanding the arguments.
2023-01-30 10:37:15 +08:00
kt programs 4941cdb074 _get_command_arguments: make trailing space optional
When pane_full_command has no arguments, the regex doesn't find argv[0]
as there is no trailing space.

For example, if pane_full_command was "vim" and the restore option was
"~Vim->vim *", the command "vim vim" would get executed instead of just
"vim".

Make the trailing space optional to match having only the command
without arguments.
2023-01-30 10:37:15 +08:00
Bruno Sutic a2ddfb96b9
Merge pull request #458 from oliverlew/xdg_dir
use XDG_DATA_HOME for resurrect-dir path
2022-10-22 16:31:55 +02:00
Lu Xu dd36a4561b
use XDG_DATA_HOME for resurrect-dir path 2022-10-22 14:21:51 +08:00
Bruno Sutic 88297b4c3a
Merge pull request #455 from tfaughnan/ps-fix
ps.sh: fix ps arguments to work for busybox
2022-09-22 09:14:40 +02:00
Thomas Faughnan 45aa8feef6
ps.sh: fix ps arguments to work for busybox
Use the format specifier 'ppid,args' instead of 'ppid command'. POSIX
allows either spaces or commas as separators, but busybox only allows
commas. Furthermore, 'args' is recognized by POSIX[0] while 'command' is
not. On implementations of ps that do recognize 'command', it is simply
an alias for 'args', e.g. Debian[1] and FreeBSD[2].

[0]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html
[1]: https://manpages.debian.org/bullseye/procps/ps.1.en.html
[2]: https://www.freebsd.org/cgi/man.cgi?query=ps
2022-09-20 18:30:28 -04:00
Bruno Sutic 75458f91c8
Merge pull request #450 from mdeguzis/master
Use bash subshell for procfs interpolation of cmdline file
2022-08-17 09:09:56 +02:00
Michael T. DeGuzis 1431ba6fbe Use bash subshell for procfs interpolation of cmdline file 2022-08-16 08:57:39 -04:00
Bruno Sutic 3606e4f602
Merge pull request #443 from rbren/master
Fix for restoring bash history
2022-07-16 13:55:50 +02:00
Robert Brennan 7f5fa4bed2
Update restoring_bash_history.md 2022-07-15 16:36:24 -04:00
Bruno Sutic 74d9112314
Merge pull request #442 from rbren/master
Create restoring_bash_history.md
2022-06-26 09:18:44 +02:00
Robert Brennan 8101d98358
Create restoring_bash_history.md 2022-06-25 16:33:19 -04:00
Bruno Sutic ca6468e2de
Fix restoring active/alternate windows 2022-05-01 17:32:14 +02:00
Bruno Sutic 6050d2d8d8
Remove deprecated "restoring shell history" 2022-04-10 08:58:27 +02:00
Bruno Sutic e87d7d592c
v4.0.0 2022-04-10 08:40:19 +02:00
Bruno Sutic 5b5e6ca7b1
Merge pull request #431 from Hologos/feature/save-pane-title
Adds support for saving and restoring pane titles.
2022-04-10 08:39:15 +02:00
Jiří Málek 1ad109d3a8
Adds support for saving and restoring pane titles. 2022-04-09 13:52:28 +02:00
Bruno Sutic 027960ad25
Explain delayed pane content cleanup 2021-12-19 16:21:44 +01:00
Bruno Sutic dc6252d950
Merge pull request #422 from cartoonist/master
Fix #141
2021-12-19 16:19:30 +01:00
Ali Ghaffaari c3d0599a6e Fix #141
The issue apprently happens when using fish as the default shell. This commit
fixes this issue by postponing `restore/pane_contents` clean-up after calling
`restore_active_pane_for_each_window` (scripts/restore.sh:392). It might also
fix #192.
2021-12-19 12:50:20 +01:00
Bruno Sutic 6be2f34b5f
automatic-rename: changelog and comments 2021-08-30 14:17:15 +02:00
Bruno Sutic 4234ba99aa
Merge pull request #401 from Farzat07/automatic-rename2
Maintain the value of automatic-rename
2021-08-30 14:07:33 +02:00
A Farzat 3e8fbdf7aa Make window_name variable local in restoring func
In restore_window_properties function, the window_name is set globally
at first, but now it is first declared as local to prevent that from
happening.
2021-08-27 18:02:00 +09:00
A Farzat 1b63a940a0 Fix even more bugs in before last commit
First, increment the relevant indices in the awk statements regarding
windows, as now the window_name entry exists.

Second, remove the window_name entry from the dump_pane_contents and
dump_shell_history functions as it no longer exists in the format.
2021-08-27 15:57:26 +09:00
A Farzat 02a7f1f9d6 Fix some of the errors in the last commit
First, make sure to include the ":" placeholder in the window_name
format.

Second, decrement the indices in relevant awk commands to make sure they
point to the right items.
2021-08-27 13:27:00 +09:00
A Farzat 6c9322aa99 Leave window name handling to windows
Previously, window names were set when creating panes and were therefore
saved with pane data. However, saving the names with window data is more
intuitive and easier to manage. In addition, one can set the name and
automatic-rename options in the same function, so one can make sure that
renaming the windows will not overwrite the automatic-rename option.
2021-08-26 07:00:49 +09:00
A Farzat 80adb917c1 Maintain the value of automatic-rename
When the session is restored, the windows are renamed to their original
names switching off automatic-rename, which can be undesirable.
Therefore the value of automatic-rename is now saved for each window and
restored after the renaming.

If the value is set, that value is saved and then applied. Otherwise, a
placeholder of ':' is placed instead, in which case the local option is
unset for that window (as it originally was).
2021-08-23 14:04:11 +09:00
14 changed files with 134 additions and 167 deletions

View File

@ -1,6 +1,12 @@
# Changelog
### master
- Remove deprecated "restoring shell history" feature.
### v4.0.0, 2022-04-10
- Proper handling of `automatic-rename` window option.
- save and restore tmux pane title (breaking change: you have to re-save to be
able to properly restore!)
### v3.0.0, 2021-08-30
- save and restore tmux pane contents (@laomaiweng)

View File

@ -104,10 +104,6 @@ You should now be able to use the plugin.
is nice if you're a vim/neovim user.
- [Restoring pane contents](docs/restoring_pane_contents.md) feature.
**Experimental features (also optional)**
- [restoring shell history](docs/restoring_shell_history.md)
### Other goodies
- [tmux-copycat](https://github.com/tmux-plugins/tmux-copycat) - a plugin for

View File

@ -20,15 +20,9 @@ Currently the following hooks are supported:
Called before any tmux state is altered.
- `@resurrect-hook-pre-restore-history` - deprecated
Called after panes and layout have been restores, but before bash history is
restored (if it is enabled) -- the hook is always called even if history
saving is disabled.
- `@resurrect-hook-pre-restore-pane-processes`
Called after history is restored, but before running processes are restored.
Called before running processes are restored.
### Examples

View File

@ -0,0 +1,39 @@
tmux-ressurect 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.
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`.
Any improvements/suggestions for getting a unique, persistent ID for each pane are welcome!
```bash
pane_id_prefix="resurrect_"
# Create history directory if it doesn't exist
HISTS_DIR=$HOME/.bash_history.d
mkdir -p "${HISTS_DIR}"
if [ -n "${TMUX_PANE}" ]; then
# 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
# 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
# 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
# Stash the new history each time a command runs.
export PROMPT_COMMAND="$PROMPT_COMMAND;history -a"
```

View File

@ -1,7 +1,8 @@
# Restoring previously saved environment
None of the previous saves are deleted (unless you explicitly do that). All save
files are kept in `~/.tmux/resurrect/` directory.<br/>
files are kept in `~/.tmux/resurrect/` directory, or `~/.local/share/tmux/resurrect`
(unless `${XDG_DATA_HOME}` says otherwise).<br/>
Here are the steps to restore to a previous point in time:
- make sure you start this with a "fresh" tmux instance

View File

@ -28,6 +28,10 @@ contains space-separated list of additional programs to restore.
set -g @resurrect-processes 'some_program "grunt->grunt development"'
- Use `*` to expand the arguments from the saved command when restoring:
set -g @resurrect-processes 'some_program "~rails server->rails server *"'
- Don't restore any programs:
set -g @resurrect-processes 'false'
@ -96,6 +100,20 @@ command name".
Full (long) process name is now ignored and you'll see just `rails server` in
the command line when the program is restored.
> What is asterisk `*` and why is it used?
(Please read the above clarifications about tilde `~` and arrow `->`).
Continuing with the `rails server` example, you might have added flags for e.g.
verbose logging, but with the above configuration, the flags would be lost.
To preserve the command arguments when restoring, use the asterisk `*`: (**note**: there **must** be a space before `*`)
set -g @resurrect-processes '"~rails server->rails server *"'
This option says: "when this process is restored use `rails server` as the
command name, but preserve its arguments".
> Now I understand the tilde and the arrow, but things still don't work for me
Here's the general workflow for figuring this out:

View File

@ -1,23 +0,0 @@
# Restoring shell history (deprecated, do not use)
This feature is deprecated because it's very invasive. It will be removed in
the future with no replacement. To see problems it causes check
[this issue](https://github.com/tmux-plugins/tmux-resurrect/issues/288).
**Supported shells**: `bash` and `zsh`.
Enable feature with this option in `.tmux.conf`:
set -g @resurrect-save-shell-history 'on'
**Note**: the older `@resurrect-save-bash-history` is now an alias to
`@resurrect-save-shell-history`.
Shell `history` for individual panes will now be saved and restored. Due to
technical limitations, this only works for panes which have no program running
in foreground when saving. `tmux-resurrect` will send history write command to
each such pane.
To prevent these commands from being added to `bash` history
themselves, add `HISTCONTROL=ignoreboth` to your `.bashrc`
(this is set by default in Ubuntu).

View File

@ -13,7 +13,10 @@ exit_safely_if_empty_ppid() {
full_command() {
[[ -z "$COMMAND_PID" ]] && exit 0
cat /proc/${COMMAND_PID}/cmdline | xargs -0 printf "%q "
# See: https://unix.stackexchange.com/a/567021
# Avoid complications with system printf by using bash subshell interpolation.
# This will properly escape sequences and null in cmdline.
cat /proc/${COMMAND_PID}/cmdline | xargs -0 bash -c 'printf "%q " "$0" "$@"'
}
main() {

View File

@ -11,7 +11,7 @@ exit_safely_if_empty_ppid() {
}
full_command() {
ps -ao "ppid command" |
ps -ao "ppid,args" |
sed "s/^ *//" |
grep "^${PANE_PID}" |
cut -d' ' -f2-

View File

@ -1,4 +1,8 @@
default_resurrect_dir="$HOME/.tmux/resurrect"
if [ -d "$HOME/.tmux/resurrect" ]; then
default_resurrect_dir="$HOME/.tmux/resurrect"
else
default_resurrect_dir="${XDG_DATA_HOME:-$HOME/.local/share}"/tmux/resurrect
fi
resurrect_dir_option="@resurrect-dir"
SUPPORTED_VERSION="1.9"
@ -64,13 +68,6 @@ files_differ() {
! cmp -s "$1" "$2"
}
save_shell_history_option_on() {
local option_shell="$(get_tmux_option "$shell_history_option" "off")"
local option_bash="$(get_tmux_option "$bash_history_option" "off")"
[ "$option_shell" == "on" ] || [ "$option_bash" == "on" ]
}
get_grouped_sessions() {
local grouped_sessions_dump="$1"
export GROUPED_SESSIONS="${d}$(echo "$grouped_sessions_dump" | cut -f2 -d"$d" | tr "\\n" "$d")"
@ -143,12 +140,6 @@ pane_contents_archive_file() {
echo "$(resurrect_dir)/pane_contents.tar.gz"
}
resurrect_history_file() {
local pane_id="$1"
local shell_name="$2"
echo "$(resurrect_dir)/${shell_name}_history-${pane_id}"
}
execute_hook() {
local kind="$1"
shift

View File

@ -121,7 +121,7 @@ _get_command_arguments() {
if _proc_starts_with_tildae "$match"; then
match="$(remove_first_char "$match")"
fi
echo "$pane_full_command" | sed "s,^.*${match}[^ ]* ,,"
echo "$pane_full_command" | sed "s,^.*${match}[^ ]* *,,"
}
_get_proc_restore_command() {
@ -132,7 +132,7 @@ _get_proc_restore_command() {
if [[ "$restore_element" =~ " ${inline_strategy_arguments_token}" ]]; then
# replaces "%" with command arguments
local command_arguments="$(_get_command_arguments "$pane_full_command" "$match")"
echo "$restore_element" | sed "s/${inline_strategy_arguments_token}/${command_arguments}/"
echo "$restore_element" | sed "s,${inline_strategy_arguments_token},${command_arguments},"
else
echo "$restore_element"
fi

View File

@ -126,31 +126,29 @@ pane_creation_command() {
new_window() {
local session_name="$1"
local window_number="$2"
local window_name="$3"
local dir="$4"
local pane_index="$5"
local dir="$3"
local pane_index="$4"
local pane_id="${session_name}:${window_number}.${pane_index}"
dir="${dir/#\~/$HOME}"
if is_restoring_pane_contents && pane_contents_file_exists "$pane_id"; then
local pane_creation_command="$(pane_creation_command "$session_name" "$window_number" "$pane_index")"
tmux new-window -d -t "${session_name}:${window_number}" -n "$window_name" -c "$dir" "$pane_creation_command"
tmux new-window -d -t "${session_name}:${window_number}" -c "$dir" "$pane_creation_command"
else
tmux new-window -d -t "${session_name}:${window_number}" -n "$window_name" -c "$dir"
tmux new-window -d -t "${session_name}:${window_number}" -c "$dir"
fi
}
new_session() {
local session_name="$1"
local window_number="$2"
local window_name="$3"
local dir="$4"
local pane_index="$5"
local dir="$3"
local pane_index="$4"
local pane_id="${session_name}:${window_number}.${pane_index}"
if is_restoring_pane_contents && pane_contents_file_exists "$pane_id"; then
local pane_creation_command="$(pane_creation_command "$session_name" "$window_number" "$pane_index")"
TMUX="" tmux -S "$(tmux_socket)" new-session -d -s "$session_name" -n "$window_name" -c "$dir" "$pane_creation_command"
TMUX="" tmux -S "$(tmux_socket)" new-session -d -s "$session_name" -c "$dir" "$pane_creation_command"
else
TMUX="" tmux -S "$(tmux_socket)" new-session -d -s "$session_name" -n "$window_name" -c "$dir"
TMUX="" tmux -S "$(tmux_socket)" new-session -d -s "$session_name" -c "$dir"
fi
# change first window number if necessary
local created_window_num="$(first_window_num)"
@ -162,9 +160,8 @@ new_session() {
new_pane() {
local session_name="$1"
local window_number="$2"
local window_name="$3"
local dir="$4"
local pane_index="$5"
local dir="$3"
local pane_index="$4"
local pane_id="${session_name}:${window_number}.${pane_index}"
if is_restoring_pane_contents && pane_contents_file_exists "$pane_id"; then
local pane_creation_command="$(pane_creation_command "$session_name" "$window_number" "$pane_index")"
@ -172,27 +169,24 @@ new_pane() {
else
tmux split-window -t "${session_name}:${window_number}" -c "$dir"
fi
tmux rename-window -t "${session_name}:${window_number}" "$window_name"
# minimize window so more panes can fit
tmux resize-pane -t "${session_name}:${window_number}" -U "999"
tmux resize-pane -t "${session_name}:${window_number}" -U "999"
}
restore_pane() {
local pane="$1"
while IFS=$d read line_type session_name window_number window_name window_active window_flags pane_index dir pane_active pane_command pane_full_command; do
while IFS=$d read line_type session_name window_number window_active window_flags pane_index pane_title dir pane_active pane_command pane_full_command; do
dir="$(remove_first_char "$dir")"
window_name="$(remove_first_char "$window_name")"
pane_full_command="$(remove_first_char "$pane_full_command")"
if [ "$session_name" == "0" ]; then
restored_session_0_true
fi
if pane_exists "$session_name" "$window_number" "$pane_index"; then
tmux rename-window -t "${session_name}:${window_number}" "$window_name"
if is_restoring_from_scratch; then
# overwrite the pane
# happens only for the first pane if it's the only registered pane for the whole tmux server
local pane_id="$(tmux display-message -p -F "#{pane_id}" -t "$session_name:$window_number")"
new_pane "$session_name" "$window_number" "$window_name" "$dir" "$pane_index"
new_pane "$session_name" "$window_number" "$dir" "$pane_index"
tmux kill-pane -t "$pane_id"
else
# Pane exists, no need to create it!
@ -200,13 +194,14 @@ restore_pane() {
register_existing_pane "$session_name" "$window_number" "$pane_index"
fi
elif window_exists "$session_name" "$window_number"; then
tmux rename-window -t "${session_name}:${window_number}" "$window_name"
new_pane "$session_name" "$window_number" "$window_name" "$dir" "$pane_index"
new_pane "$session_name" "$window_number" "$dir" "$pane_index"
elif session_exists "$session_name"; then
new_window "$session_name" "$window_number" "$window_name" "$dir" "$pane_index"
new_window "$session_name" "$window_number" "$dir" "$pane_index"
else
new_session "$session_name" "$window_number" "$window_name" "$dir" "$pane_index"
new_session "$session_name" "$window_number" "$dir" "$pane_index"
fi
# set pane title
tmux select-pane -t "$session_name:$window_number.$pane_index" -T "$pane_title"
done < <(echo "$pane")
}
@ -277,9 +272,6 @@ restore_all_panes() {
restore_pane "$line"
fi
done < $(last_resurrect_file)
if is_restoring_pane_contents; then
rm "$(pane_contents_dir "restore")"/*
fi
}
handle_session_0() {
@ -292,28 +284,21 @@ handle_session_0() {
fi
}
restore_pane_layout_for_each_window() {
restore_window_properties() {
local window_name
\grep '^window' $(last_resurrect_file) |
while IFS=$d read line_type session_name window_number window_active window_flags window_layout; do
while IFS=$d read line_type session_name window_number window_name window_active window_flags window_layout automatic_rename; do
tmux select-layout -t "${session_name}:${window_number}" "$window_layout"
done
}
restore_shell_history() {
awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ { print $2, $3, $7, $10; }' $(last_resurrect_file) |
while IFS=$d read session_name window_number pane_index pane_command; do
if ! is_pane_registered_as_existing "$session_name" "$window_number" "$pane_index"; then
local pane_id="$session_name:$window_number.$pane_index"
local history_file="$(resurrect_history_file "$pane_id" "$pane_command")"
if [ "$pane_command" = "bash" ]; then
local read_command="history -r '$history_file'"
tmux send-keys -t "$pane_id" "$read_command" C-m
elif [ "$pane_command" = "zsh" ]; then
local accept_line="$(expr "$(zsh -i -c bindkey | grep -m1 '\saccept-line$')" : '^"\(.*\)".*')"
local read_command="fc -R '$history_file'; clear"
tmux send-keys -t "$pane_id" "$read_command" "$accept_line"
fi
# Below steps are properly handling window names and automatic-rename
# option. `rename-window` is an extra command in some scenarios, but we
# opted for always doing it to keep the code simple.
window_name="$(remove_first_char "$window_name")"
tmux rename-window -t "${session_name}:${window_number}" "$window_name"
if [ "${automatic_rename}" = ":" ]; then
tmux set-option -u -t "${session_name}:${window_number}" automatic-rename
else
tmux set-option -t "${session_name}:${window_number}" automatic-rename "$automatic_rename"
fi
done
}
@ -321,7 +306,7 @@ restore_shell_history() {
restore_all_pane_processes() {
if restore_pane_processes_enabled; then
local pane_full_command
awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ && $11 !~ "^:$" { print $2, $3, $7, $8, $11; }' $(last_resurrect_file) |
awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ && $11 !~ "^:$" { print $2, $3, $6, $8, $11; }' $(last_resurrect_file) |
while IFS=$d read -r session_name window_number pane_index dir pane_full_command; do
dir="$(remove_first_char "$dir")"
pane_full_command="$(remove_first_char "$pane_full_command")"
@ -331,7 +316,7 @@ restore_all_pane_processes() {
}
restore_active_pane_for_each_window() {
awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ && $9 == 1 { print $2, $3, $7; }' $(last_resurrect_file) |
awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ && $9 == 1 { print $2, $3, $6; }' $(last_resurrect_file) |
while IFS=$d read session_name window_number active_pane; do
tmux switch-client -t "${session_name}:${window_number}"
tmux select-pane -t "$active_pane"
@ -339,7 +324,7 @@ restore_active_pane_for_each_window() {
}
restore_zoomed_windows() {
awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ && $6 ~ /Z/ && $9 == 1 { print $2, $3; }' $(last_resurrect_file) |
awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ && $5 ~ /Z/ && $9 == 1 { print $2, $3; }' $(last_resurrect_file) |
while IFS=$d read session_name window_number; do
tmux resize-pane -t "${session_name}:${window_number}" -Z
done
@ -355,7 +340,7 @@ restore_grouped_sessions() {
}
restore_active_and_alternate_windows() {
awk 'BEGIN { FS="\t"; OFS="\t" } /^window/ && $5 ~ /[*-]/ { print $2, $4, $3; }' $(last_resurrect_file) |
awk 'BEGIN { FS="\t"; OFS="\t" } /^window/ && $6 ~ /[*-]/ { print $2, $5, $3; }' $(last_resurrect_file) |
sort -u |
while IFS=$d read session_name active_window window_number; do
tmux switch-client -t "${session_name}:${window_number}"
@ -370,17 +355,21 @@ restore_active_and_alternate_sessions() {
done < $(last_resurrect_file)
}
# A cleanup that happens after 'restore_all_panes' seems to fix fish shell
# users' restore problems.
cleanup_restored_pane_contents() {
if is_restoring_pane_contents; then
rm "$(pane_contents_dir "restore")"/*
fi
}
main() {
if supported_tmux_version_ok && check_saved_session_exists; then
start_spinner "Restoring..." "Tmux restore complete!"
execute_hook "pre-restore-all"
restore_all_panes
handle_session_0
restore_pane_layout_for_each_window >/dev/null 2>&1
execute_hook "pre-restore-history"
if save_shell_history_option_on; then
restore_shell_history
fi
restore_window_properties >/dev/null 2>&1
execute_hook "pre-restore-pane-processes"
restore_all_pane_processes
# below functions restore exact cursor positions
@ -389,6 +378,7 @@ main() {
restore_grouped_sessions # also restores active and alt windows for grouped sessions
restore_active_and_alternate_windows
restore_active_and_alternate_sessions
cleanup_restored_pane_contents
execute_hook "post-restore-all"
stop_spinner
display_message "Tmux restore complete!"

View File

@ -33,14 +33,14 @@ pane_format() {
format+="${delimiter}"
format+="#{window_index}"
format+="${delimiter}"
format+=":#{window_name}"
format+="${delimiter}"
format+="#{window_active}"
format+="${delimiter}"
format+=":#{window_flags}"
format+="${delimiter}"
format+="#{pane_index}"
format+="${delimiter}"
format+="#{pane_title}"
format+="${delimiter}"
format+=":#{pane_current_path}"
format+="${delimiter}"
format+="#{pane_active}"
@ -61,6 +61,8 @@ window_format() {
format+="${delimiter}"
format+="#{window_index}"
format+="${delimiter}"
format+=":#{window_name}"
format+="${delimiter}"
format+="#{window_active}"
format+="${delimiter}"
format+=":#{window_flags}"
@ -142,46 +144,6 @@ capture_pane_contents() {
fi
}
save_shell_history() {
if [ "$pane_command" = "bash" ]; then
local history_w='history -w'
local history_r='history -r'
local accept_line='C-m'
local end_of_line='C-e'
local backward_kill_line='C-u'
elif [ "$pane_command" = "zsh" ]; then
# fc -W does not work with -L
# fc -l format is different from what's written by fc -W
# fc -R either reads the format produced by fc -W or considers
# the entire line to be a command. That's why we need -n.
# fc -l only list the last 16 items by default, I think 64 is more reasonable.
local history_w='fc -lLn -64 >'
local history_r='fc -R'
local zsh_bindkey="$(zsh -i -c bindkey)"
local accept_line="$(expr "$(echo "$zsh_bindkey" | grep -m1 '\saccept-line$')" : '^"\(.*\)".*')"
local end_of_line="$(expr "$(echo "$zsh_bindkey" | grep -m1 '\send-of-line$')" : '^"\(.*\)".*')"
local backward_kill_line="$(expr "$(echo "$zsh_bindkey" | grep -m1 '\sbackward-kill-line$')" : '^"\(.*\)".*')"
else
return
fi
local pane_id="$1"
local pane_command="$2"
local full_command="$3"
if [ "$full_command" = ":" ]; then
# leading space prevents the command from being saved to history
# (assuming default HISTCONTROL settings)
local write_command=" $history_w '$(resurrect_history_file "$pane_id" "$pane_command")'"
local read_command=" $history_r '$(resurrect_history_file "$pane_id" "$pane_command")'"
# C-e C-u is a Bash shortcut sequence to clear whole line. It is necessary to
# delete any pending input so it does not interfere with our history command.
tmux send-keys -t "$pane_id" "$end_of_line" "$backward_kill_line" "$write_command" "$accept_line"
# Immediately restore after saving
tmux send-keys -t "$pane_id" "$end_of_line" "$backward_kill_line" "$read_command" "$accept_line"
fi
}
get_active_window_index() {
local session_name="$1"
tmux list-windows -t "$session_name" -F "#{window_flags} #{window_index}" |
@ -227,25 +189,28 @@ fetch_and_dump_grouped_sessions(){
dump_panes() {
local full_command
dump_panes_raw |
while IFS=$d read line_type session_name window_number window_name window_active window_flags pane_index dir pane_active pane_command pane_pid history_size; do
while IFS=$d read line_type session_name window_number window_active window_flags pane_index pane_title dir pane_active pane_command pane_pid history_size; do
# not saving panes from grouped sessions
if is_session_grouped "$session_name"; then
continue
fi
full_command="$(pane_full_command $pane_pid)"
dir=$(echo $dir | sed 's/ /\\ /') # escape all spaces in directory path
echo "${line_type}${d}${session_name}${d}${window_number}${d}${window_name}${d}${window_active}${d}${window_flags}${d}${pane_index}${d}${dir}${d}${pane_active}${d}${pane_command}${d}:${full_command}"
echo "${line_type}${d}${session_name}${d}${window_number}${d}${window_active}${d}${window_flags}${d}${pane_index}${d}${pane_title}${d}${dir}${d}${pane_active}${d}${pane_command}${d}:${full_command}"
done
}
dump_windows() {
dump_windows_raw |
while IFS=$d read line_type session_name window_index window_active window_flags window_layout; do
while IFS=$d read line_type session_name window_index window_name window_active window_flags window_layout; do
# not saving windows from grouped sessions
if is_session_grouped "$session_name"; then
continue
fi
echo "${line_type}${d}${session_name}${d}${window_index}${d}${window_active}${d}${window_flags}${d}${window_layout}"
automatic_rename="$(tmux show-window-options -vt "${session_name}:${window_index}" automatic-rename)"
# If the option was unset, use ":" as a placeholder.
[ -z "${automatic_rename}" ] && automatic_rename=":"
echo "${line_type}${d}${session_name}${d}${window_index}${d}${window_name}${d}${window_active}${d}${window_flags}${d}${window_layout}${d}${automatic_rename}"
done
}
@ -256,18 +221,11 @@ dump_state() {
dump_pane_contents() {
local pane_contents_area="$(get_tmux_option "$pane_contents_area_option" "$default_pane_contents_area")"
dump_panes_raw |
while IFS=$d read line_type session_name window_number window_name window_active window_flags pane_index dir pane_active pane_command pane_pid history_size; do
while IFS=$d read line_type session_name window_number window_active window_flags pane_index pane_title dir pane_active pane_command pane_pid history_size; do
capture_pane_contents "${session_name}:${window_number}.${pane_index}" "$history_size" "$pane_contents_area"
done
}
dump_shell_history() {
dump_panes |
while IFS=$d read line_type session_name window_number window_name window_active window_flags pane_index dir pane_active pane_command full_command; do
save_shell_history "$session_name:$window_number.$pane_index" "$pane_command" "$full_command"
done
}
remove_old_backups() {
# remove resurrect files older than 30 days (default), but keep at least 5 copies of backup.
local delete_after="$(get_tmux_option "$delete_backup_after_option" "$default_delete_backup_after")"
@ -297,9 +255,6 @@ save_all() {
pane_contents_create_archive
rm "$(pane_contents_dir "save")"/*
fi
if save_shell_history_option_on; then
dump_shell_history
fi
remove_old_backups
execute_hook "post-save-all"
}

View File

@ -38,9 +38,6 @@ pane_contents_option="@resurrect-capture-pane-contents"
pane_contents_area_option="@resurrect-pane-contents-area"
default_pane_contents_area="full"
bash_history_option="@resurrect-save-bash-history" # deprecated
shell_history_option="@resurrect-save-shell-history" # deprecated
# set to 'on' to ensure panes are never ever overwritten
overwrite_option="@resurrect-never-overwrite"