diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-02 12:16:38 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-02 12:16:38 -0500 |
| commit | 8c32bbbf9fab115dc51afa17c081e0763cbee717 (patch) | |
| tree | 246b46b53c956cfea07bc9d1c2b81f9f8de53d65 /dotfiles/common/.local/bin/tmux-util | |
| parent | 3f370d6c19c83430547d1771b0e6fa669dc7d5c5 (diff) | |
| download | archsetup-8c32bbbf9fab115dc51afa17c081e0763cbee717.tar.gz archsetup-8c32bbbf9fab115dc51afa17c081e0763cbee717.zip | |
refactor: drop in-repo dotfiles/, move stow tooling to the dotfiles repo
Since the installer clones DOTFILES_REPO into ~/.dotfiles and stows from there, the in-repo dotfiles/ tree was dead weight. Nothing reads it at install time. I removed it (831 files) now that both machines are migrated.
The Makefile's stow / restow / reset / unstow / import targets and the dotfile-script unit suites moved to the dotfiles repo. They sit alongside the scripts they manage and run standalone (cd ~/.dotfiles && make ...). This Makefile keeps the VM-integration targets and the installer-helper suite (safe-rm-rf).
I updated CLAUDE.md and README.md so stow operations run from ~/.dotfiles, and the dotfile-management, theme, and unit-test sections point at the standalone repo. The README was already describing the old in-repo model from before the installer switched to cloning. This brings it in line.
Diffstat (limited to 'dotfiles/common/.local/bin/tmux-util')
| -rwxr-xr-x | dotfiles/common/.local/bin/tmux-util | 302 |
1 files changed, 0 insertions, 302 deletions
diff --git a/dotfiles/common/.local/bin/tmux-util b/dotfiles/common/.local/bin/tmux-util deleted file mode 100755 index dca01fd..0000000 --- a/dotfiles/common/.local/bin/tmux-util +++ /dev/null @@ -1,302 +0,0 @@ -#!/bin/bash -# tmux-util — small utilities for managing tmux sessions. -# -# Subcommands: -# go <name> attach to <name> if it exists, otherwise create it -# pick fzf-driven session switcher -# ls opinionated session listing (attached, idle, windows, cwd) -# find <pattern> locate panes whose foreground process matches <pattern> -# reap gracefully exit every unattached session (skipping aiv-*) -# rename fzf-pick a session, prompt for a new name, rename it -# -# Run with no arguments to print this help. - -set -uo pipefail - -# ----------------------------------------------------------------------------- -# Usage -# ----------------------------------------------------------------------------- - -usage() { - cat <<'EOF' -Usage: tmux-util <subcommand> [args] - -Subcommands: - go <name> Attach to session <name>; create it (in $PWD) if missing. - pick Fzf-driven session switcher. - ls List sessions with attached / idle / window / cwd columns. - find <pattern> Locate panes whose foreground process matches <pattern>. - reap Send SIGHUP to every unattached session's panes and close - the session. Sessions matching $TMUX_UTIL_REAP_SKIP - (default: ^aiv-) are skipped. - rename Pick a session via fzf, prompt for a new name, rename it. - -Run with no arguments to print this help. -EOF -} - -# ----------------------------------------------------------------------------- -# rename -# ----------------------------------------------------------------------------- - -cmd_rename() { - local sessions - sessions=$(tmux list-sessions \ - -F '#{session_attached} #{session_name}' 2>/dev/null || true) - if [ -z "$sessions" ]; then - echo "No tmux sessions to rename." - return 0 - fi - - local choice - choice=$(echo "$sessions" | awk '{ - state = ($1 == "1") ? "attached" : "detached" - printf "%-9s %s\n", state, $2 - }' | fzf --header="Pick a session to rename" | awk '{print $2}') - - if [ -z "$choice" ]; then - # User cancelled. - return 0 - fi - - local new_name - printf 'New name for "%s": ' "$choice" - read -r new_name - - if [ -z "$new_name" ]; then - echo "tmux-util rename: empty new name, cancelled." >&2 - return 1 - fi - - if [ "$new_name" = "$choice" ]; then - echo "tmux-util rename: new name same as old, no change." - return 0 - fi - - if tmux has-session -t "=$new_name" 2>/dev/null; then - echo "tmux-util rename: a session named '$new_name' already exists." >&2 - return 1 - fi - - tmux rename-session -t "$choice" "$new_name" - echo "Renamed: $choice -> $new_name" -} - -# ----------------------------------------------------------------------------- -# pick -# ----------------------------------------------------------------------------- - -cmd_pick() { - local sessions - sessions=$(tmux list-sessions \ - -F '#{session_attached} #{session_name}' 2>/dev/null || true) - if [ -z "$sessions" ]; then - echo "No tmux sessions to pick from." - return 0 - fi - - # Format for fzf: "<state> <name>" — name is the second field of the - # selection line, which we recover after fzf returns. - local choice - choice=$(echo "$sessions" | awk '{ - state = ($1 == "1") ? "attached" : "detached" - printf "%-9s %s\n", state, $2 - }' | fzf --header="Pick a tmux session" | awk '{print $2}') - - if [ -z "$choice" ]; then - # User cancelled (Ctrl-C or Esc); fzf exits 130, the pipeline - # returns empty. - return 0 - fi - - if [ -n "${TMUX:-}" ]; then - tmux switch-client -t "$choice" - else - tmux attach-session -t "$choice" - fi -} - -# ----------------------------------------------------------------------------- -# find -# ----------------------------------------------------------------------------- - -cmd_find() { - local pattern="${1:-}" - if [ -z "$pattern" ]; then - echo "tmux-util find: missing pattern" >&2 - echo "Usage: tmux-util find <pattern>" >&2 - return 2 - fi - - local matches - matches=$(tmux list-panes -a \ - -F '#{session_name}:#{window_index}.#{pane_index} #{pane_current_command}' \ - 2>/dev/null | grep -E "$pattern" || true) - - if [ -z "$matches" ]; then - return 1 - fi - echo "$matches" -} - -# ----------------------------------------------------------------------------- -# go -# ----------------------------------------------------------------------------- - -cmd_go() { - local name="${1:-}" - if [ -z "$name" ]; then - echo "tmux-util go: missing session name" >&2 - echo "Usage: tmux-util go <name>" >&2 - return 2 - fi - - # `=name` forces exact match in `tmux has-session` (otherwise tmux does - # prefix matching, which would let `go foo` attach to a session named - # `foobar`). - if tmux has-session -t "=$name" 2>/dev/null; then - if [ -n "${TMUX:-}" ]; then - tmux switch-client -t "$name" - else - tmux attach-session -t "$name" - fi - else - if [ -n "${TMUX:-}" ]; then - tmux new-session -d -s "$name" -c "$PWD" - tmux switch-client -t "$name" - else - tmux new-session -s "$name" -c "$PWD" - fi - fi -} - -# ----------------------------------------------------------------------------- -# ls -# ----------------------------------------------------------------------------- - -# Render seconds as a short human duration (e.g. "5s", "12m", "3h", "2d"). -format_idle() { - local s="$1" - if [ "$s" -lt 60 ]; then - echo "${s}s" - elif [ "$s" -lt 3600 ]; then - echo "$((s / 60))m" - elif [ "$s" -lt 86400 ]; then - echo "$((s / 3600))h" - else - echo "$((s / 86400))d" - fi -} - -cmd_ls() { - local sessions - sessions=$(tmux list-sessions \ - -F '#{session_attached} #{session_name} #{session_activity} #{session_windows}' \ - 2>/dev/null || true) - - if [ -z "$sessions" ]; then - echo "No tmux sessions." - return 0 - fi - - local now="${TMUX_UTIL_NOW:-$(date +%s)}" - - { - printf 'STATE\tNAME\tIDLE\tWINDOWS\tCWD\n' - local attached name activity windows state idle_str cwd - while IFS=' ' read -r attached name activity windows; do - [ -n "$name" ] || continue - state="detached" - [ "$attached" -gt 0 ] && state="attached" - idle_str=$(format_idle "$((now - activity))") - cwd=$(tmux display -p -t "$name" '#{pane_current_path}' 2>/dev/null || echo "?") - # Replace leading $HOME with ~ for display. - if [ -n "${HOME:-}" ] && [ "${cwd#$HOME}" != "$cwd" ]; then - cwd="~${cwd#$HOME}" - fi - printf '%s\t%s\t%s\t%s\t%s\n' "$state" "$name" "$idle_str" "$windows" "$cwd" - done <<<"$sessions" - } | column -t -s $'\t' -} - -# ----------------------------------------------------------------------------- -# Reap -# ----------------------------------------------------------------------------- - -cmd_reap() { - local skip="${TMUX_UTIL_REAP_SKIP:-^aiv-}" - local sessions - sessions=$(tmux list-sessions -F '#{session_name} #{session_attached}' 2>/dev/null \ - | awk '$2 == 0 {print $1}' \ - | grep -vE "$skip" || true) - - if [ -z "$sessions" ]; then - echo "No unattached sessions to reap." - return 0 - fi - - local s pids - while IFS= read -r s; do - [ -n "$s" ] || continue - echo "Reaping: $s" - pids=$(tmux list-panes -s -t "$s" -F '#{pane_pid}' 2>/dev/null) - if [ -n "$pids" ]; then - echo "$pids" | xargs -r kill -HUP - fi - # Give the session a moment to wind down naturally. - local i - for i in 1 2 3; do - tmux has-session -t "$s" 2>/dev/null || break - sleep 1 - done - if tmux has-session -t "$s" 2>/dev/null; then - echo " still alive, force killing" - tmux kill-session -t "$s" - fi - done <<<"$sessions" -} - -# ----------------------------------------------------------------------------- -# Dispatch -# ----------------------------------------------------------------------------- - -main() { - if [ "$#" -eq 0 ]; then - usage - return 0 - fi - - local sub="$1" - shift - - case "$sub" in - -h|--help|help) - usage - ;; - reap) - cmd_reap "$@" - ;; - ls) - cmd_ls "$@" - ;; - go) - cmd_go "$@" - ;; - find) - cmd_find "$@" - ;; - pick) - cmd_pick "$@" - ;; - rename) - cmd_rename "$@" - ;; - *) - echo "tmux-util: unknown subcommand: $sub" >&2 - usage >&2 - return 2 - ;; - esac -} - -main "$@" |
