8 Commits

Author SHA1 Message Date
e2e55c6faa v0.3.0 2014-08-29 17:21:27 +02:00
cedd1292c1 Restore window zoom state
Close #25
2014-08-29 17:04:00 +02:00
05cf790493 Enable restoring more panes per window
Closes #24
2014-08-29 16:16:21 +02:00
f9ef86d604 Do not restore processes within existing panes
Closes #23
2014-08-29 15:50:18 +02:00
9a6e4a1a2c Make pane restorations idempotent 2014-08-29 12:49:06 +02:00
bd13c9bae8 Clean out comments 2014-08-29 01:04:50 +02:00
87b2d75794 Update readme 2014-08-29 01:04:03 +02:00
54f47a4015 Properly restore pane with top program
Fixes #17
2014-08-29 00:42:11 +02:00
5 changed files with 83 additions and 19 deletions

View File

@ -2,6 +2,16 @@
### master ### master
### v0.3.0, 2014-08-29
- bugfix: when top is running the pane `$PWD` can't be saved. This was causing
issues during the restore and is now fixed.
- restoring sessions multiple times messes up the whole environment - new panes
are all around. This is now fixed - pane restorations are now idempotent.
- if pane exists from before session restore - do not restore the process within
it. This makes the restoration process even more idempotent.
- more panes within a window can now be restored
- restore window zoom state
### v0.2.0, 2014-08-29 ### v0.2.0, 2014-08-29
- bugfix: with vim 'session' strategy, if the session file does not exist - make - bugfix: with vim 'session' strategy, if the session file does not exist - make
sure vim does not contain `-S` flag sure vim does not contain `-S` flag

View File

