Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
ee1ab0c728 | |||
18f4d1099e | |||
655bdb9a75 | |||
3da5d61b5b | |||
5509256a02 | |||
cde50d4d92 | |||
07bba0fde7 | |||
1e945c2cac | |||
7f50660918 | |||
cbf58ac613 | |||
2edd3ff98d | |||
bcad7cd1ea | |||
4d5c0a2a0d | |||
8051fb9d36 | |||
a649614a20 | |||
8166fa2602 | |||
ecc42c5a56 | |||
aa8f323b8b | |||
c78a38803a | |||
877780eb02 | |||
8ba7d6d873 | |||
c993e9ff00 | |||
81ed0811b4 | |||
732d53cede | |||
5c2853a55f | |||
70d78e8d73 | |||
1280e659d5 | |||
3dce66acaa |
34
CHANGELOG.md
34
CHANGELOG.md
@ -1,4 +1,36 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
# master
|
### master
|
||||||
|
|
||||||
|
### v0.1.0, 2014-08-28
|
||||||
|
- refactor checking if saved tmux session exists
|
||||||
|
- spinner while tmux sessions are restored
|
||||||
|
|
||||||
|
### v0.0.5, 2014-08-28
|
||||||
|
- restore pane processes
|
||||||
|
- user option for disabling pane process restoring
|
||||||
|
- enable whitelisting processes that will be restored
|
||||||
|
- expand readme with configuration options
|
||||||
|
- enable command strategies; enable restoring vim sessions
|
||||||
|
- update readme: explain restoring vim sessions
|
||||||
|
|
||||||
|
### v0.0.4, 2014-08-26
|
||||||
|
- restore pane layout for each window
|
||||||
|
- bugfix: correct pane ordering in a window
|
||||||
|
|
||||||
|
### v0.0.3, 2014-08-26
|
||||||
|
- save and restore current and alternate session
|
||||||
|
- fix a bug with non-existing window names
|
||||||
|
- restore active pane for each window that has multiple panes
|
||||||
|
- restore active and alternate window for each session
|
||||||
|
|
||||||
|
### v0.0.2, 2014-08-26
|
||||||
|
- saving a new session does not remove the previous one
|
||||||
|
- make the directory where sessions are stored configurable
|
||||||
|
- support only Tmux v1.9 or greater
|
||||||
|
- display a nice error message if saved session file does not exist
|
||||||
|
- added README
|
||||||
|
|
||||||
|
### v0.0.1, 2014-08-26
|
||||||
- started a project
|
- started a project
|
||||||
|
- basic saving and restoring works
|
||||||
|
104
README.md
104
README.md
@ -1,4 +1,108 @@
|
|||||||
# Tmux Session Saver
|
# Tmux Session Saver
|
||||||
|
|
||||||
|
Persists `tmux` environment across system restarts.
|
||||||
|
|
||||||
|
Tmux is great, except when you have to restart your computer. You loose all the
|
||||||
|
running programs, working directories, pane layouts etc.
|
||||||
|
There are helpful management tools out there, but they require initial
|
||||||
|
configuration and continuous updates as your workflow evolves or you start new
|
||||||
|
projects.
|
||||||
|
|
||||||
|
Enter `tmux-session-saver`: tmux persistence without configuration so there are
|
||||||
|
no interruptions in your workflow.
|
||||||
|
|
||||||
|
It will even (optionally) [restore vim sessions](#restoring-vim-sessions)!
|
||||||
|
|
||||||
|
### Key bindings
|
||||||
|
|
||||||
|
- `prefix + Alt-s` - save
|
||||||
|
- `prefix + Alt-r` - restore
|
||||||
|
|
||||||
|
### About
|
||||||
|
|
||||||
|
This plugin goes to great lengths to save and restore all the details from your
|
||||||
|
`tmux` environment. Here's what's been taken care of:
|
||||||
|
|
||||||
|
- all sessions, windows, panes and their order
|
||||||
|
- current working directory for each pane
|
||||||
|
- **exact pane layouts** within windows
|
||||||
|
- active and alternative session
|
||||||
|
- active and alternative window for each session
|
||||||
|
- 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).
|
||||||
|
|
||||||
|
Requirements / dependencies: `tmux 1.9` or higher, `pgrep`
|
||||||
|
|
||||||
|
### Installation with [Tmux Plugin Manager](https://github.com/tmux-plugins/tpm) (recommended)
|
||||||
|
|
||||||
|
Add plugin to the list of TPM plugins in `.tmux.conf`:
|
||||||
|
|
||||||
|
set -g @tpm_plugins " \
|
||||||
|
tmux-plugins/tpm \
|
||||||
|
tmux-plugins/tmux-session-saver \
|
||||||
|
"
|
||||||
|
|
||||||
|
Hit `prefix + I` to fetch the plugin and source it. You should now be able to
|
||||||
|
use the plugin.
|
||||||
|
|
||||||
|
### Manual Installation
|
||||||
|
|
||||||
|
Clone the repo:
|
||||||
|
|
||||||
|
$ git clone https://github.com/tmux-plugins/tmux-session-saver ~/clone/path
|
||||||
|
|
||||||
|
Add this line to the bottom of `.tmux.conf`:
|
||||||
|
|
||||||
|
run-shell ~/clone/path/session_saver.tmux
|
||||||
|
|
||||||
|
Reload TMUX environment:
|
||||||
|
|
||||||
|
# type this in terminal
|
||||||
|
$ tmux source-file ~/.tmux.conf
|
||||||
|
|
||||||
|
You should now be able to use the plugin.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
By default, only a conservative list of programs is restored:
|
||||||
|
`vim emacs man less more tail top htop irssi`.
|
||||||
|
Open a github issue if you think some other program should be on the default list.
|
||||||
|
|
||||||
|
- Restore additional programs by putting the following in `.tmux.conf`:
|
||||||
|
|
||||||
|
set -g @session-saver-processes 'ssh telnet myprogram'
|
||||||
|
|
||||||
|
- Don't restore any programs:
|
||||||
|
|
||||||
|
set -g @session-saver-processes 'false'
|
||||||
|
|
||||||
|
- Restore **all** programs (be careful with this!):
|
||||||
|
|
||||||
|
set -g @session-saver-processes ':all:'
|
||||||
|
|
||||||
|
#### Restoring vim sessions
|
||||||
|
|
||||||
|
- save vim sessions - I recommend [tpope/vim-obsession](tpope/vim-obsession)
|
||||||
|
- in `.tmux.conf`:
|
||||||
|
|
||||||
|
set -g @session-saver-strategy-vim "session"
|
||||||
|
|
||||||
|
`tmux-session-saver` will now restore vim sessions if `Sessions.vim` file is
|
||||||
|
present.
|
||||||
|
|
||||||
|
### Reporting bugs and contributing
|
||||||
|
|
||||||
|
Code contributions are welcome!
|
||||||
|
|
||||||
|
If you find a bug please report it in the issues. When reporting a bug please
|
||||||
|
attach a file symlinked to `~/.tmux/sessions/last`.
|
||||||
|
|
||||||
|
### Credits
|
||||||
|
|
||||||
|
[Mislav Marohnić](https://github.com/mislav) - the idea for the plugin came from his
|
||||||
|
[tmux-session script](https://github.com/mislav/dotfiles/blob/master/bin/tmux-session).
|
||||||
|
|
||||||
### License
|
### License
|
||||||
[MIT](LICENSE.md)
|
[MIT](LICENSE.md)
|
||||||
|
78
scripts/check_tmux_version.sh
Executable file
78
scripts/check_tmux_version.sh
Executable file
@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
VERSION="$1"
|
||||||
|
UNSUPPORTED_MSG="$2"
|
||||||
|
|
||||||
|
get_tmux_option() {
|
||||||
|
local option=$1
|
||||||
|
local default_value=$2
|
||||||
|
local option_value=$(tmux show-option -gqv "$option")
|
||||||
|
if [ -z "$option_value" ]; then
|
||||||
|
echo "$default_value"
|
||||||
|
else
|
||||||
|
echo "$option_value"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensures a message is displayed for 5 seconds in tmux prompt.
|
||||||
|
# Does not override the 'display-time' tmux option.
|
||||||
|
display_message() {
|
||||||
|
local message="$1"
|
||||||
|
|
||||||
|
# display_duration defaults to 5 seconds, if not passed as an argument
|
||||||
|
if [ "$#" -eq 2 ]; then
|
||||||
|
local display_duration="$2"
|
||||||
|
else
|
||||||
|
local display_duration="5000"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# saves user-set 'display-time' option
|
||||||
|
local saved_display_time=$(get_tmux_option "display-time" "750")
|
||||||
|
|
||||||
|
# sets message display time to 5 seconds
|
||||||
|
tmux set-option -gq display-time "$display_duration"
|
||||||
|
|
||||||
|
# displays message
|
||||||
|
tmux display-message "$message"
|
||||||
|
|
||||||
|
# restores original 'display-time' value
|
||||||
|
tmux set-option -gq display-time "$saved_display_time"
|
||||||
|
}
|
||||||
|
|
||||||
|
# this is used to get "clean" integer version number. Examples:
|
||||||
|
# `tmux 1.9` => `19`
|
||||||
|
# `1.9a` => `19`
|
||||||
|
get_digits_from_string() {
|
||||||
|
local string="$1"
|
||||||
|
local only_digits="$(echo "$string" | tr -dC '[:digit:]')"
|
||||||
|
echo "$only_digits"
|
||||||
|
}
|
||||||
|
|
||||||
|
tmux_version_int() {
|
||||||
|
local tmux_version_string=$(tmux -V)
|
||||||
|
echo "$(get_digits_from_string "$tmux_version_string")"
|
||||||
|
}
|
||||||
|
|
||||||
|
unsupported_version_message() {
|
||||||
|
if [ -n "$UNSUPPORTED_MSG" ]; then
|
||||||
|
echo "$UNSUPPORTED_MSG"
|
||||||
|
else
|
||||||
|
echo "Error, Tmux version unsupported! Please install Tmux version $VERSION or greater!"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_if_unsupported_version() {
|
||||||
|
local current_version="$1"
|
||||||
|
local supported_version="$2"
|
||||||
|
if [ "$current_version" -lt "$supported_version" ]; then
|
||||||
|
display_message "$(unsupported_version_message)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local supported_version_int="$(get_digits_from_string "$VERSION")"
|
||||||
|
local current_version_int="$(tmux_version_int)"
|
||||||
|
exit_if_unsupported_version "$current_version_int" "$supported_version_int"
|
||||||
|
}
|
||||||
|
main
|
@ -1,3 +1,10 @@
|
|||||||
|
# configurable constants
|
||||||
|
default_sessions_dir="$HOME/.tmux/sessions"
|
||||||
|
sessions_dir_option="@session-saver-dir"
|
||||||
|
|
||||||
|
SUPPORTED_VERSION="1.9"
|
||||||
|
|
||||||
|
# helper functions
|
||||||
get_tmux_option() {
|
get_tmux_option() {
|
||||||
local option="$1"
|
local option="$1"
|
||||||
local default_value="$2"
|
local default_value="$2"
|
||||||
@ -33,3 +40,23 @@ display_message() {
|
|||||||
# restores original 'display-time' value
|
# restores original 'display-time' value
|
||||||
tmux set-option -gq display-time "$saved_display_time"
|
tmux set-option -gq display-time "$saved_display_time"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
supported_tmux_version_ok() {
|
||||||
|
$CURRENT_DIR/check_tmux_version.sh "$SUPPORTED_VERSION"
|
||||||
|
}
|
||||||
|
|
||||||
|
# path helpers
|
||||||
|
|
||||||
|
sessions_dir() {
|
||||||
|
echo $(get_tmux_option "$sessions_dir_option" "$default_sessions_dir")
|
||||||
|
}
|
||||||
|
|
||||||
|
session_path() {
|
||||||
|
local timestamp="$(date +"%Y-%m-%dT%H:%M:%S")"
|
||||||
|
echo "$(sessions_dir)/tmux_session_${timestamp}.txt"
|
||||||
|
}
|
||||||
|
|
||||||
|
last_session_path() {
|
||||||
|
echo "$(sessions_dir)/last"
|
||||||
|
}
|
||||||
|
121
scripts/process_restore_helpers.sh
Normal file
121
scripts/process_restore_helpers.sh
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
# default processes that are restored
|
||||||
|
default_proc_list_option="@session-saver-default-processes"
|
||||||
|
default_proc_list="vim emacs man less more tail top htop irssi"
|
||||||
|
|
||||||
|
# User defined processes that are restored
|
||||||
|
# 'false' - nothing is restored
|
||||||
|
# ':all:' - all processes are restored
|
||||||
|
#
|
||||||
|
# user defined list of programs that are restored:
|
||||||
|
# 'my_program foo another_program'
|
||||||
|
restore_processes_option="@session-saver-processes"
|
||||||
|
restore_processes=""
|
||||||
|
|
||||||
|
# Defines part of the user variable. Example usage:
|
||||||
|
# set -g @session-saver-strategy-vim "session"
|
||||||
|
restore_process_strategy_option="@session-saver-strategy-"
|
||||||
|
|
||||||
|
restore_pane_processes_enabled() {
|
||||||
|
local restore_processes="$(get_tmux_option "$restore_processes_option" "$restore_processes")"
|
||||||
|
if [ "$restore_processes" == "false" ]; then
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
restore_pane_process() {
|
||||||
|
local pane_full_command="$1"
|
||||||
|
local session_name="$2"
|
||||||
|
local window_number="$3"
|
||||||
|
local pane_index="$4"
|
||||||
|
local dir="$5"
|
||||||
|
if _process_should_be_restored "$pane_full_command"; then
|
||||||
|
tmux switch-client -t "${session_name}:${window_number}"
|
||||||
|
tmux select-pane -t "$pane_index"
|
||||||
|
|
||||||
|
if _strategy_exists "$pane_full_command"; then
|
||||||
|
local strategy_file="$(_get_strategy_file "$pane_full_command")"
|
||||||
|
local strategy_command="$($strategy_file "$pane_full_command" "$dir")"
|
||||||
|
tmux send-keys "$strategy_command" "C-m"
|
||||||
|
# tmux send-keys "Strategy! $pane_full_command $strategy_file"
|
||||||
|
# tmux send-keys "Strategy! $strategy_command"
|
||||||
|
else
|
||||||
|
# just invoke the command
|
||||||
|
tmux send-keys "$pane_full_command" "C-m"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# private functions below
|
||||||
|
|
||||||
|
_process_should_be_restored() {
|
||||||
|
local pane_full_command="$1"
|
||||||
|
if _restore_all_processes; then
|
||||||
|
return 0
|
||||||
|
elif _process_on_the_restore_list "$pane_full_command"; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_restore_all_processes() {
|
||||||
|
local restore_processes="$(get_tmux_option "$restore_processes_option" "$restore_processes")"
|
||||||
|
if [ $restore_processes == ":all:" ]; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_process_on_the_restore_list() {
|
||||||
|
local pane_full_command="$1"
|
||||||
|
local restore_list="$(_restore_list)"
|
||||||
|
local proc
|
||||||
|
for proc in $restore_list; do
|
||||||
|
if [[ "$pane_full_command" =~ (^$proc) ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
_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
|
||||||
|
# user didn't define any processes
|
||||||
|
echo "$default_processes"
|
||||||
|
else
|
||||||
|
echo "$default_processes $user_processes"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_strategy_exists() {
|
||||||
|
local pane_full_command="$1"
|
||||||
|
local strategy="$(_get_command_strategy "$pane_full_command")"
|
||||||
|
if [ -n "$strategy" ]; then # strategy set?
|
||||||
|
local strategy_file="$(_get_strategy_file "$pane_full_command")"
|
||||||
|
[ -e "$strategy_file" ] # strategy file exists?
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_get_command_strategy() {
|
||||||
|
local pane_full_command="$1"
|
||||||
|
local command="$(_just_command "$pane_full_command")"
|
||||||
|
get_tmux_option "${restore_process_strategy_option}${command}" ""
|
||||||
|
}
|
||||||
|
|
||||||
|
_just_command() {
|
||||||
|
echo "$1" | cut -d' ' -f1
|
||||||
|
}
|
||||||
|
|
||||||
|
_get_strategy_file() {
|
||||||
|
local pane_full_command="$1"
|
||||||
|
local strategy="$(_get_command_strategy "$pane_full_command")"
|
||||||
|
local command="$(_just_command "$pane_full_command")"
|
||||||
|
echo "$CURRENT_DIR/../strategies/${command}_${strategy}.sh"
|
||||||
|
}
|
@ -3,6 +3,23 @@
|
|||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
source "$CURRENT_DIR/helpers.sh"
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
source "$CURRENT_DIR/process_restore_helpers.sh"
|
||||||
|
source "$CURRENT_DIR/spinner_helpers.sh"
|
||||||
|
|
||||||
|
is_line_type() {
|
||||||
|
local line_type="$1"
|
||||||
|
local line="$2"
|
||||||
|
echo "$line" |
|
||||||
|
\grep -q "^$line_type"
|
||||||
|
}
|
||||||
|
|
||||||
|
check_saved_session_exists() {
|
||||||
|
local saved_session="$(last_session_path)"
|
||||||
|
if [ ! -f $saved_session ]; then
|
||||||
|
display_message "Saved tmux session not found!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
window_exists() {
|
window_exists() {
|
||||||
local session_name="$1"
|
local session_name="$1"
|
||||||
@ -24,6 +41,10 @@ tmux_socket() {
|
|||||||
echo $TMUX | cut -d',' -f1
|
echo $TMUX | cut -d',' -f1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remove_first_char() {
|
||||||
|
echo "$1" | cut -c2-
|
||||||
|
}
|
||||||
|
|
||||||
new_window() {
|
new_window() {
|
||||||
local session_name="$1"
|
local session_name="$1"
|
||||||
local window_number="$2"
|
local window_number="$2"
|
||||||
@ -50,35 +71,96 @@ 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 -d -t "${session_name}:${window_number}" -c "$dir"
|
tmux split-window -t "${session_name}:${window_number}" -c "$dir"
|
||||||
}
|
}
|
||||||
|
|
||||||
restore_pane() {
|
restore_pane() {
|
||||||
local pane="$1"
|
local pane="$1"
|
||||||
echo "$pane" |
|
echo "$pane" |
|
||||||
while IFS=$'\t' read session_name window_number window_name dir; 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
|
||||||
# echo "$session_name - $window_number - $window_name - $dir"
|
window_name="$(remove_first_char "$window_name")"
|
||||||
|
pane_full_command="$(remove_first_char "$pane_full_command")"
|
||||||
if window_exists "$session_name" "$window_number"; then
|
if window_exists "$session_name" "$window_number"; then
|
||||||
echo "new pane $session_name $window_number"
|
|
||||||
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
|
||||||
echo "new window $session_name $window_number"
|
|
||||||
new_window "$session_name" "$window_number" "$window_name" "$dir"
|
new_window "$session_name" "$window_number" "$window_name" "$dir"
|
||||||
else
|
else
|
||||||
echo "new session $session_name"
|
|
||||||
new_session "$session_name" "$window_number" "$window_name" "$dir"
|
new_session "$session_name" "$window_number" "$window_name" "$dir"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
restore_state() {
|
||||||
|
local state="$1"
|
||||||
|
echo "$state" |
|
||||||
|
while IFS=$'\t' read line_type client_session client_last_session; do
|
||||||
|
tmux switch-client -t "$client_last_session"
|
||||||
|
tmux switch-client -t "$client_session"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
restore_all_sessions() {
|
restore_all_sessions() {
|
||||||
while read line; do
|
while read line; do
|
||||||
|
if is_line_type "pane" "$line"; then
|
||||||
restore_pane "$line"
|
restore_pane "$line"
|
||||||
done < $HOME/.tmux/session
|
fi
|
||||||
display_message "Restored all Tmux sessions!"
|
done < $(last_session_path)
|
||||||
|
}
|
||||||
|
|
||||||
|
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_session_path) |
|
||||||
|
while IFS=$'\t' read session_name window_number pane_index dir pane_full_command; do
|
||||||
|
pane_full_command="$(remove_first_char "$pane_full_command")"
|
||||||
|
restore_pane_process "$pane_full_command" "$session_name" "$window_number" "$pane_index" "$dir"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
restore_pane_layout_for_each_window() {
|
||||||
|
\grep '^window' $(last_session_path) |
|
||||||
|
while IFS=$'\t' read line_type session_name window_number window_active window_flags window_layout; do
|
||||||
|
tmux select-layout -t "${session_name}:${window_number}" "$window_layout"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
restore_active_pane_for_each_window() {
|
||||||
|
awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ && $7 != 0 && $9 == 1 { print $2, $3, $7; }' $(last_session_path) |
|
||||||
|
while IFS=$'\t' read session_name window_number active_pane; do
|
||||||
|
tmux switch-client -t "${session_name}:${window_number}"
|
||||||
|
tmux select-pane -t "$active_pane"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
restore_active_and_alternate_windows() {
|
||||||
|
awk 'BEGIN { FS="\t"; OFS="\t" } /^window/ && $5 ~ /[*-]/ { print $2, $4, $3; }' $(last_session_path) |
|
||||||
|
sort -u |
|
||||||
|
while IFS=$'\t' read session_name active_window window_number; do
|
||||||
|
tmux switch-client -t "${session_name}:${window_number}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
restore_active_and_alternate_sessions() {
|
||||||
|
while read line; do
|
||||||
|
if is_line_type "state" "$line"; then
|
||||||
|
restore_state "$line"
|
||||||
|
fi
|
||||||
|
done < $(last_session_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
if supported_tmux_version_ok && check_saved_session_exists; then
|
||||||
|
start_spinner
|
||||||
restore_all_sessions
|
restore_all_sessions
|
||||||
|
restore_all_pane_processes
|
||||||
|
restore_pane_layout_for_each_window >/dev/null 2>&1
|
||||||
|
# below functions restore exact cursor positions
|
||||||
|
restore_active_pane_for_each_window
|
||||||
|
restore_active_and_alternate_windows
|
||||||
|
restore_active_and_alternate_sessions
|
||||||
|
stop_spinner
|
||||||
|
display_message "Restored all Tmux sessions!"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
main
|
main
|
||||||
|
@ -4,30 +4,103 @@ CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|||||||
|
|
||||||
source "$CURRENT_DIR/helpers.sh"
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
dump_format() {
|
pane_format() {
|
||||||
local delimiter=$'\t'
|
local delimiter=$'\t'
|
||||||
local format
|
local format
|
||||||
|
format+="pane"
|
||||||
|
format+="${delimiter}"
|
||||||
format+="#{session_name}"
|
format+="#{session_name}"
|
||||||
format+="${delimiter}"
|
format+="${delimiter}"
|
||||||
format+="#{window_index}"
|
format+="#{window_index}"
|
||||||
format+="${delimiter}"
|
format+="${delimiter}"
|
||||||
format+="#{window_name}"
|
format+=":#{window_name}"
|
||||||
|
format+="${delimiter}"
|
||||||
|
format+="#{window_active}"
|
||||||
|
format+="${delimiter}"
|
||||||
|
format+=":#{window_flags}"
|
||||||
|
format+="${delimiter}"
|
||||||
|
format+="#{pane_index}"
|
||||||
format+="${delimiter}"
|
format+="${delimiter}"
|
||||||
format+="#{pane_current_path}"
|
format+="#{pane_current_path}"
|
||||||
|
format+="${delimiter}"
|
||||||
|
format+="#{pane_active}"
|
||||||
|
format+="${delimiter}"
|
||||||
|
format+="#{pane_current_command}"
|
||||||
|
format+="${delimiter}"
|
||||||
|
format+="#{pane_pid}"
|
||||||
echo "$format"
|
echo "$format"
|
||||||
}
|
}
|
||||||
|
|
||||||
dump() {
|
window_format() {
|
||||||
tmux list-panes -a -F "$(dump_format)"
|
local delimiter=$'\t'
|
||||||
|
local format
|
||||||
|
format+="window"
|
||||||
|
format+="${delimiter}"
|
||||||
|
format+="#{session_name}"
|
||||||
|
format+="${delimiter}"
|
||||||
|
format+="#{window_index}"
|
||||||
|
format+="${delimiter}"
|
||||||
|
format+="#{window_active}"
|
||||||
|
format+="${delimiter}"
|
||||||
|
format+=":#{window_flags}"
|
||||||
|
format+="${delimiter}"
|
||||||
|
format+="#{window_layout}"
|
||||||
|
echo "$format"
|
||||||
|
}
|
||||||
|
|
||||||
|
state_format() {
|
||||||
|
local delimiter=$'\t'
|
||||||
|
local format
|
||||||
|
format+="state"
|
||||||
|
format+="${delimiter}"
|
||||||
|
format+="#{client_session}"
|
||||||
|
format+="${delimiter}"
|
||||||
|
format+="#{client_last_session}"
|
||||||
|
echo "$format"
|
||||||
|
}
|
||||||
|
|
||||||
|
dump_panes_raw() {
|
||||||
|
tmux list-panes -a -F "$(pane_format)"
|
||||||
|
}
|
||||||
|
|
||||||
|
pane_full_command() {
|
||||||
|
pane_pid="$1"
|
||||||
|
\pgrep -lf -P "$pane_pid" |
|
||||||
|
cut -d' ' -f2-
|
||||||
|
}
|
||||||
|
|
||||||
|
# translates pane pid to process command running inside a pane
|
||||||
|
dump_panes() {
|
||||||
|
local full_command
|
||||||
|
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
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
dump_windows() {
|
||||||
|
tmux list-windows -a -F "$(window_format)"
|
||||||
|
}
|
||||||
|
|
||||||
|
dump_state() {
|
||||||
|
tmux display-message -p "$(state_format)"
|
||||||
}
|
}
|
||||||
|
|
||||||
save_all_sessions() {
|
save_all_sessions() {
|
||||||
mkdir -p $HOME/.tmux
|
local session_path="$(session_path)"
|
||||||
dump > $HOME/.tmux/session
|
mkdir -p "$(sessions_dir)"
|
||||||
|
dump_panes > $session_path
|
||||||
|
dump_windows >> $session_path
|
||||||
|
dump_state >> $session_path
|
||||||
|
ln -fs "$session_path" "$(last_session_path)"
|
||||||
display_message "Saved all Tmux sessions!"
|
display_message "Saved all Tmux sessions!"
|
||||||
}
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
if supported_tmux_version_ok; then
|
||||||
save_all_sessions
|
save_all_sessions
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
main
|
main
|
||||||
|
8
scripts/spinner_helpers.sh
Normal file
8
scripts/spinner_helpers.sh
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
start_spinner() {
|
||||||
|
$CURRENT_DIR/tmux_spinner.sh "Restoring sessions..." "Restored all Tmux sessions!" &
|
||||||
|
export SPINNER_PID=$!
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_spinner() {
|
||||||
|
kill $SPINNER_PID
|
||||||
|
}
|
29
scripts/tmux_spinner.sh
Executable file
29
scripts/tmux_spinner.sh
Executable file
@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# This script shows tmux spinner with a message. It is intended to be running
|
||||||
|
# as a background process which should be `kill`ed at the end.
|
||||||
|
#
|
||||||
|
# Example usage:
|
||||||
|
#
|
||||||
|
# ./tmux_spinner.sh "Working..." "End message!" &
|
||||||
|
# SPINNER_PID=$!
|
||||||
|
# ..
|
||||||
|
# .. execute commands here
|
||||||
|
# ..
|
||||||
|
# kill $SPINNER_PID # Stops spinner and displays 'End message!'
|
||||||
|
|
||||||
|
MESSAGE="$1"
|
||||||
|
END_MESSAGE="$2"
|
||||||
|
SPIN='-\|/'
|
||||||
|
|
||||||
|
trap "tmux display-message $END_MESSAGE; exit" SIGINT SIGTERM
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local i=0
|
||||||
|
while true; do
|
||||||
|
i=$(( (i+1) %4 ))
|
||||||
|
tmux display-message " ${SPIN:$i:1} $MESSAGE"
|
||||||
|
sleep 0.1
|
||||||
|
done
|
||||||
|
}
|
||||||
|
main
|
23
strategies/vim_session.sh
Executable file
23
strategies/vim_session.sh
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# "vim session strategy"
|
||||||
|
#
|
||||||
|
# Restores a vim session from 'Session.vim' file, if it exists.
|
||||||
|
# If 'Session.vim' does not exist, it falls back to invoking the original
|
||||||
|
# command.
|
||||||
|
|
||||||
|
ORIGINAL_COMMAND="$1"
|
||||||
|
DIRECTORY="$2"
|
||||||
|
|
||||||
|
vim_session_file_exists() {
|
||||||
|
[ -e "${DIRECTORY}/Session.vim" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
if vim_session_file_exists; then
|
||||||
|
echo "vim -S"
|
||||||
|
else
|
||||||
|
echo "$ORIGINAL_COMMAND"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
main
|
Reference in New Issue
Block a user