#!/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/-$//' }