- Modular installer with gum-based TUI - Fresh-install detection with auto GPU driver selection - Preflight module for system detection (Intel/AMD/NVIDIA) - Core modules: packages, dotfiles, services, SDDM - Optional software installer (Obsidian, Neovim, VS Code, etc.) - Homelab config module with dynamic AGS integration - Two complete themes: Forest Neon and Rose Night - 19 Hyprland control scripts + 4 AGS widgets - Idempotent dotfile deployment with automatic backup - YAML-based configuration, extensible module system - Full logging to ~/.local/share/omeron/
162 lines
3.3 KiB
Bash
Executable File
162 lines
3.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
TUI_STYLE="${TUI_STYLE:-gum}"
|
|
|
|
tui_check() {
|
|
if [[ "$TUI_STYLE" == "gum" ]] && ! command -v gum >/dev/null 2>&1; then
|
|
printf "gum is not installed. Install it or set TUI_STYLE=basic\n" >&2
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
tui_style() {
|
|
if command -v gum >/dev/null 2>&1; then
|
|
TUI_STYLE="gum"
|
|
else
|
|
TUI_STYLE="basic"
|
|
fi
|
|
}
|
|
|
|
tui_choose() {
|
|
local prompt="$1"
|
|
shift
|
|
|
|
if [[ "$TUI_STYLE" == "gum" ]]; then
|
|
gum choose "$@"
|
|
else
|
|
select __choice in "$@"; do
|
|
printf '%s\n' "$__choice"
|
|
break
|
|
done
|
|
fi
|
|
}
|
|
|
|
tui_confirm() {
|
|
local prompt="$1"
|
|
|
|
if [[ "$TUI_STYLE" == "gum" ]]; then
|
|
gum confirm "$prompt"
|
|
else
|
|
printf '%s [y/N]: ' "$prompt" >&2
|
|
read -r response
|
|
[[ "$response" =~ ^[yY](es)?$ ]]
|
|
fi
|
|
}
|
|
|
|
tui_input() {
|
|
local prompt="$1"
|
|
|
|
if [[ "$TUI_STYLE" == "gum" ]]; then
|
|
gum input --prompt "$prompt "
|
|
else
|
|
printf '%s: ' "$prompt" >&2
|
|
read -r response
|
|
printf '%s\n' "$response"
|
|
fi
|
|
}
|
|
|
|
tui_password() {
|
|
local prompt="$1"
|
|
|
|
if [[ "$TUI_STYLE" == "gum" ]]; then
|
|
gum input --password --prompt "$prompt "
|
|
else
|
|
printf '%s: ' "$prompt" >&2
|
|
read -rs response
|
|
printf '\n'
|
|
printf '%s\n' "$response"
|
|
fi
|
|
}
|
|
|
|
tui_multiselect() {
|
|
local prompt="$1"
|
|
shift
|
|
|
|
if [[ "$TUI_STYLE" == "gum" ]]; then
|
|
gum choose --no-limit "$@"
|
|
else
|
|
printf '%s (space-separated indices):\n' "$prompt" >&2
|
|
local i=0
|
|
local items=("$@")
|
|
for item in "${items[@]}"; do
|
|
printf ' [%d] %s\n' "$i" "$item" >&2
|
|
((i++))
|
|
done
|
|
printf '> ' >&2
|
|
read -ra selections
|
|
for idx in "${selections[@]}"; do
|
|
printf '%s\n' "${items[$idx]}"
|
|
done
|
|
fi
|
|
}
|
|
|
|
tui_spin() {
|
|
local title="$1"
|
|
shift
|
|
|
|
if [[ "$TUI_STYLE" == "gum" ]]; then
|
|
gum spin --title "$title" -- "$@"
|
|
else
|
|
printf '%s... ' "$title" >&2
|
|
"$@"
|
|
printf 'done\n' >&2
|
|
fi
|
|
}
|
|
|
|
tui_header() {
|
|
local title="$1"
|
|
|
|
if [[ "$TUI_STYLE" == "gum" ]]; then
|
|
gum style --foreground 212 --border-foreground 212 --border double --align center --width 60 --margin "1 2" --padding "1 2" "$title"
|
|
else
|
|
printf '╔══════════════════════════════════════════════════╗\n'
|
|
printf '║ %s\n' "$title"
|
|
printf '╚══════════════════════════════════════════════════╝\n'
|
|
fi
|
|
}
|
|
|
|
tui_status() {
|
|
local ok="$1"
|
|
local message="$2"
|
|
|
|
if [[ "$TUI_STYLE" == "gum" ]]; then
|
|
if [[ "$ok" == "0" ]]; then
|
|
gum style --foreground 10 "✓ $message"
|
|
else
|
|
gum style --foreground 9 "✗ $message"
|
|
fi
|
|
else
|
|
if [[ "$ok" == "0" ]]; then
|
|
printf '✓ %s\n' "$message"
|
|
else
|
|
printf '✗ %s\n' "$message"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
tui_file_pick() {
|
|
local directory="$1"
|
|
local pattern="$2"
|
|
|
|
if [[ "$TUI_STYLE" == "gum" ]]; then
|
|
find "$directory" -maxdepth 1 -type f -name "$pattern" -printf '%f\n' | sort | gum choose
|
|
else
|
|
local files=()
|
|
while IFS= read -r -d '' f; do
|
|
files+=("$(basename "$f")")
|
|
done < <(find "$directory" -maxdepth 1 -type f -name "$pattern" -print0 | sort -z)
|
|
select __file in "${files[@]}"; do
|
|
printf '%s\n' "$__file"
|
|
break
|
|
done
|
|
fi
|
|
}
|
|
|
|
tui_format() {
|
|
if [[ "$TUI_STYLE" == "gum" ]]; then
|
|
gum format "$@"
|
|
else
|
|
printf '%s\n' "$*"
|
|
fi
|
|
}
|