27 Commits

Author SHA1 Message Date
e770c87e10 v1.5.0 2014-11-09 16:43:44 +01:00
601366be6d Support for restoring neovim sessions 2014-11-09 16:42:53 +01:00
059686ab6c Merge pull request #55 from rburny/master
Fixes to #51 and #52
2014-10-26 16:59:41 +01:00
488f086fa5 Add a note about HISTCONTROL to README. 2014-10-26 02:17:12 +02:00
fcf7ca13f0 Only save pane history if its not running any program (other than Bash
shell). Fixes a bug where 'history -w' was sent to pane running Bash
script.
2014-10-26 01:30:00 +02:00
e38eed7dae v1.4.0 2014-10-25 18:46:15 +02:00
a35d5f9b90 Update changelog & readme for the zoomed windows feature
Closes #47, #54
2014-10-25 18:43:56 +02:00
0b496dd228 Removing the last_resized variable
Instead resizing only if pane_active is set so we are sure the resizep
is called only once
2014-10-25 18:29:52 +02:00
ad52ade4bf Preserving layout of zoomed windows across restores
The problem is that tmux list-window shows only the current pane layout
if a pane is maximized. This is a bug in tmux. In order to avoid this
bug we unzoom the window when saving and zoom in again after saving.
This implies that the Z flag is no longer set in list-windows, and so it
can't be used when restoring. Instead we use the Z flag of the panes
(which still have it) to restore the zoom.
2014-10-25 18:29:52 +02:00
3ba092459a Merge pull request #49 from tmux-plugins/bash_history
Bash save and restore history feature
2014-10-20 23:17:46 +02:00
6a6d65b98a Update the readme 2014-10-20 23:16:56 +02:00
f3fe4acc39 Document bash restore history feature 2014-10-17 22:40:15 +02:00
8684d4592b Flag gate the bash history restore feature 2014-10-17 22:33:29 +02:00
8328de41d8 Update changelog 2014-10-17 17:47:10 +02:00
94985fc500 Extract save_shell_history to a separate function 2014-10-17 17:45:49 +02:00
81982b5114 Add bash history saving and restoring (first version).
This does not yet have flag to turn the feature off.
2014-10-17 17:14:33 +02:00
a73c465e47 Add issue video screenshot 2014-10-07 13:55:23 +02:00
4ba0e398b9 Document tmux env save dir 2014-10-06 12:59:14 +02:00
8fd38588c0 Fix ps command flags for FreeBSD
This was reported by @duck in #45
2014-09-29 13:39:41 +02:00
a7fe9dcac3 Command line script that fully restores tmux environment 2014-09-24 14:33:46 +02:00
ec9f68cad5 Quote arguments in tmux display-message 2014-09-24 14:30:05 +02:00
94594efdb0 Small bugfix: text command arguments 2014-09-24 14:25:30 +02:00
1b79eb2f63 Rename default strategy to ps 2014-09-21 15:12:35 +02:00
8ebda79f68 Implement save command strategy gdb
@danschumann originally came up with this strategy in #44
2014-09-21 00:08:41 +02:00
ae9083e695 Implement save command strategy: pgrep 2014-09-20 23:55:19 +02:00
9f7050aaae Use a strategy when fetching pane full command 2014-09-20 23:47:15 +02:00
99abfa5f13 Small readme update 2014-09-20 22:45:37 +02:00
14 changed files with 262 additions and 28 deletions

View File

@ -2,6 +2,21 @@
### master
### v1.5.0, 2014-11-09
- add support for restoring neovim sessions
### v1.4.0, 2014-10-25
- plugin now uses strategies when fetching pane full command. Implemented
'default' strategy.
- save command strategy: 'pgrep'. It's here only if fallback is needed.
- save command strategy: 'gdb'
- rename default strategy name to 'ps'
- create `expect` script that can fully restore tmux environment
- fix default save command strategy `ps` command flags. Flags are different for
FreeBSD.
- add bash history saving and restoring (@rburny)
- preserving layout of zoomed windows across restores (@Azrael3000)
### v1.3.0, 2014-09-20
- remove dependency on `pgrep` command. Use `ps` for fetching process names.

View File

