#!/usr/bin/env bash ## ┏━┃┃┏━┛┏━┛ ┃┏━ ┏━┛━┏┛┏━┃┃ ┃ ┏━┛┏━┃ ## ┏┏┛┃┃ ┏━┛ ┃┃ ┃━━┃ ┃ ┏━┃┃ ┃ ┏━┛┏┏┛ ## ┛ ┛┛━━┛━━┛ ┛┛ ┛━━┛ ┛ ┛ ┛━━┛━━┛━━┛┛ ┛ # Script to install my dotfiles MER=$(tput setaf 1) # Red KUN=$(tput setaf 3) # Yellow HIJ=$(tput setaf 2) # Green BRU=$(tput setaf 4) # Blue BLD=$(tput bold) # Bold RST=$(tput sgr0) # Reset colors # Global vars backup_folder=~/.RiceBackup ERROR_LOG="$HOME/RiceError.log" logo () { local text="${1:?}" echo -en " *** **,** //(,***//. /**,,,/,,,,,,,.*/, *(,,.(/,,,(,,,,....#( .*..(@#@%(.(#( .... .*/ ,*,(%(%&@%@@@@&(... .@ ##@@......@@@@.. .,, (/ @@@@@@@@@@@@.&/*% *,%* .#** @@&@@@@@@@@@%&& . ** ( . , %@@@@@(//& **& //,/ %&@&&&&/&&,,,, # ,# (##(##/&&&&&&*,,,. .(//( %//,, ((///&&&((. ............// /, /...../&/&&(,........ ..... . *(/ //....... #... ................ ,. ((.. ..... . ................ / adilhyz Dotfiles\n\n" printf ' %s [%s%s %s%s %s]%s\n\n' "${MER}" "${RST}" "${KUN}" "${text}" "${RST}" "${MER}" "${RST}" } # Handle errors log_error() { local error_msg="$1" local timestamp=$(date +"%Y-%m-%d %H:%M:%S") echo "[${timestamp}] ERROR: ${error_msg}" >> "$ERROR_LOG" printf "%s%sERROR:%s %s\n" "${MER}" "${BLD}" "${RST}" "${error_msg}" >&2 } is_installed() { pacman -Qq "$1" >/dev/null 2>&1 } home_dir=$HOME current_dir=$(pwd) # Verificaciones iniciales initial_checks() { # Verificar usuario root if [ "$(id -u)" = 0 ]; then log_error "This script MUST NOT be run as root user." exit 1 fi # Verificar directorio HOME if [ "$PWD" != "$HOME" ]; then log_error "The script must be executed from HOME directory." exit 1 fi # Verificar conexión a internet if ! ping -q -c 1 -W 1 8.8.8.8 &>/dev/null; then log_error "No internet connection detected." exit 1 fi } welcome() { logo "Welcome $USER" printf "%b" "${BLD}${HIJ}This script will install my dotfiles and this is what it will do:${RST} ${BLD}${HIJ}[${KUN}i${HIJ}]${RST} Check necessary dependencies and install them ${BLD}${HIJ}[${KUN}i${HIJ}]${RST} Download my dotfiles in ${HOME}/dotfiles-v1 ${BLD}${HIJ}[${KUN}i${HIJ}]${RST} Backup of possible existing configurations (bspwm, polybar, etc...) ${BLD}${HIJ}[${KUN}i${HIJ}]${RST} Install my configuration ${BLD}${HIJ}[${KUN}i${HIJ}]${RST} Enabling MPD service (Music player daemon) ${BLD}${HIJ}[${KUN}i${HIJ}]${RST} Change your shell to zsh shell ${BLD}${HIJ}[${MER}!${HIJ}]${RST} ${BLD}${MER}My dotfiles DO NOT modify any of your system configurations${RST} ${BLD}${HIJ}[${MER}!${HIJ}]${RST} ${BLD}${MER}This script does NOT have the potential power to break your system${RST}" local yn while true; do read -rp " ${BLD}${HIJ}Do you wish to continue?${RST} [y/N]: " yn case "${yn,,}" in y|yes) return 0 ;; n|no|"") echo -e "\n${BLD}${KUN}Operation cancelled${RST}" exit 0 ;; *) echo -e "\n${BLD}${MER}Error:${RST} Just write '${BLD}${KUN}y${RST}' or '${BLD}${KUN}n${RST}'\n" ;; esac done } add_adilhyz_repo() { clear logo "Add adilhyz custom repo" repo="adilhyz-repo" sleep 2 # Mensaje de instalación del repositorio printf "%b\n" "${BLD}${KUN}Installing ${BRU}${repo}${KUN} repository...${RST}" # Verificar si ya existe la sección en pacman.conf if ! grep -q "\[${repo}\]" /etc/pacman.conf; then # Agregar repo al final del archivo if printf "\n[%s]\nSigLevel = Optional TrustAll\nServer = http://adilhyz.github.io/adilhyz-repo/x86_64\n" "$repo" \ | sudo tee -a /etc/pacman.conf >/dev/null 2>> "$ERROR_LOG"; then printf "\n%b\n" "${BLD}${KUN}${repo} ${HIJ}repository added successfully!${RST}" # Actualizar bases de datos if ! sudo pacman -Syy 2>&1 | tee -a "$ERROR_LOG" >/dev/null; then log_error "Database update failed" return 1 fi else log_error "Error adding repository - check permissions" return 1 fi else printf "\n%b\n" "${BLD}${KUN}The repository already exists and is configured${RST}" sleep 2 return 0 fi } install_dependencies() { clear logo "Installing needed packages.." sleep 2 # List of dependencies dependencies=(alacritty base-devel bspwm bat blueberry brightnessctl clipcat dunst eza fd feh fzf ffmpegthumbnailer geany git jgmenu jq kitty libwebp lazygit lxappearance maim mpc mpd mpv ncmpcpp ntfs-3g numlockx pamixer pacman-contrib pandoc-cli picom playerctl polybar polkit-gnome redshift ripgrep rofi rofi-emoji rustup sxhkd stalonetray thunar thunar-archive-plugin thunar-media-tags-plugin thunar-volman tmux tree ttf-inconsolata ttf-jetbrains-mono ttf-jetbrains-mono-nerd ttf-terminus-nerd tumbler ueberzugpp unclutter webp-pixbuf-loader xclip xcolor xdg-user-dirs xdo xdotool xorg-xdpyinfo xorg-xinit xorg-xkill xorg-xprop xorg-xrandr xorg-xsetroot xorg-xwininfo xsettingsd xss-lock yazi zsh zsh-autosuggestions zsh-history-substring-search zsh-syntax-highlighting) printf "\n%b\n\n" "${BLD}${BRU}Checking for required packages...${RST}" sleep 2 # Detect missing packages local missing_pkgs=() for pkg in "${dependencies[@]}"; do if ! is_installed "$pkg"; then missing_pkgs+=("$pkg") echo -e " ${BLD}${KUN}${pkg} ${MER}not installed${RST}" else echo -e "${BLD}${HIJ}${pkg} ${BRU}already installed${RST}" fi done # Batch installation if ((${#missing_pkgs[@]} > 0)); then echo -e "\n${BLD}${KUN}Installing ${#missing_pkgs[@]} packages...${RST}\n" if sudo pacman -S --noconfirm --needed "${missing_pkgs[@]}" >> "$ERROR_LOG" 2>&1; then # Verify complete installation local failed_pkgs=() for pkg in "${missing_pkgs[@]}"; do if ! is_installed "$pkg"; then failed_pkgs+=("$pkg") log_error "Failed to install: $pkg" fi done # Show final results if ((${#failed_pkgs[@]} == 0)); then echo -e "${BLD}${HIJ}All packages installed successfully!${RST}\n\n" else echo -e "${BLD}${MER}Failed to install ${#failed_pkgs[@]} packages:${RST}\n" echo -e " ${BLD}${KUN}${failed_pkgs[*]}${RST}\n\n" fi else log_error "Critical error during batch installation" echo -e "${BLD}${MER}Installation failed! Check log for details${RST}\n" return 1 fi else echo -e "\n${BLD}${HIJ}All dependencies are already installed!${RST}" fi sleep 3 } install_adilhyz_dependencies() { clear logo "Installing needed packages from adilhyz repository..." sleep 2 # List of dependencies adilhyz_dependencies="adilhyz-icons adilhyz-themes adilhyz-cursors" printf "%b\n\n" "${BLD}${BRU}Checking for required packages...${RST}" sleep 2 # Detect missing packages missing_adilhyz_repo="" for pkg in $adilhyz_dependencies; do if ! is_installed "$pkg"; then missing_adilhyz_repo="$missing_adilhyz_repo $pkg" printf "%b\n" " ${BLD}${KUN}$pkg ${MER}not installed${RST}" else printf "%b\n" "${BLD}${HIJ}$pkg ${BRU}already installed${RST}" fi done # Batch installation if needed if [ -n "$(printf "%s" "$missing_adilhyz_repo" | tr -s ' ')" ]; then count=$(printf "%s" "$missing_adilhyz_repo" | wc -w) printf "\n%b\n\n" "${BLD}${KUN}Installing $count packages, please wait...${RST}" if sudo pacman -S --noconfirm $missing_adilhyz_repo 2>&1 | tee -a "$ERROR_LOG" >/dev/null; then # Verify complete installation failed_adilhyz_repo="" for pkg in $missing_adilhyz_repo; do if ! is_installed "$pkg"; then failed_adilhyz_repo="$failed_adilhyz_repo $pkg" log_error "Failed to install: $pkg" fi done # Show final results if [ -z "$(printf "%s" "$failed_adilhyz_repo" | tr -s ' ')" ]; then printf "%b\n\n" "${BLD}${HIJ}All packages installed successfully!${RST}" else fail_count=$(printf "%s" "$failed_adilhyz_repo" | wc -w) printf "%b\n" "${BLD}${MER}Failed to install $fail_count packages:${RST}" printf "%b\n\n" " ${BLD}${KUN}$(printf "%s" "$failed_adilhyz_repo")${RST}" fi else log_error "Critical error during batch installation" printf "%b\n" "${BLD}${MER}Installation failed! Check log for details${RST}" return 1 fi else printf "\n%b\n" "${BLD}${HIJ}All dependencies are already installed!${RST}" fi sleep 2 } clone_dotfiles() { clear logo "Downloading dotfiles" local repo_url="https://github.com/adilhyz/dotfiles-v1" local repo_dir="$HOME/dotfiles-v1" local timestamp=$(date +%Y%m%d-%H%M%S) sleep 3 # Handle existing repository if [[ -d "$repo_dir" ]]; then local backup_dir="${repo_dir}_${timestamp}" echo -en "${BLD}${KUN}Existing repository found - renaming to: ${BRU}${backup_dir}${RST}\n" if ! mv -v "$repo_dir" "$backup_dir" >> "$ERROR_LOG" 2>&1; then log_error "Failed to rename existing repository" echo -en "${BLD}${MER}Renaming failed! Check${KUN}RiceError.log${RST}\n" return 1 fi echo -en "${BLD}${HIJ}Repository successfully renamed for backup${RST}\n\n" fi # Clone new repository echo -en "${BLD}${KUN}Cloning dotfiles from: ${BRU}${repo_url}${RST}\n" if git clone --recurse-submodules --depth=1 "$repo_url" "$repo_dir" >> "$ERROR_LOG" 2>&1; then echo -en "${BLD}${HIJ}Dotfiles cloned successfully!${RST}\n\n" else log_error "Repository clone failed" echo -en "${BLD}${MER}Clone failed! Check ${KUN}RiceError.log${RST}\n" return 1 fi sleep 3 } backup_existing_config() { clear logo "Backup files" printf "Backup files will be stored in %s%s%s/.RiceBackup%s \n\n" "${BLD}" "${MER}" "$HOME" "${RST}" sleep 2 # Create backup directory mkdir -p "$backup_folder" 2>> "$ERROR_LOG" echo -en "\n${BLD}${KUN}Backup directory: ${BRU}${backup_folder}${RST}\n\n" sleep 2 # Generic backup function backup_item() { local type=$1 path=$2 target=$3 local base_name=$(basename "$path") if [ -$type "$path" ]; then if mv "$path" "$backup_folder/${target}_${date}" 2>> "$ERROR_LOG"; then echo -en "${BLD}${HIJ}${base_name} ${BRU}backup successful${RST}\n" else log_error "Error backup: $base_name" echo -en "${BLD}${MER}${base_name} ${KUN}backup failed${RST}\n" fi sleep 0.5 else echo -en "${BLD}${KUN}${base_name} ${BRU}not found${RST}\n" sleep 0.3 fi } # Backup of main configurations local config_folders=(bspwm alacritty clipcat picom rofi eww sxhkd dunst kitty polybar geany cava ncmpcpp nvim neofetch yazi Thunar tmux zsh mpd paru) for folder in "${config_folders[@]}"; do backup_item d "$HOME/.config/$folder" "$folder" done # Backup of individual files local single_files=("$HOME/.zshrc") for item in "${single_files[@]}"; do if [[ "$item" == *".zshrc" ]]; then backup_item d "$item" ".zshrc" else backup_item f "$item" "$(basename "$item")" fi done echo -en "\n${BLD}${HIJ}Backup completed!${RST}\n\n" sleep 3 } install_dotfiles() { clear logo "Installing dotfiles.." printf "Copying files to respective directories..\n" # Create required directories local required_dirs=("$HOME/.config" "$HOME/.local/bin" "$HOME/.local/share") for dir in "${required_dirs[@]}"; do if [ ! -d "$dir" ]; then mkdir -p "$dir" 2>> "$ERROR_LOG" && \ echo -en "${BLD}${HIJ}Created directory: ${BRU}${dir}${RST}\n" fi done # Generic function to copy files copy_files() { local source="$1" local target="$2" local item_name=$(basename "$source") if cp -R "$source" "$target" 2>> "$ERROR_LOG"; then echo -en "${BLD}${KUN}${item_name} ${HIJ}copied successfully!${RST}\n" return 0 else log_error "Failed to copy: $item_name" echo -en "${BLD}${KUN}${item_name} ${MER}copy failed!${RST}\n" return 1 fi } local config_source="$HOME/dotfiles-v1/config" for config_dir in "$config_source"/*; do local dir_name=$(basename "$config_dir") # Skip neovim if the user doesn't want it [[ "$dir_name" == "nvim" && "$try_nvim" != "y" ]] && continue copy_files "$config_dir" "$HOME/.config/" sleep 0.3 done # Copy miscellaneous components local misc_items=("applications" "asciiart" "fonts" "bin") for item in "${misc_items[@]}"; do local source_path="$HOME/dotfiles-v1/misc/$item" local target_path="$HOME/.local/share/" [[ "$item" == "bin" ]] && target_path="$HOME/.local/" copy_files "$source_path" "$target_path" sleep 0.3 done # Copy remaining files local home_files=("$HOME/dotfiles-v1/home/.zshrc") for file in "${home_files[@]}"; do copy_files "$file" "$HOME/" done # Update font cache if fc-cache -rv >/dev/null 2>&1; then echo -en "\n${BLD}${HIJ}Font cache updated successfully!${RST}\n" else log_error "Failed to update font cache" fi # Generate xdg dirs if [[ ! -e "$HOME/.config/user-dirs.dirs" ]]; then if xdg-user-dirs-update >/dev/null 2>&1; then echo -en "${BLD}${HIJ}Xdg dirs generated successfully!${RST}\n" else log_error "Failed to generate xdg dirs" fi fi echo -en "\n${BLD}${HIJ}Dotfiles installed successfully!${RST}\n" sleep 3 } #ngke install_aur() { clear logo "Installing AUR dependencies." sleep 2 logo "installing Yay, Paru, Adilhyz-repo (Needed), Neofetch, Xwinwrap, i3lock, Eww, Fzf-tab, Cpuid, & xqp" if ! command -v yay >/dev/null 2>&1; then printf "%s%sInstalling yay%s\n" "${BLD}" "${BRU}" "${RST}" cd git clone https://aur.archlinux.org/yay.git cd yay makepkg -si --noconfirm cd else printf "%s%sYay is already installed%s\n" "${BLD}" "${HIJ}" "${RST}" fi if ! command -v paru >/dev/null 2>&1; then printf "%s%sInstalling paru%s\n" "${BLD}" "${BRU}" "${RST}" cd git clone https://aur.archlinux.org/paru-bin.git cd paru-bin makepkg -si --noconfirm cd else printf "%s%sParu is already installed%s\n" "${BLD}" "${HIJ}" "${RST}" fi if ! command -v neofetch >/dev/null 2>&1; then printf "\n%s%sInstalling Neofetch for fetch your systems.%s\n" "${BLD}" "${BRU}" "${RST}" paru -S neofetch-git --skipreview --noconfirm --needed fi if ! command -v xwinwrap-0.9-bin >/dev/null 2>&1; then printf "\n%s%sInstalling xwinwrap Animated Wallpaper Engine.%s\n" "${BLD}" "${BRU}" "${RST}" paru -S xwinwrap-0.9-bin --skipreview --noconfirm --needed fi if ! command -v i3lock-color >/dev/null 2>&1; then printf "\n%s%sInstalling i3lock Lockscreen.%s\n" "${BLD}" "${BRU}" "${RST}" paru -S i3lock-color --skipreview --noconfirm --needed fi if ! command -v cava >/dev/null 2>&1; then printf "\n%s%sInstalling cava Visualizer.%s\n" "${BLD}" "${BRU}" "${RST}" paru -S cava --skipreview --noconfirm --needed fi # Intalling xqp if command -v xqp >/dev/null 2>&1; then printf "\n%s%sxqp is already installed%s\n" "${BLD}" "${HIJ}" "${RST}" else printf "\n%s%sInstalling xqp, this should be fast!%s\n" "${BLD}" "${BRU}" "${RST}" paru -S xqp --skipreview --noconfirm --needed fi # Installing Fzf-tab if pacman -Qq fzf-tab-git >/dev/null 2>&1; then printf "\n%s%sFzf-tab is already installed%s\n" "${BLD}" "${HIJ}" "${RST}" else printf "\n%s%sInstalling Fzf-tab, this should be fast!%s\n" "${BLD}" "${BRU}" "${RST}" paru -S fzf-tab-git --skipreview --noconfirm --needed fi # Installing Cpuid if pacman -Qq cpuid >/dev/null 2>&1; then printf "\n%s%sCpuid is already installed%s\n" "${BLD}" "${HIJ}" "${RST}" else printf "\n%s%sInstalling Cpuid, this should be fast%s\n" "${BLD}" "${BRU}" "${RST}" paru -S cpuid --skipreview --noconfirm --needed fi # Installing Eww if pacman -Qq eww-git >/dev/null 2>&1; then printf "\n%s%sEww is already installed%s\n" "${BLD}" "${HIJ}" "${RST}" else printf "\n%s%sInstalling Eww, this will take some time.. !%s\n" "${BLD}" "${BRU}" "${RST}" paru -S eww-git --skipreview --noconfirm --needed fi } configure_services() { clear logo "Configuring Services" sleep 2 # MPD Service Management if systemctl is-enabled --quiet mpd.service; then printf "%s%sDisabling global MPD service...%s\n" "${BLD}" "${KUN}" "${RST}" if sudo systemctl disable --now mpd.service >> "$ERROR_LOG" 2>&1; then echo -en "${BLD}${HIJ}Global MPD service disabled successfully${RST}" else log_error "Failed to disable global MPD service" echo -en "${BLD}${MER}Failed to disable global MPD service${RST}\n\n" fi fi # User-level MPD Service echo -en "${BLD}${KUN}Enabling user MPD service...${RST}\n" if systemctl --user enable --now mpd.service >> "$ERROR_LOG" 2>&1; then echo -en "${BLD}${HIJ}User MPD service activated successfully${RST}\n\n" else log_error "Failed to enable user MPD service" echo -en "${BLD}${MER}Failed to activate user MPD service${RST}\n\n" fi } change_default_shell() { clear logo "Changing default shell to zsh" local zsh_path=$(which zsh) sleep 3 if [[ -z "$zsh_path" ]]; then log_error "Zsh binary not found" echo -en "${BLD}${MER}Zsh is not installed! Cannot change shell${RST}\n\n" return 1 fi if [[ "$SHELL" != "$zsh_path" ]]; then echo -en "${BLD}${KUN}Changing your shell to Zsh...${RST}\n" if chsh -s "$zsh_path" 2> >(tee -a "$ERROR_LOG"); then echo -en "\n${BLD}${HIJ}Shell changed successfully!${RST}\n" else log_error "Failed to change shell to Zsh" echo -en "\n${BLD}${MER}Error changing shell! ${KUN}Check RiceError.log${RST}\n\n" fi else echo -en "${BLD}${HIJ}Zsh is already your default shell!${RST}\n\n" fi sleep 3 } final_prompt() { clear logo "Installation Complete" sleep 2 echo -en "${BLD}${HIJ}Installation completed successfully!${RST}\n" echo -en "${BLD}${MER}You ${BRU}MUST ${MER}restart your system to apply changes${RST}\n\n" while true; do read -rp " ${BLD}${KUN}Reboot now?${RST} [y/N]: " yn case "${yn,,}" in y|yes) echo -en "\n${BLD}${HIJ}Initiating reboot...${RST}\n" sleep 2 if ! sudo reboot >> "$ERROR_LOG" 2>&1; then log_error "Failed to trigger reboot" echo -en "${BLD}${MER}Reboot failed! Execute manually${RST}\n" fi exit 0 ;; n|no|"") echo -en "\n${BLD}${KUN}Remember to reboot later!${RST}\n\n" zsh exit 0 ;; *) echo -en "\n${BLD}${MER}Invalid choice - use '${KUN}y${MER}' or '${KUN}n${MER}'${RST}\n\n" sleep 1 ;; esac done } # --- Main run --- # initial_checks welcome add_adilhyz_repo install_dependencies install_adilhyz_dependencies clone_dotfiles backup_existing_config install_dotfiles install_aur configure_services change_default_shell final_prompt