aboutsummaryrefslogtreecommitdiff
path: root/dotfiles/common/.local/bin/tmux-util
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-02 12:16:38 -0500
committerCraig Jennings <c@cjennings.net>2026-06-02 12:16:38 -0500
commit8c32bbbf9fab115dc51afa17c081e0763cbee717 (patch)
tree246b46b53c956cfea07bc9d1c2b81f9f8de53d65 /dotfiles/common/.local/bin/tmux-util
parent3f370d6c19c83430547d1771b0e6fa669dc7d5c5 (diff)
downloadarchsetup-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-xdotfiles/common/.local/bin/tmux-util302
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 "$@"