642 lines
19 KiB
Bash
Executable File
642 lines
19 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Hyprland Installer - Core Library
|
|
# Optimized for low memory/CPU usage with modern UI
|
|
# License: GPL-3.0
|
|
|
|
set -euo pipefail
|
|
|
|
#=============================================================================
|
|
# COLOR DEFINITIONS (Lazy loaded, no subshells)
|
|
#=============================================================================
|
|
declare -A COLORS=(
|
|
[reset]="\e[0m"
|
|
[bold]="\e[1m"
|
|
[dim]="\e[2m"
|
|
[red]="\e[31m"
|
|
[green]="\e[32m"
|
|
[yellow]="\e[33m"
|
|
[blue]="\e[34m"
|
|
[magenta]="\e[35m"
|
|
[cyan]="\e[36m"
|
|
[white]="\e[37m"
|
|
[bg_red]="\e[41m"
|
|
[bg_green]="\e[42m"
|
|
[bg_blue]="\e[44m"
|
|
[bg_cyan]="\e[46m"
|
|
)
|
|
|
|
# Status prefixes (pre-computed to avoid repeated string operations)
|
|
readonly OK="${COLORS[green]}[OK]${COLORS[reset]}"
|
|
readonly ERR="${COLORS[red]}[ERROR]${COLORS[reset]}"
|
|
readonly WARN="${COLORS[yellow]}[WARN]${COLORS[reset]}"
|
|
readonly INFO="${COLORS[blue]}[INFO]${COLORS[reset]}"
|
|
readonly NOTE="${COLORS[cyan]}[NOTE]${COLORS[reset]}"
|
|
readonly ACT="${COLORS[magenta]}[ACTION]${COLORS[reset]}"
|
|
|
|
#=============================================================================
|
|
# GLOBALS (only declare if not already set by parent script)
|
|
#=============================================================================
|
|
[[ -z "${LOG_DIR:-}" ]] && declare -g LOG_DIR="Install-Logs"
|
|
[[ -z "${LOG_FILE:-}" ]] && declare -g LOG_FILE=""
|
|
[[ -z "${ISAUR:-}" ]] && declare -g ISAUR=""
|
|
[[ -z "${PARALLEL_JOBS:-}" ]] && declare -g PARALLEL_JOBS="4"
|
|
[[ -z "${SCRIPT_DIR:-}" ]] && declare -g SCRIPT_DIR=""
|
|
declare -g INSTALL_QUEUE=()
|
|
declare -g FAILED_PACKAGES=()
|
|
declare -g SUCCESSFUL_PACKAGES=()
|
|
|
|
#=============================================================================
|
|
# INITIALIZATION
|
|
#=============================================================================
|
|
init_installer() {
|
|
# Only set SCRIPT_DIR if not already set (may be readonly from parent script)
|
|
if [[ -z "${SCRIPT_DIR:-}" ]]; then
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
fi
|
|
|
|
# Create log directory
|
|
mkdir -p "$LOG_DIR"
|
|
LOG_FILE="$LOG_DIR/install-$(date +%Y%m%d-%H%M%S).log"
|
|
|
|
# Detect AUR helper (cached for performance)
|
|
if command -v paru &>/dev/null; then
|
|
ISAUR="paru"
|
|
elif command -v yay &>/dev/null; then
|
|
ISAUR="yay"
|
|
else
|
|
ISAUR=""
|
|
fi
|
|
|
|
# Set terminal settings for better UX
|
|
stty -echo 2>/dev/null || true
|
|
trap cleanup EXIT INT TERM
|
|
}
|
|
|
|
cleanup() {
|
|
stty echo 2>/dev/null || true
|
|
tput cnorm 2>/dev/null || true
|
|
echo -e "\n${COLORS[reset]}"
|
|
}
|
|
|
|
#=============================================================================
|
|
# LOGGING (Optimized - no subshells)
|
|
#=============================================================================
|
|
log() {
|
|
local level="$1"
|
|
shift
|
|
local msg="$*"
|
|
local timestamp
|
|
printf -v timestamp '%(%Y-%m-%d %H:%M:%S)T' -1
|
|
printf '[%s] [%s] %s\n' "$timestamp" "$level" "$msg" >> "$LOG_FILE"
|
|
}
|
|
|
|
log_info() { log "INFO" "$@"; }
|
|
log_error() { log "ERROR" "$@"; }
|
|
log_warn() { log "WARN" "$@"; }
|
|
|
|
#=============================================================================
|
|
# UI COMPONENTS (Modern, lightweight)
|
|
#=============================================================================
|
|
|
|
# Print styled header
|
|
print_header() {
|
|
local text="$1"
|
|
local width="${2:-60}"
|
|
local padding=$(( (width - ${#text} - 2) / 2 ))
|
|
|
|
echo -e "\n${COLORS[bold]}${COLORS[cyan]}"
|
|
printf '%*s' "$width" | tr ' ' '='
|
|
echo
|
|
printf '%*s %s %*s\n' "$padding" "" "$text" "$padding" ""
|
|
printf '%*s' "$width" | tr ' ' '='
|
|
echo -e "${COLORS[reset]}\n"
|
|
}
|
|
|
|
# Print styled box
|
|
print_box() {
|
|
local title="$1"
|
|
local content="$2"
|
|
local width="${3:-50}"
|
|
|
|
echo -e "${COLORS[cyan]}+$(printf '%*s' $((width-2)) | tr ' ' '-')+${COLORS[reset]}"
|
|
echo -e "${COLORS[cyan]}|${COLORS[bold]}${COLORS[white]} $title$(printf '%*s' $((width - ${#title} - 3)) '')${COLORS[cyan]}|${COLORS[reset]}"
|
|
echo -e "${COLORS[cyan]}+$(printf '%*s' $((width-2)) | tr ' ' '-')+${COLORS[reset]}"
|
|
echo -e "${COLORS[cyan]}|${COLORS[reset]} $content$(printf '%*s' $((width - ${#content} - 3)) '')${COLORS[cyan]}|${COLORS[reset]}"
|
|
echo -e "${COLORS[cyan]}+$(printf '%*s' $((width-2)) | tr ' ' '-')+${COLORS[reset]}"
|
|
}
|
|
|
|
# Animated spinner (memory efficient)
|
|
spinner() {
|
|
local pid="$1"
|
|
local msg="${2:-Processing}"
|
|
local frames=('.' '..' '...' '....' '.....')
|
|
local i=0
|
|
|
|
tput civis # Hide cursor
|
|
|
|
while kill -0 "$pid" 2>/dev/null; do
|
|
printf "\r${INFO} %s %s " "$msg" "${frames[i]}"
|
|
i=$(( (i + 1) % ${#frames[@]} ))
|
|
sleep 0.2
|
|
done
|
|
|
|
tput cnorm # Show cursor
|
|
}
|
|
|
|
# Modern progress bar
|
|
progress_bar() {
|
|
local current="$1"
|
|
local total="$2"
|
|
local width="${3:-40}"
|
|
local percent=$(( current * 100 / total ))
|
|
local filled=$(( current * width / total ))
|
|
local empty=$(( width - filled ))
|
|
|
|
printf "\r${COLORS[cyan]}["
|
|
printf '%*s' "$filled" | tr ' ' '#'
|
|
printf '%*s' "$empty" | tr ' ' '-'
|
|
printf "] %3d%% (%d/%d)${COLORS[reset]}" "$percent" "$current" "$total"
|
|
}
|
|
|
|
# Interactive menu using pure bash (no external deps)
|
|
select_menu() {
|
|
local title="$1"
|
|
shift
|
|
local options=("$@")
|
|
local selected=0
|
|
local key
|
|
|
|
# Save cursor position
|
|
tput sc
|
|
tput civis # Hide cursor
|
|
|
|
while true; do
|
|
tput rc # Restore cursor position
|
|
|
|
echo -e "\n${COLORS[bold]}${COLORS[cyan]}$title${COLORS[reset]}\n"
|
|
echo -e "${COLORS[dim]}Use arrow keys to navigate, Enter to select, q to quit${COLORS[reset]}\n"
|
|
|
|
for i in "${!options[@]}"; do
|
|
if [[ $i -eq $selected ]]; then
|
|
echo -e " ${COLORS[bg_cyan]}${COLORS[bold]} > ${options[$i]} ${COLORS[reset]}"
|
|
else
|
|
echo -e " ${options[$i]}"
|
|
fi
|
|
done
|
|
|
|
# Read single keypress
|
|
read -rsn1 key
|
|
|
|
case "$key" in
|
|
A|k) # Up arrow or k
|
|
((selected > 0)) && ((selected--))
|
|
;;
|
|
B|j) # Down arrow or j
|
|
((selected < ${#options[@]} - 1)) && ((selected++))
|
|
;;
|
|
'') # Enter
|
|
tput cnorm
|
|
echo "$selected"
|
|
return 0
|
|
;;
|
|
q|Q)
|
|
tput cnorm
|
|
return 1
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
# Multi-select checkbox menu
|
|
checkbox_menu() {
|
|
local title="$1"
|
|
shift
|
|
local -a options=("$@")
|
|
local -a selected=()
|
|
local cursor=0
|
|
local key
|
|
|
|
# Initialize all as unselected
|
|
for i in "${!options[@]}"; do
|
|
selected[$i]=0
|
|
done
|
|
|
|
tput sc
|
|
tput civis
|
|
|
|
while true; do
|
|
tput rc
|
|
tput ed # Clear from cursor to end of screen
|
|
|
|
echo -e "\n${COLORS[bold]}${COLORS[cyan]}$title${COLORS[reset]}\n"
|
|
echo -e "${COLORS[dim]}Space to toggle, Enter to confirm, a=all, n=none, q=quit${COLORS[reset]}\n"
|
|
|
|
for i in "${!options[@]}"; do
|
|
local checkbox
|
|
if [[ ${selected[$i]} -eq 1 ]]; then
|
|
checkbox="${COLORS[green]}[x]${COLORS[reset]}"
|
|
else
|
|
checkbox="${COLORS[dim]}[ ]${COLORS[reset]}"
|
|
fi
|
|
|
|
if [[ $i -eq $cursor ]]; then
|
|
echo -e " ${COLORS[bg_blue]}${COLORS[bold]} > $checkbox ${options[$i]} ${COLORS[reset]}"
|
|
else
|
|
echo -e " $checkbox ${options[$i]}"
|
|
fi
|
|
done
|
|
|
|
read -rsn1 key
|
|
|
|
case "$key" in
|
|
A|k) ((cursor > 0)) && ((cursor--)) ;;
|
|
B|j) ((cursor < ${#options[@]} - 1)) && ((cursor++)) ;;
|
|
' ') selected[$cursor]=$(( 1 - selected[$cursor] )) ;;
|
|
a|A) for i in "${!selected[@]}"; do selected[$i]=1; done ;;
|
|
n|N) for i in "${!selected[@]}"; do selected[$i]=0; done ;;
|
|
'') # Enter - return selected indices
|
|
tput cnorm
|
|
local result=""
|
|
for i in "${!selected[@]}"; do
|
|
[[ ${selected[$i]} -eq 1 ]] && result+="$i "
|
|
done
|
|
echo "$result"
|
|
return 0
|
|
;;
|
|
q|Q)
|
|
tput cnorm
|
|
return 1
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
# Yes/No prompt with default
|
|
confirm() {
|
|
local prompt="$1"
|
|
local default="${2:-y}"
|
|
local response
|
|
|
|
if [[ "$default" == "y" ]]; then
|
|
prompt+=" [Y/n]: "
|
|
else
|
|
prompt+=" [y/N]: "
|
|
fi
|
|
|
|
echo -en "${ACT} $prompt"
|
|
read -r response
|
|
response="${response:-$default}"
|
|
|
|
[[ "${response,,}" =~ ^(y|yes)$ ]]
|
|
}
|
|
|
|
#=============================================================================
|
|
# PACKAGE MANAGEMENT (Optimized for performance)
|
|
#=============================================================================
|
|
|
|
# Check if package is installed (cached results)
|
|
declare -A PKG_CACHE=()
|
|
is_installed() {
|
|
local pkg="$1"
|
|
|
|
# Check cache first
|
|
if [[ -n "${PKG_CACHE[$pkg]:-}" ]]; then
|
|
[[ "${PKG_CACHE[$pkg]}" == "1" ]]
|
|
return $?
|
|
fi
|
|
|
|
# Query and cache
|
|
if pacman -Qi "$pkg" &>/dev/null; then
|
|
PKG_CACHE[$pkg]=1
|
|
return 0
|
|
else
|
|
PKG_CACHE[$pkg]=0
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Install single package (pacman)
|
|
install_pacman() {
|
|
local pkg="$1"
|
|
|
|
if is_installed "$pkg"; then
|
|
echo -e "${INFO} ${COLORS[magenta]}$pkg${COLORS[reset]} already installed, skipping"
|
|
return 0
|
|
fi
|
|
|
|
echo -e "${NOTE} Installing ${COLORS[yellow]}$pkg${COLORS[reset]}..."
|
|
|
|
if sudo pacman -S --noconfirm --needed "$pkg" >> "$LOG_FILE" 2>&1; then
|
|
echo -e "${OK} ${COLORS[green]}$pkg${COLORS[reset]} installed successfully"
|
|
PKG_CACHE[$pkg]=1
|
|
SUCCESSFUL_PACKAGES+=("$pkg")
|
|
return 0
|
|
else
|
|
echo -e "${ERR} Failed to install ${COLORS[red]}$pkg${COLORS[reset]}"
|
|
FAILED_PACKAGES+=("$pkg")
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Install single package (AUR)
|
|
install_aur() {
|
|
local pkg="$1"
|
|
|
|
if [[ -z "$ISAUR" ]]; then
|
|
echo -e "${ERR} No AUR helper found"
|
|
return 1
|
|
fi
|
|
|
|
if is_installed "$pkg"; then
|
|
echo -e "${INFO} ${COLORS[magenta]}$pkg${COLORS[reset]} already installed, skipping"
|
|
return 0
|
|
fi
|
|
|
|
echo -e "${NOTE} Installing ${COLORS[yellow]}$pkg${COLORS[reset]} from AUR..."
|
|
|
|
if $ISAUR -S --noconfirm --needed "$pkg" >> "$LOG_FILE" 2>&1; then
|
|
echo -e "${OK} ${COLORS[green]}$pkg${COLORS[reset]} installed successfully"
|
|
PKG_CACHE[$pkg]=1
|
|
SUCCESSFUL_PACKAGES+=("$pkg")
|
|
return 0
|
|
else
|
|
echo -e "${ERR} Failed to install ${COLORS[red]}$pkg${COLORS[reset]}"
|
|
FAILED_PACKAGES+=("$pkg")
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Install package (auto-detect source)
|
|
install_pkg() {
|
|
local pkg="$1"
|
|
|
|
if is_installed "$pkg"; then
|
|
echo -e "${INFO} ${COLORS[magenta]}$pkg${COLORS[reset]} already installed"
|
|
return 0
|
|
fi
|
|
|
|
# Try pacman first, then AUR
|
|
if pacman -Si "$pkg" &>/dev/null; then
|
|
install_pacman "$pkg"
|
|
elif [[ -n "$ISAUR" ]]; then
|
|
install_aur "$pkg"
|
|
else
|
|
echo -e "${ERR} Package $pkg not found and no AUR helper available"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Parallel package installation (significant performance boost)
|
|
install_packages_parallel() {
|
|
local -a packages=("$@")
|
|
local total=${#packages[@]}
|
|
local count=0
|
|
local pids=()
|
|
local pkg_pids=()
|
|
|
|
echo -e "\n${INFO} Installing ${COLORS[bold]}$total${COLORS[reset]} packages (${PARALLEL_JOBS} parallel jobs)...\n"
|
|
|
|
for pkg in "${packages[@]}"; do
|
|
# Skip if already installed
|
|
if is_installed "$pkg"; then
|
|
echo -e "${INFO} ${COLORS[dim]}$pkg${COLORS[reset]} - already installed"
|
|
((count++))
|
|
progress_bar "$count" "$total"
|
|
continue
|
|
fi
|
|
|
|
# Wait if we've reached max parallel jobs
|
|
while [[ ${#pids[@]} -ge $PARALLEL_JOBS ]]; do
|
|
for i in "${!pids[@]}"; do
|
|
if ! kill -0 "${pids[$i]}" 2>/dev/null; then
|
|
wait "${pids[$i]}" && SUCCESSFUL_PACKAGES+=("${pkg_pids[$i]}") || FAILED_PACKAGES+=("${pkg_pids[$i]}")
|
|
unset 'pids[i]' 'pkg_pids[i]'
|
|
fi
|
|
done
|
|
pids=("${pids[@]}")
|
|
pkg_pids=("${pkg_pids[@]}")
|
|
sleep 0.1
|
|
done
|
|
|
|
# Start background installation
|
|
(
|
|
if pacman -Si "$pkg" &>/dev/null; then
|
|
sudo pacman -S --noconfirm --needed "$pkg" >> "$LOG_FILE" 2>&1
|
|
elif [[ -n "$ISAUR" ]]; then
|
|
$ISAUR -S --noconfirm --needed "$pkg" >> "$LOG_FILE" 2>&1
|
|
fi
|
|
) &
|
|
|
|
pids+=($!)
|
|
pkg_pids+=("$pkg")
|
|
|
|
((count++))
|
|
progress_bar "$count" "$total"
|
|
done
|
|
|
|
# Wait for remaining jobs
|
|
for i in "${!pids[@]}"; do
|
|
wait "${pids[$i]}" && SUCCESSFUL_PACKAGES+=("${pkg_pids[$i]}") || FAILED_PACKAGES+=("${pkg_pids[$i]}")
|
|
done
|
|
|
|
echo -e "\n\n${OK} Installation complete"
|
|
echo -e "${INFO} Successful: ${#SUCCESSFUL_PACKAGES[@]} | Failed: ${#FAILED_PACKAGES[@]}"
|
|
|
|
if [[ ${#FAILED_PACKAGES[@]} -gt 0 ]]; then
|
|
echo -e "${WARN} Failed packages: ${FAILED_PACKAGES[*]}"
|
|
fi
|
|
}
|
|
|
|
# Sequential installation with progress
|
|
install_packages_sequential() {
|
|
local -a packages=("$@")
|
|
local total=${#packages[@]}
|
|
local count=0
|
|
|
|
echo -e "\n${INFO} Installing ${COLORS[bold]}$total${COLORS[reset]} packages...\n"
|
|
|
|
for pkg in "${packages[@]}"; do
|
|
((count++))
|
|
progress_bar "$count" "$total"
|
|
echo ""
|
|
install_pkg "$pkg"
|
|
done
|
|
|
|
echo -e "\n${OK} Installation complete"
|
|
}
|
|
|
|
# Remove package
|
|
remove_pkg() {
|
|
local pkg="$1"
|
|
|
|
if ! is_installed "$pkg"; then
|
|
echo -e "${INFO} ${COLORS[dim]}$pkg${COLORS[reset]} not installed, skipping"
|
|
return 0
|
|
fi
|
|
|
|
echo -e "${NOTE} Removing ${COLORS[yellow]}$pkg${COLORS[reset]}..."
|
|
|
|
if sudo pacman -Rns --noconfirm "$pkg" >> "$LOG_FILE" 2>&1; then
|
|
echo -e "${OK} ${COLORS[green]}$pkg${COLORS[reset]} removed"
|
|
PKG_CACHE[$pkg]=0
|
|
return 0
|
|
else
|
|
echo -e "${ERR} Failed to remove ${COLORS[red]}$pkg${COLORS[reset]}"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
#=============================================================================
|
|
# SYSTEM DETECTION
|
|
#=============================================================================
|
|
|
|
# Detect GPU
|
|
detect_gpu() {
|
|
local gpu_info
|
|
gpu_info=$(lspci 2>/dev/null | grep -iE "vga|3d|display" || true)
|
|
|
|
if echo "$gpu_info" | grep -qi "nvidia"; then
|
|
echo "nvidia"
|
|
elif echo "$gpu_info" | grep -qi "amd\|radeon"; then
|
|
echo "amd"
|
|
elif echo "$gpu_info" | grep -qi "intel"; then
|
|
echo "intel"
|
|
else
|
|
echo "unknown"
|
|
fi
|
|
}
|
|
|
|
# Detect if running in VM
|
|
detect_vm() {
|
|
if systemd-detect-virt -q 2>/dev/null; then
|
|
systemd-detect-virt
|
|
elif [[ -d /proc/vz ]]; then
|
|
echo "openvz"
|
|
elif grep -qi "hypervisor" /proc/cpuinfo 2>/dev/null; then
|
|
echo "unknown-vm"
|
|
else
|
|
echo "none"
|
|
fi
|
|
}
|
|
|
|
# Check if laptop
|
|
is_laptop() {
|
|
[[ -d /sys/class/power_supply/BAT0 ]] || [[ -d /sys/class/power_supply/BAT1 ]]
|
|
}
|
|
|
|
# Detect active display manager
|
|
detect_dm() {
|
|
local dms=("gdm" "gdm3" "lightdm" "lxdm" "sddm")
|
|
|
|
for dm in "${dms[@]}"; do
|
|
if systemctl is-active --quiet "$dm.service" 2>/dev/null; then
|
|
echo "$dm"
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
echo "none"
|
|
}
|
|
|
|
#=============================================================================
|
|
# SCRIPT EXECUTION
|
|
#=============================================================================
|
|
|
|
# Execute script from install-scripts directory
|
|
run_script() {
|
|
local script="$1"
|
|
local script_path="${SCRIPT_DIR}/${script}"
|
|
|
|
if [[ -f "$script_path" ]]; then
|
|
chmod +x "$script_path"
|
|
log_info "Executing: $script"
|
|
|
|
if bash "$script_path"; then
|
|
log_info "Completed: $script"
|
|
return 0
|
|
else
|
|
log_error "Failed: $script"
|
|
return 1
|
|
fi
|
|
else
|
|
echo -e "${ERR} Script not found: $script"
|
|
log_error "Script not found: $script"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
#=============================================================================
|
|
# UTILITY FUNCTIONS
|
|
#=============================================================================
|
|
|
|
# Backup file/directory
|
|
backup() {
|
|
local target="$1"
|
|
local backup_dir="${2:-$HOME/.config-backup}"
|
|
local timestamp
|
|
printf -v timestamp '%(%Y%m%d-%H%M%S)T' -1
|
|
|
|
if [[ -e "$target" ]]; then
|
|
mkdir -p "$backup_dir"
|
|
cp -r "$target" "$backup_dir/$(basename "$target").$timestamp"
|
|
echo -e "${OK} Backed up: $target"
|
|
log_info "Backed up: $target -> $backup_dir"
|
|
fi
|
|
}
|
|
|
|
# Download file with progress
|
|
download() {
|
|
local url="$1"
|
|
local dest="$2"
|
|
|
|
if command -v curl &>/dev/null; then
|
|
curl -fsSL --progress-bar -o "$dest" "$url"
|
|
elif command -v wget &>/dev/null; then
|
|
wget -q --show-progress -O "$dest" "$url"
|
|
else
|
|
echo -e "${ERR} Neither curl nor wget found"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Clone git repo
|
|
git_clone() {
|
|
local repo="$1"
|
|
local dest="$2"
|
|
local depth="${3:-1}"
|
|
|
|
if [[ -d "$dest" ]]; then
|
|
echo -e "${INFO} Updating existing repo: $dest"
|
|
git -C "$dest" pull --ff-only >> "$LOG_FILE" 2>&1
|
|
else
|
|
echo -e "${NOTE} Cloning: $repo"
|
|
git clone --depth="$depth" "$repo" "$dest" >> "$LOG_FILE" 2>&1
|
|
fi
|
|
}
|
|
|
|
# Print system info
|
|
print_system_info() {
|
|
echo -e "\n${COLORS[bold]}${COLORS[cyan]}System Information${COLORS[reset]}"
|
|
echo -e "${COLORS[dim]}─────────────────────────────────────${COLORS[reset]}"
|
|
echo -e " ${COLORS[yellow]}Distro:${COLORS[reset]} $(grep -oP '(?<=^NAME=).+' /etc/os-release | tr -d '"')"
|
|
echo -e " ${COLORS[yellow]}Kernel:${COLORS[reset]} $(uname -r)"
|
|
echo -e " ${COLORS[yellow]}GPU:${COLORS[reset]} $(detect_gpu)"
|
|
echo -e " ${COLORS[yellow]}VM:${COLORS[reset]} $(detect_vm)"
|
|
echo -e " ${COLORS[yellow]}Laptop:${COLORS[reset]} $(is_laptop && echo "Yes" || echo "No")"
|
|
echo -e " ${COLORS[yellow]}DM:${COLORS[reset]} $(detect_dm)"
|
|
echo -e " ${COLORS[yellow]}AUR:${COLORS[reset]} ${ISAUR:-none}"
|
|
echo -e "${COLORS[dim]}─────────────────────────────────────${COLORS[reset]}\n"
|
|
}
|
|
|
|
#=============================================================================
|
|
# EXPORT ALL FUNCTIONS
|
|
#=============================================================================
|
|
export -f log log_info log_error log_warn
|
|
export -f print_header print_box spinner progress_bar
|
|
export -f select_menu checkbox_menu confirm
|
|
export -f is_installed install_pacman install_aur install_pkg
|
|
export -f install_packages_parallel install_packages_sequential remove_pkg
|
|
export -f detect_gpu detect_vm is_laptop detect_dm
|
|
export -f run_script backup download git_clone
|
|
export -f print_system_info
|