@ -12,7 +12,7 @@ projects.
can be completely restored after a system restart (or when you feel like it).
No configuration is required. You should feel like you never quit tmux.
It even (optionally) [restores vim sessions](#restoring-vim-sessions)!
It even (optionally) [restores vim and neovim sessions](#restoring-vim-and-neovim-sessions)!
### Screencast
@ -20,10 +20,10 @@ It even (optionally) [restores vim sessions](#restoring-vim-sessions)!
### Key bindings
- `prefix + Ctrl-s` or `prefix + Alt-s` - save
- `prefix + Ctrl-r` or `prefix + Alt-r` - restore
- `prefix + Ctrl-s` - save
- `prefix + Ctrl-r` - restore
Some people can't get `Alt` key mappings to work so they are deprecated.
`prefix + Alt-s` and `prefix + Alt-r` key bindings are now deprecated.
For custom key bindings, add to `.tmux.conf`:
@ -37,15 +37,17 @@ This plugin goes to great lengths to save and restore all the details from your
- all sessions, windows, panes and their order
- current working directory for each pane
- **exact pane layouts** within windows
- **exact pane layouts** within windows (even when zoomed)
- active and alternative session
- active and alternative window for each session
- windows with focus
- active pane for each window
- programs running within a pane! More details in the
[configuration section](#configuration).
- restoring vim sessions (optional). More details in
[restoring vim sessions](#restoring-vim-sessions).
- restoring vim/neovim sessions (optional). More details in
[restoring vim and neovim sessions](#restoring-vim-and-neovim-sessions).
- restoring bash history (optional, *experimental*). More details in
[restoring bash history](#restoring-bash-history-experimental).
Requirements / dependencies: `tmux 1.9` or higher, `bash`.
@ -56,10 +58,10 @@ already exist.
Add plugin to the list of TPM plugins in `.tmux.conf`:
set -g @tpm_plugins " \
set -g @tpm_plugins ' \
tmux-plugins/tpm \
tmux-plugins/tmux-resurrect \
"
'
Hit `prefix + I` to fetch the plugin and source it. You should now be able to
use the plugin.
@ -86,7 +88,7 @@ You should now be able to use the plugin.
Configuration is not required, but it enables extra features.
Only a conservative list of programs is restored by default:<br/>
`vi vim emacs man less more tail top htop irssi`.
`vi vim nvim emacs man less more tail top htop irssi`.
- Restore additional programs with the setting in `.tmux.conf`:
@ -113,15 +115,39 @@ Only a conservative list of programs is restored by default:<br/>
set -g @resurrect-processes ':all:'
#### Restoring vim sessions
#### Restoring vim and neovim sessions
- save vim sessions. I recommend [tpope/vim-obsession](https://github.com/tpope/vim-obsession).
- save vim/neovim sessions. I recommend
[tpope/vim-obsession](https://github.com/tpope/vim-obsession) (as almost every
plugin, it works for both vim and neovim).
- in `.tmux.conf`:
# for vim
set -g @resurrect-strategy-vim 'session'
# for neovim
set -g @resurrect-strategy-nvim 'session'
`tmux-resurrect` will now restore vim sessions if `Sessions.vim` file is
present.
`tmux-resurrect` will now restore vim and neovim sessions if `Sessions.vim` file
is present.
#### Resurrect save dir
By default Tmux environment is saved to a file in `~/.tmux/resurrect` dir.
Change this with:
set -g @resurrect-dir '/some/path'
#### Restoring bash history (experimental)
In `.tmux.conf`:
set -g @resurrect-save-bash-history 'on'
Bash `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 history themselves,
add `HISTCONTROL=ignoreboth` to your `.bashrc` (this is set by default in Ubuntu).
### Other goodies

22
save_command_strategies/gdb.sh Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PANE_PID="$1"
exit_safely_if_empty_ppid() {
if [ -z "$PANE_PID" ]; then
exit 0
fi
}
full_command() {
gdb -batch --eval "attach $PANE_PID" --eval "call write_history(\"/tmp/bash_history-${PANE_PID}.txt\")" --eval 'detach' --eval 'q' >/dev/null 2>&1
\tail -1 "/tmp/bash_history-${PANE_PID}.txt"
}
main() {
exit_safely_if_empty_ppid
full_command
}
main

View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PANE_PID="$1"
exit_safely_if_empty_ppid() {
if [ -z "$PANE_PID" ]; then
exit 0
fi
}
full_command() {
\pgrep -lf -P "$PANE_PID" |
cut -d' ' -f2-
}
main() {
exit_safely_if_empty_ppid
full_command
}
main

31
save_command_strategies/ps.sh Executable file
View File

@ -0,0 +1,31 @@
#!/usr/bin/env bash
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PANE_PID="$1"
exit_safely_if_empty_ppid() {
if [ -z "$PANE_PID" ]; then
exit 0
fi
}
ps_command_flags() {
case $(uname -s) in
FreeBSD) echo "-ao" ;;
*) echo "-eo" ;;
esac
}
full_command() {
ps "$(ps_command_flags)" "ppid command" |
sed "s/^ *//" |
grep "^${PANE_PID}" |
cut -d' ' -f2-
}
main() {
exit_safely_if_empty_ppid
full_command
}
main

View File

@ -49,6 +49,11 @@ remove_first_char() {
echo "$1" | cut -c2-
}
save_bash_history_option_on() {
local option="$(get_tmux_option "$bash_history_option" "off")"
[ "$option" == "on" ]
}
# path helpers
resurrect_dir() {
@ -63,3 +68,15 @@ resurrect_file_path() {
last_resurrect_file() {
echo "$(resurrect_dir)/last"
}
resurrect_history_file() {
local pane_id="$1"
echo "$(resurrect_dir)/bash_history-${pane_id}"
}
restore_zoomed_windows() {
awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ && $6 ~ /Z/ && $9 == 1 { print $2, $3; }' $(last_resurrect_file) |
while IFS=$'\t' read session_name window_number; do
tmux resize-pane -t "${session_name}:${window_number}" -Z
done
}

View File

@ -57,7 +57,7 @@ _process_should_be_restored() {
_restore_all_processes() {
local restore_processes="$(get_tmux_option "$restore_processes_option" "$restore_processes")"
if [ $restore_processes == ":all:" ]; then
if [ "$restore_processes" == ":all:" ]; then
return 0
else
return 1
@ -108,7 +108,7 @@ _get_proc_restore_element() {
_restore_list() {
local user_processes="$(get_tmux_option "$restore_processes_option" "$restore_processes")"
local default_processes="$(get_tmux_option "$default_proc_list_option" "$default_proc_list")"
if [ -z $user_processes ]; then
if [ -z "$user_processes" ]; then
# user didn't define any processes
echo "$default_processes"
else

14
scripts/restore.exp Executable file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env expect
# start tmux
spawn tmux -S/tmp/foo
# delay with sleep to compensate for tmux starting time
sleep 2
# run restore script directly
send "~/.tmux/plugins/tmux-resurrect/scripts/restore.sh\r"
# long wait until tmux restore is complete
# (things get messed up if expect client isn't attached)
sleep 100

View File

@ -141,6 +141,21 @@ restore_all_panes() {
done < $(last_resurrect_file)
}
restore_shell_history() {
awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ { print $2, $3, $7, $10; }' $(last_resurrect_file) |
while IFS=$'\t' read session_name window_number pane_index pane_command; do
if ! is_pane_registered_as_existing "$session_name" "$window_number" "$pane_index"; then
if [ "$pane_command" = "bash" ]; then
local pane_id="$session_name:$window_number.$pane_index"
# tmux send-keys has -R option that should reset the terminal.
# However, appending 'clear' to the command seems to work more reliably.
local read_command="history -r '$(resurrect_history_file "$pane_id")'; clear"
tmux send-keys -t "$pane_id" "$read_command" C-m
fi
fi
done
}
restore_all_pane_processes() {
if restore_pane_processes_enabled; then
local pane_full_command
@ -168,13 +183,6 @@ restore_active_pane_for_each_window() {
done
}
restore_zoomed_windows() {
awk 'BEGIN { FS="\t"; OFS="\t" } /^window/ && $5 ~ /Z/ { print $2, $3; }' $(last_resurrect_file) |
while IFS=$'\t' read session_name window_number; do
tmux resize-pane -t "${session_name}:${window_number}" -Z
done
}
restore_active_and_alternate_windows() {
awk 'BEGIN { FS="\t"; OFS="\t" } /^window/ && $5 ~ /[*-]/ { print $2, $4, $3; }' $(last_resurrect_file) |
sort -u |
@ -196,6 +204,9 @@ main() {
start_spinner "Restoring..." "Tmux restore complete!"
restore_all_panes
restore_pane_layout_for_each_window >/dev/null 2>&1
if save_bash_history_option_on; then
restore_shell_history
fi
restore_all_pane_processes
# below functions restore exact cursor positions
restore_active_pane_for_each_window

View File

@ -65,11 +65,36 @@ dump_panes_raw() {
tmux list-panes -a -F "$(pane_format)"
}
_save_command_strategy_file() {
local save_command_strategy="$(get_tmux_option "$save_command_strategy_option" "$default_save_command_strategy")"
local strategy_file="$CURRENT_DIR/../save_command_strategies/${save_command_strategy}.sh"
local default_strategy_file="$CURRENT_DIR/../save_command_strategies/${default_save_command_strategy}.sh"
if [ -e "$strategy_file" ]; then # strategy file exists?
echo "$strategy_file"
else
echo "$default_strategy_file"
fi
}
pane_full_command() {
local pane_pid="$1"
ps -eo "ppid command" |
grep "^${pane_pid}" |
cut -d' ' -f2-
local strategy_file="$(_save_command_strategy_file)"
# execute strategy script to get pane full command
$strategy_file "$pane_pid"
}
save_shell_history() {
local pane_id="$1"
local pane_command="$2"
local full_command="$3"
if [ "$pane_command" = "bash" ] && [ "$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")'"
# 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" C-e C-u "$write_command" C-m
fi
}
# translates pane pid to process command running inside a pane
@ -78,6 +103,11 @@ dump_panes() {
local d=$'\t' # delimiter
dump_panes_raw |
while IFS=$'\t' read line_type session_name window_number window_name window_active window_flags pane_index dir pane_active pane_command pane_pid; do
# check if current pane is part of a maximized window and if the pane is active
if [[ "${window_flags}" == *Z* ]] && [[ ${pane_active} == 1 ]]; then
# unmaximize the pane
tmux resize-pane -Z -t "${session_name}:${window_number}"
fi
full_command="$(pane_full_command $pane_pid)"
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}"
done
@ -91,6 +121,13 @@ dump_state() {
tmux display-message -p "$(state_format)"
}
dump_bash_history() {
dump_panes |
while IFS=$'\t' 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
}
save_all() {
local resurrect_file_path="$(resurrect_file_path)"
mkdir -p "$(resurrect_dir)"
@ -98,6 +135,10 @@ save_all() {
dump_windows >> $resurrect_file_path
dump_state >> $resurrect_file_path
ln -fs "$resurrect_file_path" "$(last_resurrect_file)"
if save_bash_history_option_on; then
dump_bash_history
fi
restore_zoomed_windows
}
main() {

View File

@ -16,7 +16,7 @@ MESSAGE="$1"
END_MESSAGE="$2"
SPIN='-\|/'
trap "tmux display-message $END_MESSAGE; exit" SIGINT SIGTERM
trap "tmux display-message '$END_MESSAGE'; exit" SIGINT SIGTERM
main() {
local i=0

View File

@ -7,7 +7,7 @@ restore_option="@resurrect-restore"
# default processes that are restored
default_proc_list_option="@resurrect-default-processes"
default_proc_list='vi vim emacs man less more tail top htop irssi'
default_proc_list='vi vim nvim emacs man less more tail top htop irssi'
# User defined processes that are restored
# 'false' - nothing is restored
@ -23,3 +23,8 @@ restore_processes=""
restore_process_strategy_option="@resurrect-strategy-"
inline_strategy_token="->"
save_command_strategy_option="@resurrect-save-command-strategy"
default_save_command_strategy="ps"
bash_history_option="@resurrect-save-bash-history"

30
strategies/nvim_session.sh Executable file
View File

@ -0,0 +1,30 @@
#!/usr/bin/env bash
# "nvim session strategy"
#
# Same as vim strategy, see file 'vim_session.sh'
ORIGINAL_COMMAND="$1"
DIRECTORY="$2"
nvim_session_file_exists() {
[ -e "${DIRECTORY}/Session.vim" ]
}
original_command_contains_session_flag() {
[[ "$ORIGINAL_COMMAND" =~ "-S" ]]
}
main() {
if nvim_session_file_exists; then
echo "nvim -S"
elif original_command_contains_session_flag; then
# Session file does not exist, yet the original nvim command contains
# session flag `-S`. This will cause an error, so we're falling back to
# starting plain nvim.
echo "nvim"
else
echo "$ORIGINAL_COMMAND"
fi
}
main

BIN
video/issue_vid.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB