ContextStudioWizard/lib/utils.sh
Karamelmar 699087f08c Redesign wizard UI with gum (charmbracelet)
- Bootstrap gum automatically on first run (Arch/Debian/RHEL/Fedora/SUSE)
- utils.sh: replace all bash color helpers with gum equivalents
  - gum input for text prompts (with value pre-fill for defaults)
  - gum choose for selection menus
  - gum confirm for yes/no
  - gum spin for long-running operations
  - gum style/log for output (catppuccin mocha palette)
  - gum style for banners and summary box
- core.sh: spinner on git clone/pull
- workflow.sh: spinner on git clone
- prereqs.sh: spinner on package installs
- wizard.sh: double-border welcome banner, rounded summary box,
  success banner with next-steps panel

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 13:02:42 +01:00

125 lines
3.8 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# utils.sh — gum-based UI helpers (requires gum)
# ── Catppuccin Mocha palette ─────────────────────────────────────────────
C_MAUVE="#CBA6F7"
C_SKY="#89DCEB"
C_GREEN="#A6E3A1"
C_YELLOW="#F9E2AF"
C_RED="#F38BA8"
C_PINK="#F5C2E7"
C_BASE="#1E1E2E"
C_TEXT="#CDD6F4"
C_SURFACE="#585B70"
# ── Output helpers ────────────────────────────────────────────────────────
info() { gum log --level info -- "$*"; }
success() { gum style --foreground "$C_GREEN" "$*"; }
warn() { gum log --level warn -- "$*"; }
error() { gum log --level error -- "$*" >&2; }
die() { gum style --foreground "$C_RED" --bold "$*" >&2; exit 1; }
header() {
echo ""
gum style \
--foreground "$C_MAUVE" --bold \
--margin "0 2" \
"$*"
gum style \
--foreground "$C_SURFACE" \
--margin "0 2" \
"────────────────────────────────────────────────"
echo ""
}
# ── Prompts ───────────────────────────────────────────────────────────────
# ask VAR "Label" "default"
ask() {
local var="$1" prompt="$2" default="${3:-}"
local result
if [[ -n "$default" ]]; then
result=$(gum input \
--value "$default" \
--prompt " " \
--prompt.foreground "$C_MAUVE" \
--cursor.foreground "$C_MAUVE" \
--header " $prompt" \
--header.foreground "$C_SKY" \
--width 70) || true
else
result=$(gum input \
--placeholder "(required)" \
--prompt " " \
--prompt.foreground "$C_MAUVE" \
--cursor.foreground "$C_MAUVE" \
--header " $prompt" \
--header.foreground "$C_SKY" \
--width 70) || true
fi
if [[ -z "$result" && -n "$default" ]]; then
eval "$var=\"\$default\""
else
eval "$var=\"\$result\""
fi
}
# ask_yn VAR "Question" "y|n"
ask_yn() {
local var="$1" prompt="$2" default="$3"
local affirmative="Yes" negative="No"
[[ "$default" == "y" ]] && affirmative="Yes" || affirmative="Yes"
if gum confirm \
--affirmative "Yes" \
--negative "No" \
--default="$([[ "$default" == "y" ]] && echo Yes || echo No)" \
--prompt.foreground "$C_SKY" \
--selected.background "$C_MAUVE" \
--selected.foreground "$C_BASE" \
--unselected.foreground "$C_TEXT" \
" $prompt"; then
eval "$var=y"
else
eval "$var=n"
fi
}
# ask_choice VAR "Header" option1 option2 ...
ask_choice() {
local var="$1" prompt="$2"; shift 2
local first="$1"
local result
result=$(gum choose \
--cursor " " \
--cursor.foreground "$C_MAUVE" \
--selected.foreground "$C_MAUVE" \
--selected.bold \
--header " $prompt" \
--header.foreground "$C_SKY" \
--height 10 \
"$@") || true
if [[ -z "$result" ]]; then
eval "$var=\"\$first\""
else
eval "$var=\"\$result\""
fi
}
# spin "Title" command args...
spin() {
local title="$1"; shift
gum spin \
--spinner dot \
--spinner.foreground "$C_MAUVE" \
--title " $title" \
--title.foreground "$C_SKY" \
-- "$@"
}
require_cmd() {
command -v "$1" &>/dev/null || die "Required command not found: $1"
}
slugify() {
echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-//;s/-$//'
}