omnixient/modules/dev-env/scripts/tmux-launch.sh
2026-06-28 09:59:05 +02:00

131 lines
4.2 KiB
Bash

#!/usr/bin/env bash
# dev-tm: launch a declared tmux session
#
# Reads /etc/dev-env/tmux-sessions.json (rendered by config.nix) and
# either attaches to an existing session or creates one with the
# declared windows. Window cwds are resolved relative to $DEV_ROOT.
#
# This is a single generic launcher; the window layouts come from Nix
# (or a runtime override at ~/.config/dev-env/tmux-sessions.json).
set -euo pipefail
if [[ -r /etc/dev-env/config.sh ]]; then
# shellcheck disable=SC1091
source /etc/dev-env/config.sh
fi
DEV_ROOT="${DEV_ROOT:-$HOME/dev}"
# Prefer a user override if present
SESSIONS_JSON=""
if [[ -r "$HOME/.config/dev-env/tmux-sessions.json" ]]; then
SESSIONS_JSON="$HOME/.config/dev-env/tmux-sessions.json"
elif [[ -r /etc/dev-env/tmux-sessions.json ]]; then
SESSIONS_JSON=/etc/dev-env/tmux-sessions.json
else
echo "No tmux-sessions.json found" >&2
exit 1
fi
usage() {
cat <<EOF
dev-tm — declarative tmux session launcher
USAGE:
dev-tm list available sessions
dev-tm <session> start or attach to <session>
dev-tm -k <session> kill session
dev-tm -k all kill all dev sessions
dev-tm -l list available sessions
EOF
}
list_sessions() {
echo "Defined sessions (from $SESSIONS_JSON):"
jq -r 'keys[]' "$SESSIONS_JSON" | sed 's/^/ /'
echo ""
echo "Active tmux sessions:"
tmux list-sessions 2>/dev/null | sed 's/^/ /' || echo " (none)"
}
resolve_path() {
local p="$1"
[[ -z "$p" || "$p" == "null" ]] && { echo "$DEV_ROOT"; return; }
[[ "$p" = /* ]] && { echo "$p"; return; }
echo "$DEV_ROOT/$p"
}
start_session() {
local name="$1"
local session_name="dev-$name"
if tmux has-session -t "$session_name" 2>/dev/null; then
tmux attach-session -t "$session_name"
return
fi
local session_cwd
session_cwd="$(resolve_path "$(jq -r --arg s "$name" '.[$s].cwd // empty' "$SESSIONS_JSON")")"
local nwindows
nwindows="$(jq --arg s "$name" '.[$s].windows | length' "$SESSIONS_JSON")"
if (( nwindows == 0 )); then
echo "Session '$name' has no windows defined" >&2
exit 1
fi
# First window
local first_name first_cwd first_cmd
first_name="$(jq -r --arg s "$name" '.[$s].windows[0].name' "$SESSIONS_JSON")"
first_cwd="$(resolve_path "$(jq -r --arg s "$name" '.[$s].windows[0].cwd // empty' "$SESSIONS_JSON")")"
first_cmd="$(jq -r --arg s "$name" '.[$s].windows[0].cmd // empty' "$SESSIONS_JSON")"
tmux new-session -d -s "$session_name" -n "$first_name" -c "$first_cwd"
[[ -n "$first_cmd" && "$first_cmd" != "null" ]] && \
tmux send-keys -t "$session_name:0" "$first_cmd" C-m
# Remaining windows
for ((i = 1; i < nwindows; i++)); do
local wn wcwd wcmd
wn="$(jq -r --arg s "$name" --argjson i "$i" '.[$s].windows[$i].name' "$SESSIONS_JSON")"
wcwd="$(resolve_path "$(jq -r --arg s "$name" --argjson i "$i" '.[$s].windows[$i].cwd // empty' "$SESSIONS_JSON")")"
wcmd="$(jq -r --arg s "$name" --argjson i "$i" '.[$s].windows[$i].cmd // empty' "$SESSIONS_JSON")"
tmux new-window -t "$session_name" -n "$wn" -c "$wcwd"
[[ -n "$wcmd" && "$wcmd" != "null" ]] && \
tmux send-keys -t "$session_name:$i" "$wcmd" C-m
done
tmux select-window -t "$session_name:0"
tmux attach-session -t "$session_name"
}
kill_session() {
local target="$1"
if [[ "$target" == "all" ]]; then
tmux list-sessions -F '#{session_name}' 2>/dev/null \
| grep '^dev-' \
| xargs -r -n1 tmux kill-session -t \
|| echo "No dev sessions to kill"
return
fi
tmux kill-session -t "dev-$target" 2>/dev/null || echo "Session 'dev-$target' not found"
}
# --- entry ---
case "${1:-}" in
-h|--help) usage ;;
-l|--list|"") list_sessions ;;
-k|--kill)
[[ -z "${2:-}" ]] && { echo "Usage: dev-tm -k <session|all>"; exit 1; }
kill_session "$2"
;;
*)
if ! jq -e --arg s "$1" 'has($s)' "$SESSIONS_JSON" >/dev/null; then
echo "Unknown session: $1" >&2
list_sessions
exit 1
fi
start_session "$1"
;;
esac