all repos

tmux-stare @ 02f8aba

session manager, but my session manager

tmux-stare/scripts/sessions.sh (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
fix /last link, 3 months ago
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
get_current_session_name() {
9
  if [ "$(tmux display-message -p "#{session_grouped}")" = 0 ]; then
10
    tmux display-message -p "#{session_name}" 2>/dev/null || true
11
  else
12
    tmux display-message -p "#{session_group}" 2>/dev/null || true
13
  fi
14
}
15
16
rename_session() {
17
  local old="$1"
18
  local new="$2"
19
  local dir="$(get_opt_dir)"
20
21
  [[ -z "$new" || "$old" == "$new" ]] && return 1
22
  [[ -e "${dir}/${new}_last" ]] && return 1
23
24
  tmux has-session -t "$new" 2>/dev/null && return 1
25
  tmux rename-session -t "$old" "$new" 2>/dev/null
26
27
  local old_last="${dir}/${old}_last"
28
  [[ -L "$old_last" ]] && {
29
    local actual="$(readlink "$old_last")"
30
    local new_actual="${dir}/${new}_$(basename "$actual" | cut -d_ -f2-)"
31
    mv "$actual" "$new_actual"
32
    ln -sf "$new_actual" "${dir}/${new}_last"
33
    rm "$old_last"
34
  }
35
}
36
37
# === save
38
save_cwd() {
39
  local session_name="$1"
40
  local save_file="$2"
41
  tmux display-message -p -t "$session_name" -F "#{session_path}" >>"$save_file"
42
}
43
44
save_windows() {
45
  local session_name="$1"
46
  local save_file="$2"
47
  local format="window$S#{window_index}$S#{window_name}$S#{window_layout}$S#{window_active}"
48
  tmux list-windows -t "$session_name" -F "$format" >>"$save_file"
49
50
}
51
52
save_panes() {
53
  local session_name="$1"
54
  local save_file="$2"
55
  local format="pane$S#{pane_index}$S#{pane_current_path}$S#{pane_active}$S#{window_index}$S#{pane_pid}"
56
  tmux list-panes -s -t "$session_name" -F "$format" |
57
    while IFS="$S" read -r line; do
58
      pids=$(ps -ao "ppid,pid" |
59
        sed "s/^ *//" |
60
        grep "^$(cut -f6 <<<"$line")" |
61
        rev |
62
        cut -d' ' -f1 |
63
        rev)
64
65
      command="$(
66
        for pid in $pids; do
67
          while read -r arg; do
68
            echo -n "'$arg' "
69
          done <<<"$(xargs -0L1 </proc/"$pid"/cmdline 2>/dev/null)"
70
        done
71
      )"
72
73
      awk -v command="$command" \
74
        'BEGIN {FS=OFS="\t"} {$6=command; print}' \
75
        <<<"$line" >>"$save_file"
76
    done
77
}
78
79
link_session_last() {
80
  local save_file="$1"
81
  local last_file="$2"
82
  if ! cmp -s "$save_file" "$last_file"; then
83
    ln -sf "$save_file" "$last_file"
84
  else
85
    rm "$save_file"
86
  fi
87
}
88
89
link_last() {
90
  local save_file="$1"
91
  local save_dir="$2"
92
  ln -sf "$save_file" "$save_dir"/last
93
}
94
95
save_session() {
96
  local session_name="$1"
97
  local save_dir="$(get_opt_dir)"
98
  local save_file="${save_dir}/${session_name}_$(get_time)"
99
  local last_file="${save_dir}/${session_name}_last"
100
101
  save_cwd "$session_name" "$save_file"
102
  save_windows "$session_name" "$save_file"
103
  save_panes "$session_name" "$save_file"
104
  link_session_last "$save_file" "$last_file"
105
  link_last "$last_file" "$save_dir"
106
}
107
108
save_all_sessions() {
109
  tmux list-sessions -F "#{session_name}" | while read -r session; do
110
    save_session "$session"
111
  done
112
113
  local current_session="$(get_current_session_name)"
114
  if [[ -n "$current_session" ]]; then
115
    link_last "$(get_opt_dir)/${current_session}_last" "$(get_opt_dir)"
116
  fi
117
}
118
119
unload_session() {
120
  local session_name="$1"
121
  save_session "$session_name"
122
  tmux kill-session -t "$session_name"
123
}
124
125
# === restore
126
restore_session_from_file() {
127
  local session_file="$1"
128
  local session_name=$(basename "$session_file" | sed 's/_last$//')
129
  exec <"$session_file"
130
131
  start_spinner "Restoring session $session_name"
132
133
  local session_path="$(head -n1 | cut -d"$SEPARATOR" -f2)"
134
  tmux new-session -ds "$session_name" -c "$session_path"
135
136
  declare -A window_layouts
137
  declare active_window
138
  while read -r line; do
139
    case $line in
140
    window*)
141
      IFS=$S read -r _ window_index window_name window_layout window_active <<<"$line"
142
      window_id="$session_name:$window_index"
143
      tmux new-window -k -t "$window_id" -n "$window_name"
144
      window_layouts["$window_id"]="$window_layout"
145
      if [[ "$window_active" == "1" ]]; then
146
        active_window="$window_id"
147
      fi
148
      ;;
149
150
    pane*)
151
      IFS=$S read -r _ pane_index pane_current_path pane_active window_index command <<<"$line"
152
      if [[ "$pane_index" == "$(get_tmux_option base-index 0)" ]]; then
153
        tmux send-keys -t "$session_name:$window_index" "cd \"$pane_current_path\"" Enter "clear" Enter
154
      else
155
        tmux split-window -d -t "$session_name:$window_index" -c "$pane_current_path"
156
      fi
157
      if [[ "$pane_active" == "1" ]]; then
158
        tmux select-pane -t "$session_name:$window_index.$pane_index"
159
      fi
160
      if [[ -n "$command" ]]; then
161
        tmux send-keys -t "$session_name:$window_index.$pane_index" "$command" Enter
162
      fi
163
      ;;
164
    esac
165
  done
166
167
  for window in "${!window_layouts[@]}"; do
168
    tmux select-layout -t "$window" "${window_layouts[$window]}"
169
  done
170
171
  tmux select-window -t "$active_window"
172
  tmux switch-client -t "$session_name"
173
  stop_spinner "Session restored"
174
}
175
176
restore_session() {
177
  local session_name="$1"
178
  if tmux has-session -t "$session_name" 2>/dev/null; then
179
    tmux switch-client -t "$session_name"
180
    return 0
181
  fi
182
183
  local session_file="$(get_opt_dir)/${session_name}_last"
184
  if [[ ! -f "$session_file" ]]; then
185
    tmux display-message "No saved session found for: $session_name"
186
    return 1
187
  fi
188
189
  restore_session_from_file "$session_file"
190
}
191
192
restore_last() {
193
  local last_file="$(get_opt_dir)/last"
194
  if [[ ! -e "$last_file" ]]; then
195
    tmux display-message "No last session saved"
196
    return 1
197
  fi
198
199
  local session_name=$(basename "$(readlink "$last_file")" | sed 's/_last$//')
200
  restore_session "$session_name"
201
}