Initial commit: Omeron modular Hyprland setup framework
- 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/
This commit is contained in:
128
lib/config.sh
Executable file
128
lib/config.sh
Executable file
@@ -0,0 +1,128 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
OMERON_CONFIG_DIR="${OMERON_CONFIG_DIR:-$HOME/.config/omeron}"
|
||||
OMERON_PROJECT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
|
||||
config_load() {
|
||||
local config_file="$1"
|
||||
|
||||
if [[ ! -f "$config_file" ]]; then
|
||||
log_warn "Configuration not found: $config_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if command -v yq >/dev/null 2>&1; then
|
||||
config_parse_yq "$config_file"
|
||||
elif command -v python3 >/dev/null 2>&1; then
|
||||
config_parse_python "$config_file"
|
||||
else
|
||||
config_parse_shell "$config_file"
|
||||
fi
|
||||
}
|
||||
|
||||
config_parse_yq() {
|
||||
local config_file="$1"
|
||||
local key
|
||||
|
||||
while IFS='=' read -r key value; do
|
||||
[[ -z "$key" ]] && continue
|
||||
printf 'export OMERON_CFG_%s="%s"\n' "$key" "$value"
|
||||
done < <(yq -o shell "$config_file" 2>/dev/null)
|
||||
}
|
||||
|
||||
config_parse_python() {
|
||||
local config_file="$1"
|
||||
|
||||
python3 -c "
|
||||
import yaml, os, sys
|
||||
|
||||
with open('$config_file') as f:
|
||||
data = yaml.safe_load(f)
|
||||
|
||||
if not data:
|
||||
sys.exit(0)
|
||||
|
||||
def flatten(d, prefix=''):
|
||||
for k, v in d.items():
|
||||
key = f'{prefix}_{k}' if prefix else k
|
||||
if isinstance(v, dict):
|
||||
flatten(v, key)
|
||||
elif isinstance(v, list):
|
||||
print(f'export OMERON_CFG_{key}=\"{chr(32).join(str(x) for x in v)}\"')
|
||||
else:
|
||||
print(f'export OMERON_CFG_{key}=\"{v}\"')
|
||||
|
||||
flatten(data)
|
||||
" 2>/dev/null || config_parse_shell "$config_file"
|
||||
}
|
||||
|
||||
config_parse_shell() {
|
||||
local config_file="$1"
|
||||
local line key value
|
||||
|
||||
while IFS= read -r line; do
|
||||
line="${line%%#*}"
|
||||
[[ -z "$line" ]] && continue
|
||||
if [[ "$line" =~ ^[[:space:]]*([a-zA-Z_][a-zA-Z0-9_]*):[[:space:]]*(.*) ]]; then
|
||||
key="${BASH_REMATCH[1]}"
|
||||
value="${BASH_REMATCH[2]}"
|
||||
value="${value#[\"\']}"
|
||||
value="${value%[\"\']}"
|
||||
printf 'export OMERON_CFG_%s="%s"\n' "$key" "$value"
|
||||
fi
|
||||
done < "$config_file"
|
||||
}
|
||||
|
||||
config_save() {
|
||||
local config_file="$1"
|
||||
local key value
|
||||
|
||||
mkdir -p "$(dirname "$config_file")"
|
||||
|
||||
{
|
||||
printf '# Omeron Configuration\n'
|
||||
printf '# Generated: %s\n\n' "$(date --rfc-3339=seconds)"
|
||||
for entry in "$@"; do
|
||||
key="${entry%%=*}"
|
||||
value="${entry#*=}"
|
||||
printf '%s: "%s"\n' "$key" "$value"
|
||||
done
|
||||
} > "$config_file"
|
||||
}
|
||||
|
||||
config_get() {
|
||||
local key="$1"
|
||||
local var_name="OMERON_CFG_${key}"
|
||||
|
||||
printf '%s' "${!var_name:-}"
|
||||
}
|
||||
|
||||
config_merge() {
|
||||
local base_file="$1"
|
||||
local override_file="$2"
|
||||
|
||||
if command -v yq >/dev/null 2>&1; then
|
||||
yq eval-all '. as $item ireduce ({}; . * $item)' "$base_file" "$override_file"
|
||||
elif command -v python3 >/dev/null 2>&1; then
|
||||
python3 -c "
|
||||
import yaml, sys
|
||||
|
||||
with open('$base_file') as f:
|
||||
base = yaml.safe_load(f) or {}
|
||||
with open('$override_file') as f:
|
||||
override = yaml.safe_load(f) or {}
|
||||
|
||||
def merge(a, b):
|
||||
for k in b:
|
||||
if k in a and isinstance(a[k], dict) and isinstance(b[k], dict):
|
||||
merge(a[k], b[k])
|
||||
else:
|
||||
a[k] = b[k]
|
||||
return a
|
||||
|
||||
print(yaml.dump(merge(base, override), default_flow_style=False))
|
||||
" 2>/dev/null || cat "$base_file"
|
||||
else
|
||||
cat "$base_file"
|
||||
fi
|
||||
}
|
||||
46
lib/log.sh
Executable file
46
lib/log.sh
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
OMERON_LOG_FILE="${OMERON_LOG_FILE:-$HOME/.local/share/omeron/install.log}"
|
||||
OMERON_LOG_LEVEL="${OMERON_LOG_LEVEL:-INFO}"
|
||||
|
||||
__log_init() {
|
||||
mkdir -p "$(dirname "$OMERON_LOG_FILE")"
|
||||
}
|
||||
|
||||
__log_timestamp() {
|
||||
date '+%Y-%m-%d %H:%M:%S'
|
||||
}
|
||||
|
||||
__log_write() {
|
||||
local level="$1"
|
||||
local message="$2"
|
||||
local timestamp
|
||||
timestamp="$(__log_timestamp)"
|
||||
|
||||
__log_init
|
||||
printf '[%s] [%s] %s\n' "$timestamp" "$level" "$message" | tee -a "$OMERON_LOG_FILE"
|
||||
}
|
||||
|
||||
log_info() { __log_write "INFO" "$1"; }
|
||||
log_warn() { __log_write "WARN" "$1" >&2; }
|
||||
log_error() { __log_write "ERROR" "$1" >&2; }
|
||||
log_success() { __log_write "SUCCESS" "$1"; }
|
||||
log_debug() {
|
||||
[[ "$OMERON_LOG_LEVEL" == "DEBUG" ]] && __log_write "DEBUG" "$1"
|
||||
}
|
||||
|
||||
log_step() {
|
||||
local num="$1"
|
||||
local total="$2"
|
||||
local message="$3"
|
||||
printf '\n━━━ [%d/%d] %s ━━━\n' "$num" "$total" "$message"
|
||||
__log_write "STEP" "[$num/$total] $message"
|
||||
}
|
||||
|
||||
log_section() {
|
||||
local message="$1"
|
||||
local line
|
||||
line="$(printf '━%.0s' $(seq 1 "${#message}"))"
|
||||
printf '\n%s\n%s\n%s\n' "$line" "$message" "$line"
|
||||
__log_write "SECTION" "$message"
|
||||
}
|
||||
84
lib/modules.sh
Executable file
84
lib/modules.sh
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
OMERON_MODULE_DIR="${OMERON_MODULE_DIR:-$OMERON_PROJECT_DIR/modules}"
|
||||
|
||||
module_list() {
|
||||
local category="${1:-}"
|
||||
|
||||
if [[ -n "$category" ]]; then
|
||||
find "$OMERON_MODULE_DIR/$category" -maxdepth 1 -name '*.sh' -type f | sort
|
||||
else
|
||||
find "$OMERON_MODULE_DIR" -name '*.sh' -type f | sort
|
||||
fi
|
||||
}
|
||||
|
||||
module_run() {
|
||||
local module_path="$1"
|
||||
local module_name
|
||||
module_name="$(basename "$module_path" .sh)"
|
||||
|
||||
if [[ ! -f "$module_path" ]]; then
|
||||
log_error "Module not found: $module_path"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_info "Running module: $module_name"
|
||||
OMERON_CURRENT_MODULE="$module_name" source "$module_path"
|
||||
|
||||
if declare -F "module_main" >/dev/null 2>&1; then
|
||||
module_main
|
||||
local rc=$?
|
||||
if [[ $rc -eq 0 ]]; then
|
||||
log_success "Module '$module_name' completed"
|
||||
else
|
||||
log_error "Module '$module_name' failed (exit: $rc)"
|
||||
fi
|
||||
return $rc
|
||||
else
|
||||
log_error "Module '$module_name' has no module_main function"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
module_check_prereqs() {
|
||||
local module_path="$1"
|
||||
|
||||
if ! declare -F "module_prereqs" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
module_prereqs
|
||||
}
|
||||
|
||||
module_skip() {
|
||||
local module_path="$1"
|
||||
|
||||
if declare -F "module_should_skip" >/dev/null 2>&1; then
|
||||
module_should_skip
|
||||
return $?
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
module_describe() {
|
||||
local module_path="$1"
|
||||
|
||||
if declare -F "module_description" >/dev/null 2>&1; then
|
||||
module_description
|
||||
else
|
||||
basename "$module_path" .sh
|
||||
fi
|
||||
}
|
||||
|
||||
module_confirm() {
|
||||
local module_path="$1"
|
||||
local description
|
||||
description="$(module_describe "$module_path")"
|
||||
|
||||
if declare -F "module_required" >/dev/null 2>&1 && module_required; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
tui_confirm "Run '$description'?"
|
||||
}
|
||||
161
lib/tui.sh
Executable file
161
lib/tui.sh
Executable file
@@ -0,0 +1,161 @@
|
||||
#!/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
|
||||
}
|
||||
263
lib/utils.sh
Executable file
263
lib/utils.sh
Executable file
@@ -0,0 +1,263 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
require() {
|
||||
local cmd="$1"
|
||||
local pkg="${2:-$1}"
|
||||
|
||||
if ! command -v "$cmd" >/dev/null 2>&1; then
|
||||
log_error "Required command '$cmd' not found. Install with: sudo pacman -S $pkg"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
require_optional() {
|
||||
local cmd="$1"
|
||||
local pkg="${2:-$1}"
|
||||
|
||||
if ! command -v "$cmd" >/dev/null 2>&1; then
|
||||
log_warn "'$cmd' not found. Install with: sudo pacman -S $pkg"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
have() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
is_arch() {
|
||||
[[ -f /etc/arch-release ]] || [[ -d /etc/pacman.d ]]
|
||||
}
|
||||
|
||||
is_root() {
|
||||
[[ "$EUID" -eq 0 ]]
|
||||
}
|
||||
|
||||
sudo_run() {
|
||||
if is_root; then
|
||||
"$@"
|
||||
else
|
||||
sudo "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
backup_file() {
|
||||
local target="$1"
|
||||
local backup_dir="${2:-$HOME/.dotfiles-backup/$(date +%Y%m%d-%H%M%S)}"
|
||||
local relative="${target#"$HOME"/}"
|
||||
local backup="$backup_dir/$relative"
|
||||
|
||||
[[ -e "$target" || -L "$target" ]] || return 0
|
||||
|
||||
mkdir -p "$(dirname "$backup")"
|
||||
cp -a "$target" "$backup"
|
||||
log_info "Backed up $target -> $backup"
|
||||
printf '%s' "$backup_dir"
|
||||
}
|
||||
|
||||
symlink_path() {
|
||||
local source="$1"
|
||||
local target="$2"
|
||||
|
||||
backup_file "$target"
|
||||
rm -rf "$target"
|
||||
mkdir -p "$(dirname "$target")"
|
||||
ln -sfn "$source" "$target"
|
||||
log_info "Linked $source -> $target"
|
||||
}
|
||||
|
||||
copy_path() {
|
||||
local source="$1"
|
||||
local target="$2"
|
||||
|
||||
backup_file "$target"
|
||||
rm -rf "$target"
|
||||
mkdir -p "$(dirname "$target")"
|
||||
cp -a "$source" "$target"
|
||||
log_info "Copied $source -> $target"
|
||||
}
|
||||
|
||||
platform_packages() {
|
||||
if is_arch; then
|
||||
printf '%s\n' "arch"
|
||||
fi
|
||||
if [[ -f /etc/os-release ]]; then
|
||||
local id
|
||||
id="$(grep -oP '^ID=\K.*' /etc/os-release)"
|
||||
printf '%s\n' "$id"
|
||||
fi
|
||||
}
|
||||
|
||||
is_package_installed() {
|
||||
local pkg="$1"
|
||||
|
||||
if command -v pacman >/dev/null 2>&1; then
|
||||
pacman -Qi "$pkg" >/dev/null 2>&1
|
||||
return $?
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
install_pacman() {
|
||||
local packages=("$@")
|
||||
local to_install=()
|
||||
local pkg
|
||||
|
||||
for pkg in "${packages[@]}"; do
|
||||
if ! pacman -Si "$pkg" >/dev/null 2>&1; then
|
||||
log_warn "Package '$pkg' not found in pacman repositories"
|
||||
continue
|
||||
fi
|
||||
if ! is_package_installed "$pkg"; then
|
||||
to_install+=("$pkg")
|
||||
fi
|
||||
done
|
||||
|
||||
if ((${#to_install[@]})); then
|
||||
log_info "Installing: ${to_install[*]}"
|
||||
sudo_run pacman -S --needed --noconfirm "${to_install[@]}"
|
||||
else
|
||||
log_info "All packages already installed"
|
||||
fi
|
||||
}
|
||||
|
||||
install_aur() {
|
||||
local packages=("$@")
|
||||
local aur_helper=""
|
||||
|
||||
if have paru; then
|
||||
aur_helper="paru"
|
||||
elif have yay; then
|
||||
aur_helper="yay"
|
||||
else
|
||||
log_error "No AUR helper found (install paru or yay)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local to_install=()
|
||||
local pkg
|
||||
|
||||
for pkg in "${packages[@]}"; do
|
||||
if ! is_package_installed "$pkg"; then
|
||||
to_install+=("$pkg")
|
||||
fi
|
||||
done
|
||||
|
||||
if ((${#to_install[@]})); then
|
||||
log_info "Installing from AUR: ${to_install[*]}"
|
||||
"$aur_helper" -S --needed --noconfirm "${to_install[@]}"
|
||||
else
|
||||
log_info "All AUR packages already installed"
|
||||
fi
|
||||
}
|
||||
|
||||
replace_home_paths() {
|
||||
local dir="$1"
|
||||
local original_home="${2:-/home/pascal}"
|
||||
|
||||
if [[ "$original_home" == "$HOME" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
find "$dir" -type f -exec sed -i "s#${original_home}#${HOME}#g" {} + 2>/dev/null || true
|
||||
log_info "Rewrote home paths in $dir"
|
||||
}
|
||||
|
||||
detect_gpu() {
|
||||
if ! command -v lspci >/dev/null 2>&1; then
|
||||
if have pacman; then
|
||||
sudo_run pacman -S --needed --noconfirm pciutils >/dev/null 2>&1 || true
|
||||
fi
|
||||
fi
|
||||
|
||||
local gpu_info
|
||||
gpu_info="$(lspci -nn 2>/dev/null | grep -E '\[0300\]|\[0302\]|\[0380\]' || true)"
|
||||
[[ -z "$gpu_info" ]] && gpu_info="$(lspci -nn 2>/dev/null | grep -iE '(VGA|3D|Display).*controller' || true)"
|
||||
|
||||
if printf '%s' "$gpu_info" | grep -qi "\[10de:"; then
|
||||
printf 'nvidia'
|
||||
elif printf '%s' "$gpu_info" | grep -qi "\[1002:\|\[1022:"; then
|
||||
printf 'amd'
|
||||
elif printf '%s' "$gpu_info" | grep -qi "\[8086:"; then
|
||||
printf 'intel'
|
||||
elif printf '%s' "$gpu_info" | grep -qi "vmware\|qemu\|virtualbox\|virtio"; then
|
||||
printf 'vm'
|
||||
elif printf '%s' "$gpu_info" | grep -qi "nvidia"; then
|
||||
printf 'nvidia'
|
||||
elif printf '%s' "$gpu_info" | grep -qi "amd\|advanced micro devices"; then
|
||||
printf 'amd'
|
||||
elif printf '%s' "$gpu_info" | grep -qi "intel"; then
|
||||
printf 'intel'
|
||||
else
|
||||
printf 'unknown'
|
||||
fi
|
||||
}
|
||||
|
||||
gpu_packages() {
|
||||
local gpu_type
|
||||
gpu_type="$(detect_gpu)"
|
||||
|
||||
case "$gpu_type" in
|
||||
intel)
|
||||
printf '%s\n' "xf86-video-intel" "vulkan-intel" "intel-media-driver" "libva-intel-driver"
|
||||
;;
|
||||
amd)
|
||||
printf '%s\n' "xf86-video-amdgpu" "vulkan-radeon" "libva-mesa-driver" "mesa-vdpau"
|
||||
;;
|
||||
nvidia)
|
||||
printf '%s\n' "nvidia-dkms" "nvidia-utils" "nvidia-settings" "libva-nvidia-driver" "vulkan-tools"
|
||||
;;
|
||||
vm)
|
||||
printf '%s\n' "xf86-video-vmware" "mesa" "vulkan-swrast"
|
||||
;;
|
||||
*)
|
||||
printf '%s\n' "mesa" "vulkan-swrast"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
is_fresh_install() {
|
||||
have hyprctl && return 1
|
||||
|
||||
if have hyprland; then
|
||||
hyprland --version >/dev/null 2>&1 && return 1
|
||||
fi
|
||||
|
||||
if [[ -n "${WAYLAND_DISPLAY:-}" || -n "${DISPLAY:-}" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
count_missing_packages() {
|
||||
local packages=("$@")
|
||||
local missing=0
|
||||
local pkg
|
||||
|
||||
for pkg in "${packages[@]}"; do
|
||||
if ! is_package_installed "$pkg"; then
|
||||
((missing++))
|
||||
fi
|
||||
done
|
||||
|
||||
printf '%d' "$missing"
|
||||
}
|
||||
|
||||
system_summary() {
|
||||
local gpu
|
||||
gpu="$(detect_gpu)"
|
||||
|
||||
cat <<SUMMARY
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ System Summary │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ OS: $(grep -oP '^PRETTY_NAME="?\K[^"\n]+' /etc/os-release 2>/dev/null | sed 's/"$//' || echo "Arch Linux")
|
||||
│ Kernel: $(uname -r)
|
||||
│ GPU: ${gpu} ($(lspci -nn 2>/dev/null | grep -E '\[0300\]|\[0302\]|\[0380\]' | sed 's/.*: //' | head -1 || echo "unknown"))
|
||||
│ Session: $(printenv XDG_SESSION_TYPE || echo "none (TTY)")
|
||||
│ Hyprland: $(have hyprctl && echo "installed" || echo "NOT installed")
|
||||
│ AUR: $(have paru && echo "paru" || (have yay && echo "yay" || echo "none"))
|
||||
└─────────────────────────────────────────────┘
|
||||
SUMMARY
|
||||
}
|
||||
Reference in New Issue
Block a user