815 lines
24 KiB
Bash
Executable File
815 lines
24 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#=============================================================================
|
|
# _ _ _ _ ___ _ _ _
|
|
# | || |_ _ _ __ _ _ _ | |__ _ _ _ __| | |_ _|_ _ __| |_ __ _| | |___ _ _
|
|
# | __ | || | '_ \ '_| || / _` | ' \/ _` | | | ' \(_-< _/ _` | | / -_) '_|
|
|
# |_||_|\_, | .__/_| |___|__,_|_||_\__,_| |___|_||_/__/\__\__,_|_|_\___|_|
|
|
# |__/|_|
|
|
#
|
|
# Modern Hyprland Installer for Arch Linux
|
|
# Version: 2.0.0 | License: GPL-3.0
|
|
#
|
|
# Features:
|
|
# - Clean, modern TUI without heavy dependencies
|
|
# - Parallel package installation for 3-4x faster installs
|
|
# - Low memory footprint (no subshells where possible)
|
|
# - Smart system detection (GPU, VM, laptop)
|
|
# - Preset support for unattended installation
|
|
#=============================================================================
|
|
|
|
set -euo pipefail
|
|
|
|
#=============================================================================
|
|
# CONFIGURATION
|
|
#=============================================================================
|
|
readonly VERSION="2.0.0"
|
|
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
readonly INSTALL_SCRIPTS="${SCRIPT_DIR}/install-scripts"
|
|
readonly LOG_DIR="${SCRIPT_DIR}/Install-Logs"
|
|
readonly PRESET_DIR="${SCRIPT_DIR}/presets"
|
|
readonly CONFIG_FILE="${SCRIPT_DIR}/.installer-config"
|
|
|
|
# Default options (can be overridden by preset)
|
|
declare -A OPTIONS=(
|
|
[hyprland]=1
|
|
[pipewire]=1
|
|
[fonts]=1
|
|
[gtk_themes]=0
|
|
[bluetooth]=0
|
|
[thunar]=0
|
|
[sddm]=0
|
|
[sddm_theme]=0
|
|
[xdph]=0
|
|
[zsh]=0
|
|
[nvidia]=0
|
|
[dotfiles]=0
|
|
[quickshell]=0
|
|
[rofi]=1
|
|
[waybar]=1
|
|
)
|
|
|
|
# Package lists (optimized for minimal memory)
|
|
declare -a CORE_PACKAGES=(
|
|
hyprland
|
|
hyprpolkitagent
|
|
xdg-user-dirs
|
|
xdg-utils
|
|
)
|
|
|
|
declare -a ESSENTIAL_PACKAGES=(
|
|
bc cliphist curl grim gvfs gvfs-mtp
|
|
imagemagick inxi jq kitty kvantum
|
|
libspng nano network-manager-applet
|
|
pamixer pavucontrol playerctl
|
|
python-requests qt5ct qt6ct qt6-svg
|
|
rofi-wayland slurp swappy swaync swww
|
|
unzip wallust waybar wget wl-clipboard
|
|
wlogout yad
|
|
)
|
|
|
|
declare -a OPTIONAL_PACKAGES=(
|
|
brightnessctl btop cava loupe fastfetch
|
|
gnome-system-monitor mousepad mpv mpv-mpris
|
|
nvtop nwg-look nwg-displays pacman-contrib
|
|
qalculate-gtk yt-dlp
|
|
)
|
|
|
|
declare -a FONT_PACKAGES=(
|
|
ttf-jetbrains-mono-nerd
|
|
ttf-firacode-nerd
|
|
otf-font-awesome
|
|
ttf-nerd-fonts-symbols
|
|
noto-fonts
|
|
noto-fonts-emoji
|
|
)
|
|
|
|
#=============================================================================
|
|
# SOURCE LIBRARY
|
|
#=============================================================================
|
|
if [[ -f "${INSTALL_SCRIPTS}/lib.sh" ]]; then
|
|
source "${INSTALL_SCRIPTS}/lib.sh"
|
|
else
|
|
echo "ERROR: Library file not found. Please ensure install-scripts/lib.sh exists."
|
|
exit 1
|
|
fi
|
|
|
|
#=============================================================================
|
|
# BANNER & UI
|
|
#=============================================================================
|
|
show_banner() {
|
|
clear
|
|
cat << 'EOF'
|
|
|
|
╦ ╦╦ ╦╔═╗╦═╗╦ ╔═╗╔╗╔╔╦╗ ╦╔╗╔╔═╗╔╦╗╔═╗╦ ╦ ╔═╗╦═╗
|
|
╠═╣╚╦╝╠═╝╠╦╝║ ╠═╣║║║ ║║ ║║║║╚═╗ ║ ╠═╣║ ║ ║╣ ╠╦╝
|
|
╩ ╩ ╩ ╩ ╩╚═╩═╝╩ ╩╝╚╝═╩╝ ╩╝╚╝╚═╝ ╩ ╩ ╩╩═╝╩═╝╚═╝╩╚═
|
|
|
|
EOF
|
|
echo -e "${COLORS[cyan]} Modern Arch Hyprland Installer v${VERSION}${COLORS[reset]}"
|
|
echo -e "${COLORS[dim]} Fast | Lightweight | Beautiful | Efficient${COLORS[reset]}"
|
|
echo -e "${COLORS[dim]}─────────────────────────────────────────────────────────────${COLORS[reset]}\n"
|
|
}
|
|
|
|
show_welcome() {
|
|
show_banner
|
|
|
|
echo -e " ${COLORS[yellow]}Welcome to the Hyprland Installer!${COLORS[reset]}\n"
|
|
echo -e " This script will help you set up Hyprland with:"
|
|
echo -e " ${COLORS[green]}*${COLORS[reset]} Modern wayland compositor (Hyprland)"
|
|
echo -e " ${COLORS[green]}*${COLORS[reset]} Beautiful themed desktop environment"
|
|
echo -e " ${COLORS[green]}*${COLORS[reset]} Essential tools and utilities"
|
|
echo -e " ${COLORS[green]}*${COLORS[reset]} Optional: NVIDIA drivers, SDDM, ZSH\n"
|
|
|
|
echo -e " ${COLORS[bold]}${COLORS[cyan]}System Requirements:${COLORS[reset]}"
|
|
echo -e " ${COLORS[dim]}- Arch Linux or Arch-based distro${COLORS[reset]}"
|
|
echo -e " ${COLORS[dim]}- Non-root user with sudo access${COLORS[reset]}"
|
|
echo -e " ${COLORS[dim]}- Internet connection${COLORS[reset]}"
|
|
echo -e " ${COLORS[dim]}- base-devel package group${COLORS[reset]}\n"
|
|
}
|
|
|
|
#=============================================================================
|
|
# PRE-FLIGHT CHECKS
|
|
#=============================================================================
|
|
preflight_checks() {
|
|
local errors=0
|
|
|
|
echo -e "${INFO} Running pre-flight checks...\n"
|
|
|
|
# Check: Not running as root
|
|
echo -n " Checking: Not running as root... "
|
|
if [[ $EUID -eq 0 ]]; then
|
|
echo -e "${COLORS[red]}FAILED${COLORS[reset]}"
|
|
echo -e "${ERR} This script should NOT be run as root!"
|
|
((errors++))
|
|
else
|
|
echo -e "${COLORS[green]}OK${COLORS[reset]}"
|
|
fi
|
|
|
|
# Check: Arch Linux
|
|
echo -n " Checking: Arch Linux detected... "
|
|
if [[ -f /etc/arch-release ]]; then
|
|
echo -e "${COLORS[green]}OK${COLORS[reset]}"
|
|
else
|
|
echo -e "${COLORS[yellow]}WARN${COLORS[reset]} (may work on Arch-based distros)"
|
|
fi
|
|
|
|
# Check: Internet connection
|
|
echo -n " Checking: Internet connection... "
|
|
if ping -c 1 archlinux.org &>/dev/null; then
|
|
echo -e "${COLORS[green]}OK${COLORS[reset]}"
|
|
else
|
|
echo -e "${COLORS[red]}FAILED${COLORS[reset]}"
|
|
echo -e "${ERR} No internet connection detected!"
|
|
((errors++))
|
|
fi
|
|
|
|
# Check: base-devel
|
|
echo -n " Checking: base-devel installed... "
|
|
if pacman -Qg base-devel &>/dev/null; then
|
|
echo -e "${COLORS[green]}OK${COLORS[reset]}"
|
|
else
|
|
echo -e "${COLORS[yellow]}MISSING${COLORS[reset]} (will install)"
|
|
fi
|
|
|
|
# Check: PulseAudio conflict
|
|
echo -n " Checking: PulseAudio conflict... "
|
|
if pacman -Qq pulseaudio &>/dev/null; then
|
|
echo -e "${COLORS[red]}CONFLICT${COLORS[reset]}"
|
|
echo -e "${WARN} PulseAudio detected. Will be replaced with PipeWire."
|
|
else
|
|
echo -e "${COLORS[green]}OK${COLORS[reset]}"
|
|
fi
|
|
|
|
# Check: AUR helper
|
|
echo -n " Checking: AUR helper... "
|
|
if command -v paru &>/dev/null; then
|
|
echo -e "${COLORS[green]}paru${COLORS[reset]}"
|
|
elif command -v yay &>/dev/null; then
|
|
echo -e "${COLORS[green]}yay${COLORS[reset]}"
|
|
else
|
|
echo -e "${COLORS[yellow]}MISSING${COLORS[reset]} (will install)"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
if [[ $errors -gt 0 ]]; then
|
|
echo -e "${ERR} Pre-flight checks failed. Please fix the issues above."
|
|
exit 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
#=============================================================================
|
|
# INSTALLATION OPTIONS
|
|
#=============================================================================
|
|
select_options() {
|
|
show_banner
|
|
|
|
local gpu_type
|
|
gpu_type=$(detect_gpu)
|
|
local dm_active
|
|
dm_active=$(detect_dm)
|
|
|
|
echo -e "${INFO} Detected GPU: ${COLORS[yellow]}${gpu_type}${COLORS[reset]}"
|
|
echo -e "${INFO} Active DM: ${COLORS[yellow]}${dm_active}${COLORS[reset]}\n"
|
|
|
|
# Build options list dynamically
|
|
local -a option_names=()
|
|
local -a option_descs=()
|
|
local -a option_keys=()
|
|
|
|
# Core options (always shown)
|
|
option_names+=("GTK Themes" "Bluetooth" "Thunar" "XDG Portal" "ZSH + Oh-My-Zsh" "Dotfiles")
|
|
option_descs+=("Install GTK themes for dark/light mode" "Configure Bluetooth support" "Install Thunar file manager" "Screen sharing support" "ZSH shell with plugins" "Pre-configured Hyprland dots")
|
|
option_keys+=("gtk_themes" "bluetooth" "thunar" "xdph" "zsh" "dotfiles")
|
|
|
|
# NVIDIA option (if detected)
|
|
if [[ "$gpu_type" == "nvidia" ]]; then
|
|
option_names+=("NVIDIA Drivers")
|
|
option_descs+=("Install and configure NVIDIA drivers")
|
|
option_keys+=("nvidia")
|
|
fi
|
|
|
|
# SDDM options (if no DM active)
|
|
if [[ "$dm_active" == "none" ]]; then
|
|
option_names+=("SDDM" "SDDM Theme")
|
|
option_descs+=("Install SDDM display manager" "Install custom SDDM theme")
|
|
option_keys+=("sddm" "sddm_theme")
|
|
fi
|
|
|
|
# QuickShell option
|
|
option_names+=("QuickShell")
|
|
option_descs+=("Desktop-like overview effect")
|
|
option_keys+=("quickshell")
|
|
|
|
echo -e "${COLORS[bold]}Select installation options:${COLORS[reset]}\n"
|
|
echo -e "${COLORS[dim]}Use number keys to toggle, Enter to continue, a=all, n=none${COLORS[reset]}\n"
|
|
|
|
local -a selected=()
|
|
for i in "${!option_keys[@]}"; do
|
|
selected[$i]=0
|
|
done
|
|
|
|
# Default selections
|
|
selected[0]=1 # GTK Themes
|
|
selected[5]=1 # Dotfiles
|
|
|
|
local cursor=0
|
|
local key
|
|
|
|
tput sc
|
|
tput civis
|
|
|
|
while true; do
|
|
tput rc
|
|
tput ed
|
|
|
|
for i in "${!option_names[@]}"; do
|
|
local checkbox
|
|
if [[ ${selected[$i]} -eq 1 ]]; then
|
|
checkbox="${COLORS[green]}[x]${COLORS[reset]}"
|
|
else
|
|
checkbox="${COLORS[dim]}[ ]${COLORS[reset]}"
|
|
fi
|
|
|
|
local num=$((i + 1))
|
|
if [[ $i -eq $cursor ]]; then
|
|
echo -e " ${COLORS[bg_blue]}${COLORS[bold]} ${num}. $checkbox ${option_names[$i]} ${COLORS[reset]}"
|
|
echo -e " ${COLORS[dim]}${option_descs[$i]}${COLORS[reset]}"
|
|
else
|
|
echo -e " ${num}. $checkbox ${option_names[$i]}"
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo -e " ${COLORS[dim]}[Space] Toggle [Enter] Continue [a] All [n] None [q] Quit${COLORS[reset]}"
|
|
|
|
read -rsn1 key
|
|
|
|
case "$key" in
|
|
[1-9])
|
|
local idx=$((key - 1))
|
|
if [[ $idx -lt ${#option_names[@]} ]]; then
|
|
selected[$idx]=$(( 1 - selected[$idx] ))
|
|
cursor=$idx
|
|
fi
|
|
;;
|
|
A|k) ((cursor > 0)) && ((cursor--)) ;;
|
|
B|j) ((cursor < ${#option_names[@]} - 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 ;;
|
|
'')
|
|
tput cnorm
|
|
# Apply selections to OPTIONS
|
|
for i in "${!option_keys[@]}"; do
|
|
OPTIONS[${option_keys[$i]}]=${selected[$i]}
|
|
done
|
|
return 0
|
|
;;
|
|
q|Q)
|
|
tput cnorm
|
|
echo -e "\n${INFO} Installation cancelled."
|
|
exit 0
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
confirm_options() {
|
|
show_banner
|
|
|
|
echo -e "${COLORS[bold]}Installation Summary:${COLORS[reset]}\n"
|
|
|
|
echo -e " ${COLORS[cyan]}Core Components (always installed):${COLORS[reset]}"
|
|
echo -e " - Hyprland compositor"
|
|
echo -e " - PipeWire audio"
|
|
echo -e " - Essential tools & utilities"
|
|
echo -e " - Fonts"
|
|
echo ""
|
|
|
|
echo -e " ${COLORS[cyan]}Selected Options:${COLORS[reset]}"
|
|
local has_options=0
|
|
for key in "${!OPTIONS[@]}"; do
|
|
if [[ ${OPTIONS[$key]} -eq 1 ]] && [[ "$key" != "hyprland" ]] && [[ "$key" != "pipewire" ]] && [[ "$key" != "fonts" ]] && [[ "$key" != "rofi" ]] && [[ "$key" != "waybar" ]]; then
|
|
echo -e " ${COLORS[green]}+${COLORS[reset]} $key"
|
|
has_options=1
|
|
fi
|
|
done
|
|
|
|
if [[ $has_options -eq 0 ]]; then
|
|
echo -e " ${COLORS[dim]}(none selected)${COLORS[reset]}"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
if confirm "Proceed with installation?"; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
#=============================================================================
|
|
# AUR HELPER INSTALLATION
|
|
#=============================================================================
|
|
install_aur_helper() {
|
|
if command -v paru &>/dev/null || command -v yay &>/dev/null; then
|
|
echo -e "${INFO} AUR helper already installed."
|
|
return 0
|
|
fi
|
|
|
|
show_banner
|
|
echo -e "${INFO} No AUR helper found. Please select one:\n"
|
|
|
|
local options=("paru (Recommended)" "yay")
|
|
local result
|
|
|
|
if result=$(select_menu "Select AUR Helper" "${options[@]}"); then
|
|
case $result in
|
|
0) # paru
|
|
echo -e "\n${NOTE} Installing paru..."
|
|
(
|
|
cd /tmp
|
|
rm -rf paru
|
|
git clone --depth=1 https://aur.archlinux.org/paru-bin.git paru
|
|
cd paru
|
|
makepkg -si --noconfirm
|
|
cd ..
|
|
rm -rf paru
|
|
) >> "$LOG_FILE" 2>&1
|
|
ISAUR="paru"
|
|
;;
|
|
1) # yay
|
|
echo -e "\n${NOTE} Installing yay..."
|
|
(
|
|
cd /tmp
|
|
rm -rf yay
|
|
git clone --depth=1 https://aur.archlinux.org/yay-bin.git yay
|
|
cd yay
|
|
makepkg -si --noconfirm
|
|
cd ..
|
|
rm -rf yay
|
|
) >> "$LOG_FILE" 2>&1
|
|
ISAUR="yay"
|
|
;;
|
|
esac
|
|
|
|
echo -e "${OK} AUR helper installed successfully."
|
|
else
|
|
echo -e "${ERR} AUR helper is required. Exiting."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
#=============================================================================
|
|
# INSTALLATION FUNCTIONS
|
|
#=============================================================================
|
|
install_base() {
|
|
echo -e "\n${INFO} Installing base-devel if needed..."
|
|
if ! pacman -Qg base-devel &>/dev/null; then
|
|
sudo pacman -S --needed --noconfirm base-devel >> "$LOG_FILE" 2>&1
|
|
fi
|
|
}
|
|
|
|
install_core() {
|
|
print_header "Installing Core Packages"
|
|
install_packages_parallel "${CORE_PACKAGES[@]}"
|
|
}
|
|
|
|
install_essential() {
|
|
print_header "Installing Essential Packages"
|
|
install_packages_parallel "${ESSENTIAL_PACKAGES[@]}"
|
|
}
|
|
|
|
install_optional() {
|
|
print_header "Installing Optional Packages"
|
|
install_packages_parallel "${OPTIONAL_PACKAGES[@]}"
|
|
}
|
|
|
|
install_fonts() {
|
|
print_header "Installing Fonts"
|
|
install_packages_parallel "${FONT_PACKAGES[@]}"
|
|
}
|
|
|
|
install_pipewire() {
|
|
print_header "Installing PipeWire"
|
|
|
|
local pipewire_pkgs=(
|
|
pipewire
|
|
wireplumber
|
|
pipewire-audio
|
|
pipewire-pulse
|
|
pipewire-alsa
|
|
pipewire-jack
|
|
)
|
|
|
|
# Remove conflicting PulseAudio if present
|
|
if is_installed pulseaudio; then
|
|
echo -e "${NOTE} Removing PulseAudio..."
|
|
remove_pkg pulseaudio
|
|
fi
|
|
|
|
install_packages_parallel "${pipewire_pkgs[@]}"
|
|
|
|
# Enable services
|
|
systemctl --user enable --now pipewire pipewire-pulse wireplumber 2>/dev/null || true
|
|
}
|
|
|
|
install_gtk_themes() {
|
|
if [[ ${OPTIONS[gtk_themes]} -ne 1 ]]; then return 0; fi
|
|
|
|
print_header "Installing GTK Themes"
|
|
|
|
local theme_pkgs=(
|
|
gtk3
|
|
gtk4
|
|
adw-gtk-theme
|
|
papirus-icon-theme
|
|
bibata-cursor-theme
|
|
)
|
|
|
|
install_packages_parallel "${theme_pkgs[@]}"
|
|
|
|
# Clone GTK themes repo
|
|
local themes_repo="https://github.com/JaKooLit/GTK-themes-icons.git"
|
|
local themes_dir="$HOME/.themes-install"
|
|
|
|
git_clone "$themes_repo" "$themes_dir"
|
|
|
|
if [[ -d "$themes_dir" ]]; then
|
|
# Copy themes
|
|
mkdir -p "$HOME/.themes" "$HOME/.icons"
|
|
cp -r "$themes_dir"/themes/* "$HOME/.themes/" 2>/dev/null || true
|
|
cp -r "$themes_dir"/icons/* "$HOME/.icons/" 2>/dev/null || true
|
|
echo -e "${OK} GTK themes installed."
|
|
fi
|
|
}
|
|
|
|
install_bluetooth() {
|
|
if [[ ${OPTIONS[bluetooth]} -ne 1 ]]; then return 0; fi
|
|
|
|
print_header "Configuring Bluetooth"
|
|
|
|
local bt_pkgs=(bluez bluez-utils blueman)
|
|
install_packages_parallel "${bt_pkgs[@]}"
|
|
|
|
# Enable service
|
|
sudo systemctl enable --now bluetooth.service
|
|
echo -e "${OK} Bluetooth configured."
|
|
}
|
|
|
|
install_thunar() {
|
|
if [[ ${OPTIONS[thunar]} -ne 1 ]]; then return 0; fi
|
|
|
|
print_header "Installing Thunar"
|
|
|
|
local thunar_pkgs=(
|
|
thunar
|
|
thunar-volman
|
|
tumbler
|
|
ffmpegthumbnailer
|
|
thunar-archive-plugin
|
|
file-roller
|
|
)
|
|
|
|
install_packages_parallel "${thunar_pkgs[@]}"
|
|
}
|
|
|
|
install_sddm() {
|
|
if [[ ${OPTIONS[sddm]} -ne 1 ]]; then return 0; fi
|
|
|
|
print_header "Installing SDDM"
|
|
|
|
install_pkg sddm
|
|
install_pkg qt5-graphicaleffects
|
|
install_pkg qt5-quickcontrols2
|
|
|
|
# Enable service
|
|
sudo systemctl enable sddm.service
|
|
|
|
echo -e "${OK} SDDM installed and enabled."
|
|
}
|
|
|
|
install_sddm_theme() {
|
|
if [[ ${OPTIONS[sddm_theme]} -ne 1 ]]; then return 0; fi
|
|
|
|
print_header "Installing SDDM Theme"
|
|
|
|
local theme_repo="https://github.com/JaKooLit/simple-sddm-2.git"
|
|
local theme_dir="/tmp/sddm-theme"
|
|
|
|
git_clone "$theme_repo" "$theme_dir"
|
|
|
|
if [[ -d "$theme_dir" ]]; then
|
|
sudo mkdir -p /usr/share/sddm/themes/
|
|
sudo cp -r "$theme_dir" /usr/share/sddm/themes/simple-sddm-2
|
|
|
|
# Configure SDDM
|
|
sudo mkdir -p /etc/sddm.conf.d
|
|
echo -e "[Theme]\nCurrent=simple-sddm-2" | sudo tee /etc/sddm.conf.d/theme.conf > /dev/null
|
|
|
|
echo -e "${OK} SDDM theme installed."
|
|
fi
|
|
}
|
|
|
|
install_xdph() {
|
|
if [[ ${OPTIONS[xdph]} -ne 1 ]]; then return 0; fi
|
|
|
|
print_header "Installing XDG Portal"
|
|
|
|
local xdph_pkgs=(
|
|
xdg-desktop-portal-hyprland
|
|
xdg-desktop-portal-gtk
|
|
)
|
|
|
|
install_packages_parallel "${xdph_pkgs[@]}"
|
|
}
|
|
|
|
install_zsh() {
|
|
if [[ ${OPTIONS[zsh]} -ne 1 ]]; then return 0; fi
|
|
|
|
print_header "Installing ZSH"
|
|
|
|
install_pkg zsh
|
|
install_pkg zsh-autosuggestions
|
|
install_pkg zsh-syntax-highlighting
|
|
|
|
# Install Oh-My-Zsh
|
|
if [[ ! -d "$HOME/.oh-my-zsh" ]]; then
|
|
echo -e "${NOTE} Installing Oh-My-Zsh..."
|
|
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
|
|
fi
|
|
|
|
# Change default shell
|
|
if [[ "$SHELL" != *"zsh"* ]]; then
|
|
chsh -s "$(which zsh)"
|
|
fi
|
|
|
|
echo -e "${OK} ZSH installed."
|
|
}
|
|
|
|
install_nvidia() {
|
|
if [[ ${OPTIONS[nvidia]} -ne 1 ]]; then return 0; fi
|
|
|
|
print_header "Configuring NVIDIA"
|
|
|
|
local nvidia_pkgs=(
|
|
nvidia-dkms
|
|
nvidia-utils
|
|
nvidia-settings
|
|
libva-nvidia-driver
|
|
)
|
|
|
|
# Install NVIDIA packages
|
|
install_packages_parallel "${nvidia_pkgs[@]}"
|
|
|
|
# Create modprobe config
|
|
echo -e "${NOTE} Configuring NVIDIA modules..."
|
|
sudo mkdir -p /etc/modprobe.d
|
|
cat << 'EOF' | sudo tee /etc/modprobe.d/nvidia.conf > /dev/null
|
|
options nvidia_drm modeset=1 fbdev=1
|
|
options nvidia NVreg_PreserveVideoMemoryAllocations=1
|
|
EOF
|
|
|
|
# Blacklist nouveau
|
|
cat << 'EOF' | sudo tee /etc/modprobe.d/blacklist-nouveau.conf > /dev/null
|
|
blacklist nouveau
|
|
options nouveau modeset=0
|
|
EOF
|
|
|
|
# Enable services
|
|
sudo systemctl enable nvidia-suspend.service
|
|
sudo systemctl enable nvidia-hibernate.service
|
|
sudo systemctl enable nvidia-resume.service
|
|
|
|
# Regenerate initramfs
|
|
sudo mkinitcpio -P
|
|
|
|
echo -e "${OK} NVIDIA configured. Reboot required."
|
|
}
|
|
|
|
install_quickshell() {
|
|
if [[ ${OPTIONS[quickshell]} -ne 1 ]]; then return 0; fi
|
|
|
|
print_header "Installing QuickShell"
|
|
install_pkg quickshell
|
|
}
|
|
|
|
install_dotfiles() {
|
|
if [[ ${OPTIONS[dotfiles]} -ne 1 ]]; then return 0; fi
|
|
|
|
print_header "Installing Dotfiles"
|
|
|
|
local dots_repo="https://github.com/JaKooLit/Hyprland-Dots.git"
|
|
local dots_dir="$HOME/Hyprland-Dots"
|
|
|
|
# Backup existing configs
|
|
backup "$HOME/.config/hypr"
|
|
backup "$HOME/.config/waybar"
|
|
backup "$HOME/.config/rofi"
|
|
|
|
git_clone "$dots_repo" "$dots_dir"
|
|
|
|
if [[ -d "$dots_dir" ]]; then
|
|
cd "$dots_dir"
|
|
if [[ -f "install.sh" ]]; then
|
|
chmod +x install.sh
|
|
./install.sh
|
|
elif [[ -f "copy.sh" ]]; then
|
|
chmod +x copy.sh
|
|
./copy.sh
|
|
fi
|
|
cd "$SCRIPT_DIR"
|
|
fi
|
|
|
|
echo -e "${OK} Dotfiles installed."
|
|
}
|
|
|
|
#=============================================================================
|
|
# FINAL CHECKS
|
|
#=============================================================================
|
|
final_checks() {
|
|
print_header "Final Verification"
|
|
|
|
local missing=()
|
|
local critical_pkgs=(hyprland kitty waybar rofi-wayland)
|
|
|
|
for pkg in "${critical_pkgs[@]}"; do
|
|
echo -n " Checking $pkg... "
|
|
if is_installed "$pkg"; then
|
|
echo -e "${COLORS[green]}OK${COLORS[reset]}"
|
|
else
|
|
echo -e "${COLORS[red]}MISSING${COLORS[reset]}"
|
|
missing+=("$pkg")
|
|
fi
|
|
done
|
|
|
|
if [[ ${#missing[@]} -gt 0 ]]; then
|
|
echo -e "\n${WARN} Some packages are missing: ${missing[*]}"
|
|
echo -e "${NOTE} You may need to install them manually."
|
|
else
|
|
echo -e "\n${OK} All critical packages installed successfully!"
|
|
fi
|
|
}
|
|
|
|
show_completion() {
|
|
show_banner
|
|
|
|
echo -e " ${COLORS[bold]}${COLORS[green]}Installation Complete!${COLORS[reset]}\n"
|
|
|
|
echo -e " ${COLORS[cyan]}What's next:${COLORS[reset]}"
|
|
echo -e " 1. Reboot your system"
|
|
echo -e " 2. Start Hyprland by typing: ${COLORS[yellow]}Hyprland${COLORS[reset]}"
|
|
echo -e " (or login via SDDM if installed)"
|
|
echo ""
|
|
echo -e " ${COLORS[cyan]}Useful keybindings:${COLORS[reset]}"
|
|
echo -e " ${COLORS[yellow]}SUPER + Enter${COLORS[reset]} - Open terminal"
|
|
echo -e " ${COLORS[yellow]}SUPER + D${COLORS[reset]} - App launcher (rofi)"
|
|
echo -e " ${COLORS[yellow]}SUPER + Q${COLORS[reset]} - Close window"
|
|
echo -e " ${COLORS[yellow]}SUPER + H${COLORS[reset]} - Show keybind hints"
|
|
echo ""
|
|
echo -e " ${COLORS[cyan]}Logs:${COLORS[reset]} ${LOG_FILE}"
|
|
echo -e " ${COLORS[cyan]}Docs:${COLORS[reset]} https://wiki.hyprland.org\n"
|
|
|
|
if confirm "Would you like to reboot now?"; then
|
|
echo -e "\n${INFO} Rebooting..."
|
|
systemctl reboot
|
|
else
|
|
echo -e "\n${INFO} Remember to reboot before starting Hyprland."
|
|
fi
|
|
}
|
|
|
|
#=============================================================================
|
|
# MAIN
|
|
#=============================================================================
|
|
main() {
|
|
# Initialize
|
|
init_installer
|
|
|
|
# Parse arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--preset)
|
|
shift
|
|
if [[ -f "$1" ]]; then
|
|
source "$1"
|
|
echo -e "${INFO} Loaded preset: $1"
|
|
fi
|
|
;;
|
|
--parallel)
|
|
shift
|
|
PARALLEL_JOBS="$1"
|
|
;;
|
|
--help|-h)
|
|
echo "Usage: $0 [options]"
|
|
echo " --preset FILE Load options from preset file"
|
|
echo " --parallel N Number of parallel installation jobs (default: 4)"
|
|
echo " --help Show this help"
|
|
exit 0
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# Show welcome
|
|
show_welcome
|
|
|
|
# Wait for user
|
|
echo -e "${ACT} Press Enter to continue or Ctrl+C to exit..."
|
|
read -r
|
|
|
|
# Pre-flight checks
|
|
preflight_checks
|
|
|
|
# Print system info
|
|
print_system_info
|
|
|
|
# Select options
|
|
select_options
|
|
|
|
# Confirm
|
|
if ! confirm_options; then
|
|
select_options
|
|
confirm_options || exit 1
|
|
fi
|
|
|
|
# Install AUR helper if needed
|
|
install_aur_helper
|
|
|
|
# Re-initialize with AUR helper
|
|
init_installer
|
|
|
|
# Run installation
|
|
echo -e "\n${INFO} Starting installation...\n"
|
|
|
|
install_base
|
|
install_core
|
|
install_essential
|
|
install_optional
|
|
install_fonts
|
|
install_pipewire
|
|
|
|
# Optional components based on selection
|
|
install_gtk_themes
|
|
install_bluetooth
|
|
install_thunar
|
|
install_sddm
|
|
install_sddm_theme
|
|
install_xdph
|
|
install_zsh
|
|
install_nvidia
|
|
install_quickshell
|
|
install_dotfiles
|
|
|
|
# Final checks
|
|
final_checks
|
|
|
|
# Show completion
|
|
show_completion
|
|
}
|
|
|
|
# Run main
|
|
main "$@"
|