Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
e2e55c6faa | |||
cedd1292c1 | |||
05cf790493 | |||
f9ef86d604 | |||
9a6e4a1a2c | |||
bd13c9bae8 | |||
87b2d75794 | |||
54f47a4015 |
10
CHANGELOG.md
10
CHANGELOG.md
@ -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
|
||||||
|
16
README.md
16
README.md
@ -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.
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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}"
|
||||||
|
Reference in New Issue
Block a user