all repos

tmux-stare @ d25769b

session manager, but my session manager
5 files changed, 179 insertions(+), 160 deletions(-)
sessions stuff in sessions.sh
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
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"