fix: TUI mit drei Backends (gum/whiptail/basic) + gum auto-install auf frischen Systemen

- tui.sh: komplett überarbeitet mit _strip_format() für basic mode
- whiptail als mittleres Fallback-Backend hinzugefügt
- Alle #{bold}/#{normal}-Markups entfernt, saubere ANSI-API (tui_info/tui_bold/...)
- install.sh: detect_environment() installiert gum vor allen Prompts
- Kein seq-Dependency mehr (printf -v statt seq)
- packages.sh/preflight.sh/homelab.sh/optional.sh auf neue TUI-API migriert
This commit is contained in:
2026-05-27 21:00:49 +02:00
parent be7bffc1e5
commit edbf5471b5
7 changed files with 333 additions and 223 deletions

View File

@@ -65,11 +65,9 @@ EOF
list_modules() {
echo "Available modules:"
echo ""
for module in $(module_list); do
local rel_path="${module#$OMERON_MODULE_DIR/}"
rel_path="${rel_path%.sh}"
local description=""
if source "$module" 2>/dev/null && declare -F "module_description" >/dev/null 2>&1; then
description="$(module_description)"
@@ -82,47 +80,59 @@ list_modules() {
parse_args() {
while [[ $# -gt 0 ]]; do
case "$1" in
--fresh)
OMERON_FRESH_INSTALL=1
shift
;;
--modules)
IFS=',' read -ra RUN_MODULES <<< "$2"
shift 2
;;
--skip)
IFS=',' read -ra SKIP_MODULES <<< "$2"
shift 2
;;
--skip-packages)
SKIP_MODULES+=("core/packages")
shift
;;
--with-sddm)
WITH_SDDM=1
shift
;;
--list-modules)
list_modules
;;
-h|--help)
usage
;;
*)
echo "Unknown option: $1" >&2
usage
;;
--fresh) OMERON_FRESH_INSTALL=1; shift ;;
--modules) IFS=',' read -ra RUN_MODULES <<< "$2"; shift 2 ;;
--skip) IFS=',' read -ra SKIP_MODULES <<< "$2"; shift 2 ;;
--skip-packages) SKIP_MODULES+=("core/packages"); shift ;;
--with-sddm) WITH_SDDM=1; shift ;;
--list-modules) list_modules ;;
-h|--help) usage ;;
*) echo "Unknown option: $1" >&2; usage ;;
esac
done
}
detect_environment() {
tui_detect
if ((!OMERON_HAS_GUM)) && have pacman; then
printf '\033[1;36m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m\n'
printf '\033[1;36m Ꮎ Ꮎ Ꮑ — Modular System Setup Framework\033[0m\n'
printf '\033[1;36m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m\n'
printf '\n'
printf ' \033[1;33mgum is not installed.\033[0m Installing it enables the full TUI experience.\n'
printf '\n'
if tui_install_gum; then
printf ' \033[1;32m✓ gum installed!\033[0m\n'
else
if ((OMERON_HAS_WHIPTAIL)); then
printf ' \033[1;33musing whiptail as fallback\033[0m\n'
else
printf ' \033[1;33musing basic text mode (install gum for UI: pacman -S gum)\033[0m\n'
fi
fi
printf '\n'
fi
if ((!OMERON_FRESH_INSTALL)) && ((${#RUN_MODULES[@]} == 0)); then
log_info "Checking for fresh install..."
if is_fresh_install; then
OMERON_FRESH_INSTALL=1
export OMERON_FRESH_INSTALL
fi
fi
if ((OMERON_FRESH_INSTALL)) && ((!OMERON_HAS_GUM)) && have pacman; then
tui_install_gum 2>/dev/null || true
fi
}
collect_modules() {
if ((${#RUN_MODULES[@]})); then
local result=()
for mod in "${RUN_MODULES[@]}"; do
result+=("$OMERON_MODULE_DIR/$mod.sh")
printf '%s\n' "$OMERON_MODULE_DIR/$mod.sh"
done
printf '%s\n' "${result[@]}"
return
fi
@@ -133,8 +143,6 @@ collect_modules() {
modules=("${DEFAULT_MODULES[@]}")
fi
local module_order=()
for mod in "${modules[@]}"; do
local skip=0
for skipped in "${SKIP_MODULES[@]}"; do
@@ -143,16 +151,11 @@ collect_modules() {
break
fi
done
[[ "$mod" == "core/sddm" && "$WITH_SDDM" -eq 0 && "$OMERON_FRESH_INSTALL" -eq 0 ]] && skip=1
((skip)) && continue
local module_file="$OMERON_MODULE_DIR/$mod.sh"
[[ -f "$module_file" ]] && module_order+=("$module_file")
[[ -f "$module_file" ]] && printf '%s\n' "$module_file"
done
printf '%s\n' "${module_order[@]}"
}
collect_all_interactive() {
@@ -182,7 +185,7 @@ collect_all_interactive() {
if declare -F "module_required" >/dev/null 2>&1; then
source "$module_file"
if module_required; then
log_info "Required module - will run"
tui_info "Required module will run"
module_order+=("$module_file")
((idx++))
continue
@@ -194,7 +197,6 @@ collect_all_interactive() {
else
log_info "Skipped"
fi
((idx++))
done
@@ -203,44 +205,41 @@ collect_all_interactive() {
show_banner() {
tui_header " Ꮎ Ꮎ Ꮑ "
tui_format ""
tui_format "#{bold}Modular System Setup Framework#{normal}"
tui_format "#{italic}Arch / Hyprland / CachyOS#{normal}"
tui_format ""
tui_info "Modular System Setup Framework"
tui_info "Arch / Hyprland / CachyOS"
printf '\n'
if ((OMERON_FRESH_INSTALL)); then
tui_format "#{bold}#{yellow}⚡ FRESH INSTALL MODE#{normal}"
tui_format "Will install Hyprland, GPU drivers, and all dependencies."
tui_format ""
tui_warn "FRESH INSTALL MODE"
tui_info "Will install Hyprland, GPU drivers, and all dependencies."
printf '\n'
fi
}
show_summary() {
local modules=("$@")
tui_format ""
tui_format "#{bold}Installation Summary:#{normal}"
tui_format " Modules to run: ${#modules[@]}"
tui_separator
tui_bold "Installation Summary"
tui_info "$(tui_bold "${#modules[@]}") module(s) to run"
local gpu
gpu="$(detect_gpu)"
tui_format " Detected GPU: ${gpu}"
tui_info "Detected GPU: $(tui_bold "$gpu")"
if ((${#modules[@]})); then
tui_format ""
tui_format "#{bold}Steps:#{normal}"
printf '\n'
tui_bold "Steps:"
local i=1
for mod in "${modules[@]}"; do
local name
name="$(basename "$mod" .sh)"
tui_format " $i. ${name}"
printf ' \033[1;36m%d.\033[0m %s\n' "$i" "$(basename "$mod" .sh)"
((i++))
done
fi
tui_format ""
printf '\n'
if ! tui_confirm "Proceed with installation?"; then
tui_format "#{bold}Installation cancelled by user.#{normal}"
tui_bold "Installation cancelled."
exit 0
fi
}
@@ -251,23 +250,14 @@ main() {
parse_args "$@"
tui_style
show_banner
mkdir -p "$(dirname "$OMERON_LOG_FILE")"
log_info "Omeron installation started"
log_info "Log file: $OMERON_LOG_FILE"
log_info "Project: $OMERON_ROOT"
log_info "Fresh install: $OMERON_FRESH_INSTALL"
if ((!OMERON_FRESH_INSTALL)) && ((${#RUN_MODULES[@]} == 0)); then
log_info "Checking for fresh install..."
if is_fresh_install; then
OMERON_FRESH_INSTALL=1
export OMERON_FRESH_INSTALL
log_info "Fresh system detected — switching to full setup mode"
fi
fi
detect_environment
show_banner
local modules_to_run=()
if ((${#RUN_MODULES[@]})); then
@@ -277,7 +267,7 @@ main() {
fi
if ((${#modules_to_run[@]} == 0)); then
log_warn "No modules selected. Nothing to do."
tui_warn "No modules selected. Nothing to do."
exit 0
fi
@@ -291,47 +281,46 @@ main() {
if source "$module_path" 2>/dev/null && declare -F "module_description" >/dev/null 2>&1; then
description="$(module_description)"
fi
printf '\n'
log_step "$idx" "$total" "${description:-$(basename "$module_path" .sh)}"
module_run "$module_path" || {
local rc=$?
if declare -F "module_required" >/dev/null 2>&1; then
source "$module_path"
if module_required 2>/dev/null; then
log_error "Required module failed. Aborting."
tui_error "Required module failed. Aborting."
exit $rc
fi
fi
log_warn "Module completed with warnings"
tui_warn "Module completed with warnings"
}
((idx++))
done
printf '\n'
tui_header " Ꮎ Ꮎ Ꮑ "
tui_format ""
tui_format "#{bold}#{green}Installation Complete!#{normal}"
tui_format ""
tui_format "Log: ${OMERON_LOG_FILE}"
tui_format ""
tui_success "Installation Complete!"
printf '\n'
tui_info "Log: ${OMERON_LOG_FILE}"
printf '\n'
if ((OMERON_FRESH_INSTALL)); then
tui_format "#{bold}Your system is ready for Hyprland!#{normal}"
tui_format ""
tui_format " Start Hyprland: Hyprland"
tui_format " Or enable SDDM: sudo systemctl enable --now sddm"
tui_format " Reload config: hyprctl reload"
tui_bold "Your system is ready for Hyprland!"
tui_list \
"Start Hyprland: Hyprland" \
"Or enable SDDM: sudo systemctl enable --now sddm" \
"Reload config: hyprctl reload"
else
tui_format "What next?"
tui_format " - Reload config with: hyprctl reload"
tui_format " - Re-run installer: ./install.sh"
tui_bold "What next?"
tui_list \
"Reload config: hyprctl reload" \
"Re-run installer: ./install.sh"
fi
tui_format ""
printf '\n'
if have notify-send; then
notify-send "Omeron" "Installation complete!" >/dev/null 2>&1 || true
notify-send "Omeron" "Installation complete!" >/dev/null 2>&1 || true
fi
}