aboutsummaryrefslogtreecommitdiff
path: root/dotfiles/common
diff options
context:
space:
mode:
Diffstat (limited to 'dotfiles/common')
-rwxr-xr-xdotfiles/common/.local/bin/tmux-util107
1 files changed, 107 insertions, 0 deletions
diff --git a/dotfiles/common/.local/bin/tmux-util b/dotfiles/common/.local/bin/tmux-util
new file mode 100755
index 0000000..10c6fbb
--- /dev/null
+++ b/dotfiles/common/.local/bin/tmux-util
@@ -0,0 +1,107 @@
+#!/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
+}
+
+# -----------------------------------------------------------------------------
+# 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 "$@"
+ ;;
+ go|pick|ls|find|rename)
+ echo "tmux-util: subcommand '$sub' is not implemented yet" >&2
+ return 2
+ ;;
+ *)
+ echo "tmux-util: unknown subcommand: $sub" >&2
+ usage >&2
+ return 2
+ ;;
+ esac
+}
+
+main "$@"