Files
sysadmin-chronicles/tools/lib/ui.sh
T
44r0n7 0265afa054 chore: bootstrap lean sysadmin-chronicles repo
Import the runnable game code, content, docs, scripts, and repo guidance while leaving local agent state, dependency installs, build output, and backup copies out of the published tree.
2026-05-02 11:49:07 -04:00

125 lines
3.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# Shared UI helpers for Sysadmin Chronicles scripts.
# Source this file; do not execute directly.
_SC_STEP_N=0
# Colors — disabled if stdout is not a terminal or NO_COLOR is set
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then
_C_RESET='\033[0m'
_C_BOLD='\033[1m'
_C_GREEN='\033[0;32m'
_C_YELLOW='\033[0;33m'
_C_RED='\033[0;31m'
_C_CYAN='\033[0;36m'
_C_DIM='\033[2m'
else
_C_RESET='' _C_BOLD='' _C_GREEN='' _C_YELLOW='' _C_RED='' _C_CYAN='' _C_DIM=''
fi
sc_header() {
local title="${1:-Sysadmin Chronicles}"
echo ""
printf "${_C_CYAN}${_C_BOLD}"
echo "╔══════════════════════════════════════════╗"
printf "║ %-40s║\n" "$title"
echo "╚══════════════════════════════════════════╝"
printf "${_C_RESET}"
echo ""
}
sc_done_banner() {
echo ""
printf "${_C_GREEN}${_C_BOLD}"
echo "╔══════════════════════════════════════════╗"
printf "║ %-40s║\n" "SETUP COMPLETE!"
echo "╚══════════════════════════════════════════╝"
printf "${_C_RESET}"
echo ""
}
sc_section() {
echo ""
printf "${_C_BOLD}── %s ${_C_DIM}─────────────────────────────────${_C_RESET}\n" "$*"
}
sc_step() {
(( _SC_STEP_N++ )) || true
echo ""
printf "${_C_BOLD}── Step %d: %s${_C_RESET}\n" "$_SC_STEP_N" "$*"
}
sc_ok() { printf " ${_C_GREEN}${_C_RESET} %s\n" "$*"; }
sc_warn() { printf " ${_C_YELLOW}${_C_RESET} %s\n" "$*"; }
sc_err() { printf " ${_C_RED}${_C_RESET} %s\n" "$*" >&2; }
sc_fail() { sc_err "$*"; exit 1; }
sc_info() { printf " ${_C_DIM}${_C_RESET} %s\n" "$*"; }
# Prompt — writes question to /dev/tty, returns answer on stdout
sc_prompt() {
local question="$1"
local default="${2:-}"
if [ -n "$default" ]; then
printf " %s [%s] > " "$question" "$default" >/dev/tty
else
printf " %s > " "$question" >/dev/tty
fi
local answer
read -r answer </dev/tty
printf '%s' "${answer:-$default}"
}
# Confirm — returns 0 for yes, 1 for no
sc_confirm() {
local question="$1"
local default="${2:-Y}"
local prompt
if [ "${default^^}" = "Y" ]; then
prompt="[Y/n]"
else
prompt="[y/N]"
fi
printf " %s %s " "$question" "$prompt" >/dev/tty
local answer
read -r answer </dev/tty
answer="${answer:-$default}"
case "${answer,,}" in
y|yes) return 0 ;;
*) return 1 ;;
esac
}
sc_progress() {
local label="$1"
local current="$2"
local total="$3"
printf " %-38s %d/%d\n" "$label" "$current" "$total"
}
_SC_SPINNER_PID=""
sc_spinner() {
local label="${1:-Working...}"
printf " %s " "$label" >/dev/tty
(
local frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local i=0
while true; do
printf "\r %s %s " "$label" "${frames[$((i % ${#frames[@]}))]}" >/dev/tty
sleep 0.12
(( i++ )) || true
done
) &
_SC_SPINNER_PID=$!
disown "$_SC_SPINNER_PID" 2>/dev/null || true
}
sc_spinner_stop() {
if [ -n "${_SC_SPINNER_PID:-}" ]; then
kill "$_SC_SPINNER_PID" 2>/dev/null || true
wait "$_SC_SPINNER_PID" 2>/dev/null || true
_SC_SPINNER_PID=""
printf "\r%-60s\r" "" >/dev/tty
fi
}