all repos

tmux-stare @ d1345eaad95899cb9d5ccf883d7bda20e9b7047a

session manager, but my session manager
1 files changed, 75 insertions(+), 13 deletions(-)
capture running command correctly
Author: Oleksandr Smirnov olexsmir@gmail.com
Committed at: 2026-04-14 16:52:19 +0300
Authored at: 2026-02-10 16:01:22 +0200
Change ID: zxvwuwolyoyqzmlswwvvnzulyuwowykt
Parent: 02f8aba
M scripts/sessions.sh
ยทยทยท
        49
        49
         

      
        50
        50
         }

      
        51
        51
         

      
        
        52
        +get_pane_child_pids() {

      
        
        53
        +  local pane_pid="$1"

      
        
        54
        +  ps -ao ppid=,pid= | awk -v pane_pid="$pane_pid" '$1 == pane_pid { print $2 }'

      
        
        55
        +}

      
        
        56
        +

      
        
        57
        +format_process_command() {

      
        
        58
        +  local pid="$1"

      
        
        59
        +  [[ -r "/proc/${pid}/cmdline" ]] || return 1

      
        
        60
        +  xargs -0 bash -c 'printf "%q " "$0" "$@"' <"/proc/${pid}/cmdline" 2>/dev/null | sed 's/[[:space:]]*$//'

      
        
        61
        +}

      
        
        62
        +

      
        
        63
        +build_command_from_pids() {

      
        
        64
        +  local pids="$1"

      
        
        65
        +  local pid

      
        
        66
        +  local formatted

      
        
        67
        +  local command=""

      
        
        68
        +  for pid in $pids; do

      
        
        69
        +    formatted="$(format_process_command "$pid")"

      
        
        70
        +    [[ -z "$formatted" ]] && continue

      
        
        71
        +    [[ -n "$command" ]] && command+=" | "

      
        
        72
        +    command+="$formatted"

      
        
        73
        +  done

      
        
        74
        +  printf "%s" "$command"

      
        
        75
        +}

      
        
        76
        +

      
        
        77
        +collect_process_names() {

      
        
        78
        +  local pids="$1"

      
        
        79
        +  local pid

      
        
        80
        +  local first_arg

      
        
        81
        +  local name

      
        
        82
        +  for pid in $pids; do

      
        
        83
        +    [[ -r "/proc/${pid}/cmdline" ]] || continue

      
        
        84
        +    first_arg="$(tr '\0' '\n' <"/proc/${pid}/cmdline" 2>/dev/null | head -n1)"

      
        
        85
        +    [[ -z "$first_arg" ]] && continue

      
        
        86
        +    name="$(basename "$first_arg")"

      
        
        87
        +    [[ -n "$name" ]] && printf "%s\n" "$name"

      
        
        88
        +  done | sort -u

      
        
        89
        +}

      
        
        90
        +

      
        
        91
        +strip_prompt_prefix() {

      
        
        92
        +  local line="$1"

      
        
        93
        +  if [[ "$line" =~ [\$\#\%\>][[:space:]]+.+$ ]]; then

      
        
        94
        +    sed -E 's/^.*[#$%>][[:space:]]+//' <<<"$line"

      
        
        95
        +  fi

      
        
        96
        +}

      
        
        97
        +

      
        
        98
        +find_command_from_pane_history() {

      
        
        99
        +  local pane_target="$1"

      
        
        100
        +  local process_names="$2"

      
        
        101
        +  local line

      
        
        102
        +  local candidate

      
        
        103
        +  local name

      
        
        104
        +  while IFS= read -r line; do

      
        
        105
        +    [[ -z "$line" ]] && continue

      
        
        106
        +    candidate="$(strip_prompt_prefix "$line")"

      
        
        107
        +    [[ -z "$candidate" ]] && continue

      
        
        108
        +    while IFS= read -r name; do

      
        
        109
        +      [[ -z "$name" ]] && continue

      
        
        110
        +      if [[ "$candidate" == *"$name"* ]]; then

      
        
        111
        +        printf "%s" "$candidate"

      
        
        112
        +        return 0

      
        
        113
        +      fi

      
        
        114
        +    done <<<"$process_names"

      
        
        115
        +  done < <(tmux capture-pane -pJ -S -200 -t "$pane_target" 2>/dev/null | tac)

      
        
        116
        +}

      
        
        117
        +

      
        52
        118
         save_panes() {

      
        53
        119
           local session_name="$1"

      
        54
        120
           local save_file="$2"

      
        55
        121
           local format="pane$S#{pane_index}$S#{pane_current_path}$S#{pane_active}$S#{window_index}$S#{pane_pid}"

      
        56
        122
           tmux list-panes -s -t "$session_name" -F "$format" |

      
        57
        123
             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)

      
        
        124
        +      IFS="$S" read -r _ pane_index _ _ window_index pane_pid <<<"$line"

      
        
        125
        +      pids="$(get_pane_child_pids "$pane_pid")"

      
        
        126
        +      command="$(build_command_from_pids "$pids")"

      
        64
        127
         

      
        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
        
        -      )"

      
        
        128
        +      if [[ -n "$command" ]]; then

      
        
        129
        +        process_names="$(collect_process_names "$pids")"

      
        
        130
        +        pane_target="${session_name}:${window_index}.${pane_index}"

      
        
        131
        +        pane_command="$(find_command_from_pane_history "$pane_target" "$process_names")"

      
        
        132
        +        [[ -n "$pane_command" ]] && command="$pane_command"

      
        
        133
        +      fi

      
        72
        134
         

      
        73
        135
               awk -v command="$command" \

      
        74
        136
                 'BEGIN {FS=OFS="\t"} {$6=command; print}' \