0265afa054
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.
125 lines
3.6 KiB
Bash
Executable File
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
|
|
}
|