#!/usr/bin/env bash OMERON_HAS_GUM=0 OMERON_HAS_WHIPTAIL=0 OMERON_TUI_MODE="basic" tui_detect() { OMERON_HAS_GUM=0 OMERON_HAS_WHIPTAIL=0 command -v gum >/dev/null 2>&1 && OMERON_HAS_GUM=1 command -v whiptail >/dev/null 2>&1 && OMERON_HAS_WHIPTAIL=1 if ((OMERON_HAS_GUM)); then OMERON_TUI_MODE="gum" elif ((OMERON_HAS_WHIPTAIL)); then OMERON_TUI_MODE="whiptail" else OMERON_TUI_MODE="basic" fi } tui_install_gum() { if ((OMERON_HAS_GUM)); then return 0 fi if ! have pacman; then return 1 fi printf '\033[1;36mInstalling gum for a better TUI experience...\033[0m\n' if sudo_run pacman -S --needed --noconfirm gum >/dev/null 2>&1; then command -v gum >/dev/null 2>&1 && OMERON_HAS_GUM=1 if ((OMERON_HAS_GUM)); then OMERON_TUI_MODE="gum" return 0 fi fi return 1 } _strip_format() { local text="$1" text="${text//#\{bold\}/}" text="${text//#\{normal\}/}" text="${text//#\{italic\}/}" text="${text//#\{green\}/}" text="${text//#\{yellow\}/}" text="${text//#\{red\}/}" text="${text//#\{blue\}/}" text="${text//#\{cyan\}/}" text="${text//#\{magenta\}/}" text="${text//#\{white\}/}" text="${text//#\{underline\}/}" printf '%s\n' "$text" } tui_choose() { local prompt="$1" shift if [[ "$OMERON_TUI_MODE" == "gum" ]]; then gum choose "$@" elif [[ "$OMERON_TUI_MODE" == "whiptail" ]]; then local i=0 local items=() for item in "$@"; do items+=("$i" "$item") ((i++)) done whiptail --menu "$prompt" 20 60 10 "${items[@]}" 3>&1 1>&2 2>&3 else printf '\n==============================\n' printf ' %s\n' "$(_strip_format "$prompt")" printf '==============================\n' local i=0 for item in "$@"; do printf ' [%d] %s\n' "$i" "$item" ((i++)) done printf ' [x] Cancel\n' printf '==============================\n' printf ' Choice: ' read -r choice if [[ "$choice" == "x" ]]; then return 1 fi if [[ "$choice" =~ ^[0-9]+$ ]] && ((choice < ${#@})); then printf '%s\n' "${!choice}" fi fi } tui_confirm() { local prompt="$1" prompt="$(_strip_format "$prompt")" if [[ "$OMERON_TUI_MODE" == "gum" ]]; then gum confirm "$prompt" elif [[ "$OMERON_TUI_MODE" == "whiptail" ]]; then whiptail --yesno "$prompt" 10 60 else printf '\n>>> %s [Y/n]: ' "$prompt" read -r response response="${response:-Y}" [[ "$response" =~ ^[yY](es)?$ ]] fi } tui_input() { local prompt="$1" prompt="$(_strip_format "$prompt")" if [[ "$OMERON_TUI_MODE" == "gum" ]]; then gum input --prompt "$prompt " elif [[ "$OMERON_TUI_MODE" == "whiptail" ]]; then whiptail --inputbox "$prompt" 10 60 3>&1 1>&2 2>&3 else printf '%s: ' "$prompt" read -r response printf '%s\n' "$response" fi } tui_password() { local prompt="$1" prompt="$(_strip_format "$prompt")" if [[ "$OMERON_TUI_MODE" == "gum" ]]; then gum input --password --prompt "$prompt " elif [[ "$OMERON_TUI_MODE" == "whiptail" ]]; then whiptail --passwordbox "$prompt" 10 60 3>&1 1>&2 2>&3 else printf '%s: ' "$prompt" read -rs response printf '\n' printf '%s\n' "$response" fi } tui_multiselect() { local prompt="$1" shift prompt="$(_strip_format "$prompt")" if [[ "$OMERON_TUI_MODE" == "gum" ]]; then gum choose --no-limit "$@" else printf '\n==============================\n' printf ' %s (space-separated indices)\n' "$prompt" printf '==============================\n' local i=0 local items=("$@") for item in "${items[@]}"; do printf ' [%d] %s\n' "$i" "$item" ((i++)) done printf ' [x] Done\n' printf '==============================\n' printf ' Select: ' read -ra selections local selection for selection in "${selections[@]}"; do if [[ "$selection" =~ ^[0-9]+$ ]] && ((selection < ${#items[@]})); then printf '%s\n' "${items[$selection]}" fi done fi } tui_spin() { local title="$1" shift title="$(_strip_format "$title")" printf ' ▶ %s ... ' "$title" "$@" local rc=$? if ((rc == 0)); then printf '\033[1;32mOK\033[0m\n' else printf '\033[1;31mFAILED\033[0m\n' fi return $rc } tui_header() { local title="$(_strip_format "$1")" if [[ "$OMERON_TUI_MODE" == "gum" ]]; then gum style --foreground 212 --border-foreground 212 --border double --align center --width 60 --margin "1 2" --padding "1 2" "$title" else local width=50 local line printf -v line '%*s' "$width" '' && line="${line// /#}" line="${line//#/=}" printf '\n' printf '\033[1;36m%s\033[0m\n' "$line" printf '\033[1;36m %s\033[0m\n' "$title" printf '\033[1;36m%s\033[0m\n' "$line" printf '\n' fi } tui_status() { local ok="$1" local message="$2" message="$(_strip_format "$message")" if [[ "$OMERON_TUI_MODE" == "gum" ]]; then if ((ok == 0)); then gum style --foreground 10 " ✓ $message" else gum style --foreground 9 " ✗ $message" fi else if ((ok == 0)); then printf ' \033[1;32m✓\033[0m %s\n' "$message" else printf ' \033[1;31m✗\033[0m %s\n' "$message" fi fi } tui_format() { if [[ "$OMERON_TUI_MODE" == "gum" ]]; then gum format "$@" else local line for line in "$@"; do _strip_format "$line" done fi } tui_info() { local message="$(_strip_format "$1")" printf ' \033[1;34m▶\033[0m %s\n' "$message" } tui_success() { local message="$(_strip_format "$1")" printf ' \033[1;32m✓\033[0m %s\n' "$message" } tui_warn() { local message="$(_strip_format "$1")" printf ' \033[1;33m⚠\033[0m %s\n' "$message" >&2 } tui_error() { local message="$(_strip_format "$1")" printf ' \033[1;31m✗\033[0m %s\n' "$message" >&2 } tui_bold() { if [[ "$OMERON_TUI_MODE" == "gum" ]]; then gum style --bold "$1" else printf '\033[1m%s\033[0m' "$1" fi } tui_separator() { if [[ "$OMERON_TUI_MODE" == "gum" ]]; then gum style --foreground 240 "────────────────────────────────────────" else printf ' \033[2m────────────────────────────────────────\033[0m\n' fi } tui_list() { local items=("$@") local item for item in "${items[@]}"; do printf ' \033[1;36m•\033[0m %s\n' "$(_strip_format "$item")" done }