aboutsummaryrefslogtreecommitdiff
path: root/tests/tmux-util/fake-tmux
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-19 12:24:40 -0500
committerCraig Jennings <c@cjennings.net>2026-05-19 12:24:40 -0500
commit5d8d9df7d1b95c1a6a7bf25ddf57652c86f110b3 (patch)
tree6c4a5c1fe10db7ea2413dc514fb3e64ed45df71c /tests/tmux-util/fake-tmux
parent7e5651e3b074366ab35321b550ac06f1823b0b3d (diff)
downloadarchsetup-5d8d9df7d1b95c1a6a7bf25ddf57652c86f110b3.tar.gz
archsetup-5d8d9df7d1b95c1a6a7bf25ddf57652c86f110b3.zip
feat(tmux-util): add script skeleton and reap subcommand
A new utility in dotfiles/common/.local/bin/ for managing tmux sessions. The eventual plan covers six subcommands (go, pick, ls, find, reap, rename). This commit ships the skeleton, the dispatch + help, and the first subcommand: reap. reap walks every unattached tmux session whose name doesn't match $TMUX_UTIL_REAP_SKIP (default `^aiv-`), sends SIGHUP to each pane's PID (the same signal that fires when you close a terminal window), waits up to three seconds for the session to wind down, and falls back to `tmux kill-session` if anything's still alive. Tests live under tests/tmux-util/ with the same fake-binary-on-PATH pattern layout-navigate uses. fake-tmux reads canned session state from a file and records every invocation. fake-kill records signal calls without sending them. fake-sleep is a no-op so tests don't actually wait. 14 tests cover Normal / Boundary cases for dispatch + reap. Run them with: cd tests && python3 -m unittest tmux-util.test_tmux_util The other five subcommands stub out for now and exit non-zero with "not implemented yet" so future TDD turns can drop them in one at a time.
Diffstat (limited to 'tests/tmux-util/fake-tmux')
-rwxr-xr-xtests/tmux-util/fake-tmux95
1 files changed, 95 insertions, 0 deletions
diff --git a/tests/tmux-util/fake-tmux b/tests/tmux-util/fake-tmux
new file mode 100755
index 0000000..f6217bb
--- /dev/null
+++ b/tests/tmux-util/fake-tmux
@@ -0,0 +1,95 @@
+#!/bin/sh
+# Fake tmux for testing tmux-util.
+#
+# State file: $FAKE_TMUX_DIR/sessions.txt
+# One line per session, space-separated: <name> <attached> <pids_csv> [last_activity_epoch]
+# pids_csv is a comma-separated list of pane PIDs (or '-' for none)
+#
+# Log file: $FAKE_TMUX_DIR/calls.log
+# Each invocation appended as a single line: tmux <args>
+
+: "${FAKE_TMUX_DIR:?FAKE_TMUX_DIR must be set}"
+
+STATE="$FAKE_TMUX_DIR/sessions.txt"
+LOG="$FAKE_TMUX_DIR/calls.log"
+
+# Log every invocation
+printf 'tmux %s\n' "$*" >> "$LOG"
+
+cmd="$1"
+shift
+
+# Helper: read state file, ignoring blank lines
+read_state() {
+ [ -f "$STATE" ] || return 0
+ grep -v '^[[:space:]]*$' "$STATE" || true
+}
+
+case "$cmd" in
+ list-sessions)
+ # Format string is ignored; we always emit "<name> <attached>" because
+ # that's the only format tmux-util uses against list-sessions.
+ read_state | while IFS=' ' read -r name attached pids _rest; do
+ [ -n "$name" ] || continue
+ echo "$name $attached"
+ done
+ ;;
+ list-panes)
+ session=""
+ while [ "$#" -gt 0 ]; do
+ case "$1" in
+ -t) shift; session="$1"; shift ;;
+ -F) shift; [ "$#" -gt 0 ] && shift ;;
+ -s) shift ;;
+ *) shift ;;
+ esac
+ done
+ read_state | while IFS=' ' read -r name attached pids _rest; do
+ if [ "$name" = "$session" ]; then
+ [ "$pids" = "-" ] || echo "$pids" | tr ',' '\n'
+ exit 0
+ fi
+ done
+ ;;
+ has-session)
+ session=""
+ while [ "$#" -gt 0 ]; do
+ case "$1" in
+ -t) shift; session="$1"; shift ;;
+ *) shift ;;
+ esac
+ done
+ while IFS=' ' read -r name attached pids _rest; do
+ if [ "$name" = "$session" ]; then
+ exit 0
+ fi
+ done < "$STATE"
+ exit 1
+ ;;
+ kill-session)
+ session=""
+ while [ "$#" -gt 0 ]; do
+ case "$1" in
+ -t) shift; session="$1"; shift ;;
+ *) shift ;;
+ esac
+ done
+ tmp="$STATE.tmp"
+ : > "$tmp"
+ while IFS=' ' read -r name attached pids rest; do
+ [ -n "$name" ] || continue
+ if [ "$name" != "$session" ]; then
+ if [ -n "$rest" ]; then
+ printf '%s %s %s %s\n' "$name" "$attached" "$pids" "$rest" >> "$tmp"
+ else
+ printf '%s %s %s\n' "$name" "$attached" "$pids" >> "$tmp"
+ fi
+ fi
+ done < "$STATE"
+ mv "$tmp" "$STATE"
+ ;;
+ *)
+ echo "fake-tmux: unknown command '$cmd'" >&2
+ exit 1
+ ;;
+esac