5 files changed,
179 insertions(+),
160 deletions(-)
Author:
Oleksandr Smirnov
olexsmir@gmail.com
Committed at:
2026-02-09 02:08:42 +0200
Authored at:
2026-02-08 21:16:09 +0200
Change ID:
lmuukxpvwklurrsxpznlmxrzyykkyrrm
Parent:
0ef3399
jump to
| M | scripts/pick.sh |
| M | scripts/restore.sh |
| M | scripts/save.sh |
| A | scripts/sessions.sh |
| M | stare.tmux |
M
scripts/pick.sh
··· 1 1 #!/usr/bin/env bash 2 2 CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 3 3 source "$CURRENT_DIR/helpers.sh" 4 +source "$CURRENT_DIR/sessions.sh" 4 5 5 6 get_all_sessions() { 6 7 local current_session="$1" ··· 44 45 if tmux has-session -t "$session_name" 2>/dev/null; then 45 46 tmux switch-client -t "$session_name" 46 47 else 47 - exec "$CURRENT_DIR/restore.sh" "$session_name" 48 + restore_session "$session_name" 48 49 fi 49 50 } 50 51
M
scripts/restore.sh
··· 2 2 CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 3 3 source "$CURRENT_DIR/helpers.sh" 4 4 5 -# TODO: set the separator globally, or do whole sessions in one module 6 -declare S=$'\t' 7 - 8 -restore_session_from_file() { 9 - local session_file="$1" 10 - local session_name=$(basename "$session_file" | sed 's/_last$//') 11 - exec <"$session_file" 12 - 13 - start_spinner "Restoring session $session_name" 14 - 15 - local session_path="$(head -n1 | cut -d"$SEPARATOR" -f2)" 16 - tmux new-session -ds "$session_name" -c "$session_path" 17 - 18 - declare -A window_layouts 19 - declare active_window 20 - while read -r line; do 21 - case $line in 22 - window*) 23 - IFS=$S read -r _ window_index window_name window_layout window_active <<<"$line" 24 - window_id="$session_name:$window_index" 25 - tmux new-window -k -t "$window_id" -n "$window_name" 26 - window_layouts["$window_id"]="$window_layout" 27 - if [[ "$window_active" == "1" ]]; then 28 - active_window="$window_id" 29 - fi 30 - ;; 31 - 32 - pane*) 33 - IFS=$S read -r _ pane_index pane_current_path pane_active window_index command <<<"$line" 34 - if [[ "$pane_index" == "$(get_tmux_option base-index 0)" ]]; then 35 - tmux send-keys -t "$session_name:$window_index" "cd \"$pane_current_path\"" Enter "clear" Enter 36 - else 37 - tmux split-window -d -t "$session_name:$window_index" -c "$pane_current_path" 38 - fi 39 - if [[ "$pane_active" == "1" ]]; then 40 - tmux select-pane -t "$session_name:$window_index.$pane_index" 41 - fi 42 - if [[ -n "$command" ]]; then 43 - tmux send-keys -t "$session_name:$window_index.$pane_index" "$command" Enter 44 - fi 45 - ;; 46 - esac 47 - done 48 - 49 - for window in "${!window_layouts[@]}"; do 50 - tmux select-layout -t "$window" "${window_layouts[$window]}" 51 - done 52 - 53 - tmux select-window -t "$active_window" 54 - tmux switch-client -t "$session_name" 55 - stop_spinner "Session restored" 56 -} 57 - 58 -restore_session() { 59 - local name="$1" 60 - if tmux has-session -t "$name" 2>/dev/null; then 61 - tmux switch-client -t "$name" 62 - return 0 63 - fi 64 - 65 - local session_file="$(get_opt_dir)/${name}_last" 66 - if [[ ! -f "$session_file" ]]; then 67 - tmux display-message "No saved session found for: $name" 68 - return 1 69 - fi 70 - 71 - restore_session_from_file "$session_file" 72 -} 73 - 74 -restore_last() { 75 - local last_file="$(get_opt_dir)/last" 76 - if [[ ! -e "$last_file" ]]; then 77 - tmux display-message "No last session saved" 78 - return 1 79 - fi 80 - 81 - local session_name=$(basename "$(readlink "$last_file")" | sed 's/_last$//') 82 - restore_session "$session_name" 83 -} 84 - 85 -main() { 86 - if [[ -n "$1" ]]; then 87 - restore_session "$1" 88 - else 89 - restore_last 90 - fi 91 -} 92 -main "$@" 5 +# main() { 6 +# if [[ -n "$1" ]]; then 7 +# restore_session "$1" 8 +# else 9 +# restore_last 10 +# fi 11 +# } 12 +# main "$@"
M
scripts/save.sh
··· 2 2 CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 3 3 source "$CURRENT_DIR/helpers.sh" 4 4 5 -declare S=$'\t' 6 - 7 -save_cwd() { 8 - local save_file="$1" 9 - tmux -c pwd >>"$save_file" 10 -} 11 - 12 -save_windows() { 13 - local save_file="$1" 14 - local format="window$S#{window_index}$S#{window_name}$S#{window_layout}$S#{window_active}" 15 - tmux list-windows -F "$format" >>"$save_file" 16 -} 17 - 18 -save_panes() { 19 - local save_file="$1" 20 - local format="pane$S#{pane_index}$S#{pane_current_path}$S#{pane_active}$S#{window_index}$S#{pane_pid}" 21 - tmux list-panes -s -F "$format" | 22 - while IFS="$S" read -r line; do 23 - pids=$(ps -ao "ppid,pid" | 24 - sed "s/^ *//" | 25 - grep "^$(cut -f6 <<<"$line")" | 26 - rev | 27 - cut -d' ' -f1 | 28 - rev) 5 +# TODO: save all sessions 29 6 30 - command="$( 31 - for pid in $pids; do 32 - while read -r arg; do 33 - echo -n "'$arg' " 34 - done <<<"$(xargs -0L1 </proc/"$pid"/cmdline)" 35 - done 36 - )" 37 - 38 - awk -v command="$command" \ 39 - 'BEGIN {FS=OFS="\t"} {$6=command; print}' \ 40 - <<<"$line" >>"$save_file" 41 - done 42 -} 43 - 44 -link_session_last() { 45 - local save_file="$1" 46 - local last_file="$2" 47 - if ! cmp -s "$save_file" "$last_file"; then 48 - ln -sf "$save_file" "$last_file" 49 - else 50 - rm "$save_file" 51 - fi 52 -} 53 - 54 -link_last() { 55 - local save_file="$1" 56 - local save_dir="$2" 57 - ln -sf "$save_file" "$save_dir"/last 58 -} 59 - 60 -# TODO: add interval saves (tmux-continuum like) 61 -# TODO: save all loaded sessions not only current 62 -# TODO: link last session saved as last 63 -main() { 64 - start_spinner "Saving current session" 65 - local save_dir="$(get_opt_dir)" 66 - local save_file="${save_dir}/$(get_current_session_name)_$(get_time)" 67 - local last_file="${save_dir}/$(get_current_session_name)_last" 68 - save_cwd "$save_file" 69 - save_windows "$save_file" 70 - save_panes "$save_file" 71 - link_session_last "$save_file" "$last_file" 72 - link_last "$last_file" "$save_dir" 73 - stop_spinner "Session saved" 74 -} 75 -main 7 +# # TODO: save all loaded sessions not only current 8 +# main() { 9 +# local session_name="${1:-$(get_current_session_name)}" 10 +# start_spinner "Saving session: $session_name" 11 +# save_session "$session_name" 12 +# stop_spinner "Session saved" 13 +# } 14 +# main "$@"
A
scripts/sessions.sh
··· 1 +#!/usr/bin/env bash 2 +CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 3 +source "$CURRENT_DIR/helpers.sh" 4 + 5 +declare S=$'\t' 6 + 7 +# === common 8 + 9 +# === save 10 +save_cwd() { 11 + local session_name="$1" 12 + local save_file="$2" 13 + tmux display-message -p -t "$session_name" -F "#{session_path}" >>"$save_file" 14 +} 15 + 16 +save_windows() { 17 + local session_name="$1" 18 + local save_file="$2" 19 + local format="window$S#{window_index}$S#{window_name}$S#{window_layout}$S#{window_active}" 20 + tmux list-windows -t "$session_name" -F "$format" >>"$save_file" 21 + 22 +} 23 + 24 +save_panes() { 25 + local session_name="$1" 26 + local save_file="$2" 27 + local format="pane$S#{pane_index}$S#{pane_current_path}$S#{pane_active}$S#{window_index}$S#{pane_pid}" 28 + tmux list-panes -s -t "$session_name" -F "$format" | 29 + while IFS="$S" read -r line; do 30 + pids=$(ps -ao "ppid,pid" | 31 + sed "s/^ *//" | 32 + grep "^$(cut -f6 <<<"$line")" | 33 + rev | 34 + cut -d' ' -f1 | 35 + rev) 36 + 37 + command="$( 38 + for pid in $pids; do 39 + while read -r arg; do 40 + echo -n "'$arg' " 41 + done <<<"$(xargs -0L1 </proc/"$pid"/cmdline 2>/dev/null)" 42 + done 43 + )" 44 + 45 + awk -v command="$command" \ 46 + 'BEGIN {FS=OFS="\t"} {$6=command; print}' \ 47 + <<<"$line" >>"$save_file" 48 + done 49 +} 50 + 51 +link_session_last() { 52 + local save_file="$1" 53 + local last_file="$2" 54 + if ! cmp -s "$save_file" "$last_file"; then 55 + ln -sf "$save_file" "$last_file" 56 + else 57 + rm "$save_file" 58 + fi 59 +} 60 + 61 +link_last() { 62 + local save_file="$1" 63 + local save_dir="$2" 64 + ln -sf "$save_file" "$save_dir"/last 65 +} 66 + 67 +save_session() { 68 + local session_name="$1" 69 + local save_dir="$(get_opt_dir)" 70 + local save_file="${save_dir}/${session_name}_$(get_time)" 71 + local last_file="${save_dir}/${session_name}_last" 72 + 73 + save_cwd "$session_name" "$save_file" 74 + save_windows "$session_name" "$save_file" 75 + save_panes "$session_name" "$save_file" 76 + link_session_last "$save_file" "$last_file" 77 + link_last "$last_file" "$save_dir" 78 +} 79 + 80 +# === restore 81 +restore_session_from_file() { 82 + local session_file="$1" 83 + local session_name=$(basename "$session_file" | sed 's/_last$//') 84 + exec <"$session_file" 85 + 86 + start_spinner "Restoring session $session_name" 87 + 88 + local session_path="$(head -n1 | cut -d"$SEPARATOR" -f2)" 89 + tmux new-session -ds "$session_name" -c "$session_path" 90 + 91 + declare -A window_layouts 92 + declare active_window 93 + while read -r line; do 94 + case $line in 95 + window*) 96 + IFS=$S read -r _ window_index window_name window_layout window_active <<<"$line" 97 + window_id="$session_name:$window_index" 98 + tmux new-window -k -t "$window_id" -n "$window_name" 99 + window_layouts["$window_id"]="$window_layout" 100 + if [[ "$window_active" == "1" ]]; then 101 + active_window="$window_id" 102 + fi 103 + ;; 104 + 105 + pane*) 106 + IFS=$S read -r _ pane_index pane_current_path pane_active window_index command <<<"$line" 107 + if [[ "$pane_index" == "$(get_tmux_option base-index 0)" ]]; then 108 + tmux send-keys -t "$session_name:$window_index" "cd \"$pane_current_path\"" Enter "clear" Enter 109 + else 110 + tmux split-window -d -t "$session_name:$window_index" -c "$pane_current_path" 111 + fi 112 + if [[ "$pane_active" == "1" ]]; then 113 + tmux select-pane -t "$session_name:$window_index.$pane_index" 114 + fi 115 + if [[ -n "$command" ]]; then 116 + tmux send-keys -t "$session_name:$window_index.$pane_index" "$command" Enter 117 + fi 118 + ;; 119 + esac 120 + done 121 + 122 + for window in "${!window_layouts[@]}"; do 123 + tmux select-layout -t "$window" "${window_layouts[$window]}" 124 + done 125 + 126 + tmux select-window -t "$active_window" 127 + tmux switch-client -t "$session_name" 128 + stop_spinner "Session restored" 129 +} 130 + 131 +restore_session() { 132 + local session_name="$1" 133 + if tmux has-session -t "$session_name" 2>/dev/null; then 134 + tmux switch-client -t "$session_name" 135 + return 0 136 + fi 137 + 138 + local session_file="$(get_opt_dir)/${session_name}_last" 139 + if [[ ! -f "$session_file" ]]; then 140 + tmux display-message "No saved session found for: $session_name" 141 + return 1 142 + fi 143 + 144 + restore_session_from_file "$session_file" 145 +} 146 + 147 +restore_last() { 148 + local last_file="$(get_opt_dir)/last" 149 + if [[ ! -e "$last_file" ]]; then 150 + tmux display-message "No last session saved" 151 + return 1 152 + fi 153 + 154 + local session_name=$(basename "$(readlink "$last_file")" | sed 's/_last$//') 155 + restore_session "$session_name" 156 +}
M
stare.tmux
··· 4 4 CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 5 5 source "$CURRENT_DIR/scripts/helpers.sh" 6 6 7 +# TODO: add interval saves (tmux-continuum like) 8 + 7 9 main() { 8 10 local pick_key="$(get_opt_pick)" 9 - [[ -n "$pick_key" ]] && tmux bind-key "$pick_key" run-shell "tmux display-popup -E -w 25% -h 30% '$CURRENT_DIR/scripts/pick.sh'" 11 + [[ -n "$pick_key" ]] && tmux bind-key "$pick_key" run-shell \ 12 + "tmux display-popup -E -w 25% -h 40% '$CURRENT_DIR/scripts/pick.sh'" 10 13 11 14 local save_key="$(get_opt_save)" 12 15 [[ -n "$save_key" ]] && tmux bind-key "$save_key" run-shell "$CURRENT_DIR/scripts/save.sh"