@ -2,16 +2,16 @@
Persists `tmux` environment across system restarts. Persists `tmux` environment across system restarts.
Tmux is great, except when you have to restart your computer. You loose all the Tmux is great, except when you have to restart the computer. You loose all the
running programs, working directories, pane layouts etc. running programs, working directories, pane layouts etc.
There are helpful management tools out there, but they require initial There are helpful management tools out there, but they require initial
configuration and continuous updates as your workflow evolves or you start new configuration and continuous updates as your workflow evolves or you start new
projects. projects.
Enter `tmux-session-saver`: tmux persistence without configuration so there are `tmux-session-saver` saves all the little details from tmux environment so it
no interruptions in your workflow. can be easily restored after system restart. No configuration is required.
It will even (optionally) [restore vim sessions](#restoring-vim-sessions)! It even (optionally) [restores vim sessions](#restoring-vim-sessions)!
### Key bindings ### Key bindings
@ -28,8 +28,10 @@ This plugin goes to great lengths to save and restore all the details from your
- **exact pane layouts** within windows - **exact pane layouts** within windows
- active and alternative session - active and alternative session
- active and alternative window for each session - active and alternative window for each session
- windows with focus
- active pane for each window - active pane for each window
- programs running within a pane! More details in the [configuration section](#configuration). - programs running within a pane! More details in the
[configuration section](#configuration).
- restoring vim sessions (optional). More details in - restoring vim sessions (optional). More details in
[restoring vim sessions](#restoring-vim-sessions). [restoring vim sessions](#restoring-vim-sessions).
@ -66,7 +68,9 @@ You should now be able to use the plugin.
### Configuration ### Configuration
Only a conservative list of programs is restored by default: 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 irb pry "~rails console"`. `vi vim emacs man less more tail top htop irssi irb pry "~rails console"`.
Open a github issue if you think some other program should be on the default list. Open a github issue if you think some other program should be on the default list.

View File

@ -13,7 +13,7 @@ restore_pane_process() {
local window_number="$3" local window_number="$3"
local pane_index="$4" local pane_index="$4"
local dir="$5" local dir="$5"
if _process_should_be_restored "$pane_full_command"; then if _process_should_be_restored "$pane_full_command" "$session_name" "$window_number" "$pane_index"; then
tmux switch-client -t "${session_name}:${window_number}" tmux switch-client -t "${session_name}:${window_number}"
tmux select-pane -t "$pane_index" tmux select-pane -t "$pane_index"
@ -21,8 +21,6 @@ restore_pane_process() {
local strategy_file="$(_get_strategy_file "$pane_full_command")" local strategy_file="$(_get_strategy_file "$pane_full_command")"
local strategy_command="$($strategy_file "$pane_full_command" "$dir")" local strategy_command="$($strategy_file "$pane_full_command" "$dir")"
tmux send-keys "$strategy_command" "C-m" tmux send-keys "$strategy_command" "C-m"
# tmux send-keys "Strategy! $pane_full_command $strategy_file"
# tmux send-keys "Strategy! $strategy_command"
else else
# just invoke the command # just invoke the command
tmux send-keys "$pane_full_command" "C-m" tmux send-keys "$pane_full_command" "C-m"
@ -34,7 +32,14 @@ restore_pane_process() {
_process_should_be_restored() { _process_should_be_restored() {
local pane_full_command="$1" local pane_full_command="$1"
if _restore_all_processes; then local session_name="$2"
local window_number="$3"
local pane_index="$4"
if is_pane_registered_as_existing "$session_name" "$window_number" "$pane_index"; then
# Scenario where pane existed before restoration, so we're not
# restoring the proces either.
return 1
elif _restore_all_processes; then
return 0 return 0
elif _process_on_the_restore_list "$pane_full_command"; then elif _process_on_the_restore_list "$pane_full_command"; then
return 0 return 0

View File

@ -7,6 +7,12 @@ source "$CURRENT_DIR/helpers.sh"
source "$CURRENT_DIR/process_restore_helpers.sh" source "$CURRENT_DIR/process_restore_helpers.sh"
source "$CURRENT_DIR/spinner_helpers.sh" source "$CURRENT_DIR/spinner_helpers.sh"
# Global variable.
# Used during the restoration: if a pane already exists from before, it is
# saved in the array in this variable. Later, process running in existing pane
# is also not restored. That makes the restoration process more idempotent.
EXISTING_PANES_VAR=""
is_line_type() { is_line_type() {
local line_type="$1" local line_type="$1"
local line="$2" local line="$2"
@ -22,6 +28,31 @@ check_saved_session_exists() {
fi fi
} }
pane_exists() {
local session_name="$1"
local window_number="$2"
local pane_index="$3"
tmux list-panes -t "${session_name}:${window_number}" -F "#{pane_index}" 2>/dev/null |
\grep -q "^$pane_index$"
}
register_existing_pane() {
local session_name="$1"
local window_number="$2"
local pane_index="$3"
local pane_custom_id="${session_name}:${window_number}:${pane_index}"
local delimiter=$'\t'
EXISTING_PANES_VAR="${EXISTING_PANES_VAR}${delimiter}${pane_custom_id}"
}
is_pane_registered_as_existing() {
local session_name="$1"
local window_number="$2"
local pane_index="$3"
local pane_custom_id="${session_name}:${window_number}:${pane_index}"
[[ "$EXISTING_PANES_VAR" =~ "$pane_custom_id" ]]
}
window_exists() { window_exists() {
local session_name="$1" local session_name="$1"
local window_number="$2" local window_number="$2"
@ -68,23 +99,28 @@ new_pane() {
local window_number="$2" local window_number="$2"
local window_name="$3" local window_name="$3"
local dir="$4" local dir="$4"
tmux split-window -t "${session_name}:${window_number}" -c "$dir" tmux split-window -t "${session_name}:${window_number}" -c "$dir" -h
tmux resize-pane -t "${session_name}:${window_number}" -L "999"
} }
restore_pane() { restore_pane() {
local pane="$1" local pane="$1"
echo "$pane" |
while IFS=$'\t' 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=$'\t' read line_type session_name window_number window_name window_active window_flags pane_index dir pane_active pane_command pane_full_command; do
dir="$(remove_first_char "$dir")"
window_name="$(remove_first_char "$window_name")" window_name="$(remove_first_char "$window_name")"
pane_full_command="$(remove_first_char "$pane_full_command")" pane_full_command="$(remove_first_char "$pane_full_command")"
if window_exists "$session_name" "$window_number"; then if pane_exists "$session_name" "$window_number" "$pane_index"; then
# Pane exists, no need to create it!
# Pane existence is registered. Later, it's process also isn't restored.
register_existing_pane "$session_name" "$window_number" "$pane_index"
elif window_exists "$session_name" "$window_number"; then
new_pane "$session_name" "$window_number" "$window_name" "$dir" new_pane "$session_name" "$window_number" "$window_name" "$dir"
elif session_exists "$session_name"; then elif session_exists "$session_name"; then
new_window "$session_name" "$window_number" "$window_name" "$dir" new_window "$session_name" "$window_number" "$window_name" "$dir"
else else
new_session "$session_name" "$window_number" "$window_name" "$dir" new_session "$session_name" "$window_number" "$window_name" "$dir"
fi fi
done done < <(echo "$pane")
} }
restore_state() { restore_state() {
@ -96,7 +132,7 @@ restore_state() {
done done
} }
restore_all_sessions() { restore_all_panes() {
while read line; do while read line; do
if is_line_type "pane" "$line"; then if is_line_type "pane" "$line"; then
restore_pane "$line" restore_pane "$line"
@ -109,6 +145,7 @@ restore_all_pane_processes() {
local pane_full_command local pane_full_command
awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ && $11 !~ "^:$" { print $2, $3, $7, $8, $11; }' $(last_session_path) | awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ && $11 !~ "^:$" { print $2, $3, $7, $8, $11; }' $(last_session_path) |
while IFS=$'\t' read session_name window_number pane_index dir pane_full_command; do while IFS=$'\t' read 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")" pane_full_command="$(remove_first_char "$pane_full_command")"
restore_pane_process "$pane_full_command" "$session_name" "$window_number" "$pane_index" "$dir" restore_pane_process "$pane_full_command" "$session_name" "$window_number" "$pane_index" "$dir"
done done
@ -123,13 +160,20 @@ restore_pane_layout_for_each_window() {
} }
restore_active_pane_for_each_window() { restore_active_pane_for_each_window() {
awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ && $7 != 0 && $9 == 1 { print $2, $3, $7; }' $(last_session_path) | awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ && $9 == 1 { print $2, $3, $7; }' $(last_session_path) |
while IFS=$'\t' read session_name window_number active_pane; do while IFS=$'\t' read session_name window_number active_pane; do
tmux switch-client -t "${session_name}:${window_number}" tmux switch-client -t "${session_name}:${window_number}"
tmux select-pane -t "$active_pane" tmux select-pane -t "$active_pane"
done done
} }
restore_zoomed_windows() {
awk 'BEGIN { FS="\t"; OFS="\t" } /^window/ && $5 ~ /Z/ { print $2, $3; }' $(last_session_path) |
while IFS=$'\t' read session_name window_number; do
tmux resize-pane -t "${session_name}:${window_number}" -Z
done
}
restore_active_and_alternate_windows() { restore_active_and_alternate_windows() {
awk 'BEGIN { FS="\t"; OFS="\t" } /^window/ && $5 ~ /[*-]/ { print $2, $4, $3; }' $(last_session_path) | awk 'BEGIN { FS="\t"; OFS="\t" } /^window/ && $5 ~ /[*-]/ { print $2, $4, $3; }' $(last_session_path) |
sort -u | sort -u |
@ -149,11 +193,12 @@ restore_active_and_alternate_sessions() {
main() { main() {
if supported_tmux_version_ok && check_saved_session_exists; then if supported_tmux_version_ok && check_saved_session_exists; then
start_spinner start_spinner
restore_all_sessions restore_all_panes
restore_all_pane_processes
restore_pane_layout_for_each_window >/dev/null 2>&1 restore_pane_layout_for_each_window >/dev/null 2>&1
restore_all_pane_processes
# below functions restore exact cursor positions # below functions restore exact cursor positions
restore_active_pane_for_each_window restore_active_pane_for_each_window
restore_zoomed_windows
restore_active_and_alternate_windows restore_active_and_alternate_windows
restore_active_and_alternate_sessions restore_active_and_alternate_sessions
stop_spinner stop_spinner

View File

@ -21,7 +21,7 @@ pane_format() {
format+="${delimiter}" format+="${delimiter}"
format+="#{pane_index}" format+="#{pane_index}"
format+="${delimiter}" format+="${delimiter}"
format+="#{pane_current_path}" format+=":#{pane_current_path}"
format+="${delimiter}" format+="${delimiter}"
format+="#{pane_active}" format+="#{pane_active}"
format+="${delimiter}" format+="${delimiter}"