2022-09-08 21:45:44 +02:00
|
|
|
#!/bin/bash
|
2022-08-11 11:22:22 +02:00
|
|
|
|
2022-09-13 14:29:13 +02:00
|
|
|
######################################################################
|
|
|
|
# 🧰 Lissy93/Dotfiles - All-in-One Install and Setup Script for Unix #
|
|
|
|
######################################################################
|
|
|
|
# Fetches latest changes, symlinks files, and installs dependencies #
|
|
|
|
# Then sets up ZSH, TMUX, Vim as well as OS-specific tools and apps #
|
|
|
|
# For docs and more info, see: https://github.com/lissy93/dotfiles #
|
|
|
|
# #
|
|
|
|
# IMPORTANT: Before running, read through everything very carefully! #
|
|
|
|
# #
|
|
|
|
# Licensed under MIT (C) Alicia Sykes 2022 <https://aliciasykes.com> #
|
|
|
|
######################################################################
|
2022-08-11 11:22:22 +02:00
|
|
|
|
|
|
|
# Configuration Params
|
2022-09-13 14:29:13 +02:00
|
|
|
REPO_NAME="${REPO_NAME:-Lissy93/Dotfiles}"
|
2022-03-12 20:27:04 +01:00
|
|
|
REPO_PATH="https://github.com/${REPO_NAME}.git"
|
2022-09-13 14:29:13 +02:00
|
|
|
SYMLINK_FILE="${SYMLINK_FILE:-symlinks.yaml}"
|
2022-03-12 20:27:04 +01:00
|
|
|
DOTBOT_DIR="dotbot"
|
|
|
|
DOTBOT_BIN="bin/dotbot"
|
2022-08-15 00:20:38 +02:00
|
|
|
CURRENT_DIR=$(cd "$(dirname ${BASH_SOURCE[0]})" && pwd)
|
2022-08-03 12:56:36 +02:00
|
|
|
DOTFILES_DIR="${DOTFILES_DIR:-$HOME/Documents/config/dotfiles}"
|
2022-09-13 14:29:13 +02:00
|
|
|
TITLE="🧰 ${REPO_NAME} Setup"
|
2022-03-09 23:10:48 +01:00
|
|
|
|
|
|
|
# Color Variables
|
|
|
|
CYAN_B='\033[1;96m'
|
|
|
|
YELLOW_B='\033[1;93m'
|
|
|
|
RED_B='\033[1;31m'
|
|
|
|
GREEN_B='\033[1;32m'
|
|
|
|
PLAIN_B='\033[1;37m'
|
|
|
|
RESET='\033[0m'
|
2022-08-30 18:39:35 +02:00
|
|
|
GREEN='\033[0;32m'
|
2022-08-07 17:58:57 +02:00
|
|
|
PURPLE='\033[0;35m'
|
2022-03-09 23:10:48 +01:00
|
|
|
|
2022-08-28 23:10:28 +02:00
|
|
|
# Other params
|
|
|
|
PROMPT_TIMEOUT=15 # When user is prompted for input, skip after x seconds
|
|
|
|
|
2022-03-09 23:10:48 +01:00
|
|
|
# Start timer
|
|
|
|
start_time=`date +%s`
|
|
|
|
|
|
|
|
# Get system type - Linux / MacOS (Darwin)
|
|
|
|
system_type=$(uname -s)
|
|
|
|
|
|
|
|
# Function that prints important text in a banner with colored border
|
|
|
|
# First param is the text to output, then optional color and padding
|
2022-08-06 12:39:28 +02:00
|
|
|
make_banner () {
|
2022-03-09 23:10:48 +01:00
|
|
|
bannerText=$1
|
|
|
|
lineColor="${2:-$CYAN_B}"
|
|
|
|
padding="${3:-0}"
|
|
|
|
titleLen=$(expr ${#bannerText} + 2 + $padding);
|
|
|
|
lineChar="─"; line=""
|
|
|
|
for (( i = 0; i < "$titleLen"; ++i )); do line="${line}${lineChar}"; done
|
|
|
|
banner="${lineColor}╭${line}╮\n│ ${PLAIN_B}${bannerText}${lineColor} │\n╰${line}╯"
|
|
|
|
echo -e "\n${banner}\n${RESET}"
|
|
|
|
}
|
2021-01-31 21:45:12 +01:00
|
|
|
|
2021-02-08 16:26:59 +01:00
|
|
|
# Checks if a given package is installed
|
|
|
|
command_exists () {
|
|
|
|
hash "$1" 2> /dev/null
|
|
|
|
}
|
|
|
|
|
2022-08-11 11:22:22 +02:00
|
|
|
# On error, displays death banner, and terminates app with exit code 1
|
2022-03-09 23:10:48 +01:00
|
|
|
terminate () {
|
|
|
|
make_banner "Installation failed. Terminating..." ${RED_B}
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
|
|
|
|
# Checks if command / package (in $1) exists and then shows
|
2022-08-30 18:39:35 +02:00
|
|
|
# either shows a warning or error, depending if package required ($2)
|
2021-02-08 16:26:59 +01:00
|
|
|
system_verify () {
|
|
|
|
if ! command_exists $1; then
|
2022-03-09 23:10:48 +01:00
|
|
|
if $2; then
|
2022-03-12 20:27:04 +01:00
|
|
|
echo -e "🚫 ${RED_B}Error:${PLAIN_B} $1 is not installed${RESET}"
|
2022-03-09 23:10:48 +01:00
|
|
|
terminate
|
|
|
|
else
|
2022-03-12 20:27:04 +01:00
|
|
|
echo -e "⚠️ ${YELLOW_B}Warning:${PLAIN_B} $1 is not installed${RESET}"
|
2022-03-09 23:10:48 +01:00
|
|
|
fi
|
2021-02-08 16:26:59 +01:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2022-08-11 11:22:22 +02:00
|
|
|
# Prints welcome banner, verifies that requirements are met
|
2022-08-10 13:07:57 +02:00
|
|
|
function pre_setup_tasks () {
|
|
|
|
# Show starting banner
|
|
|
|
make_banner "${TITLE}" "${CYAN_B}" 1
|
|
|
|
|
|
|
|
# Verify required packages are installed
|
|
|
|
system_verify "git" true
|
|
|
|
system_verify "zsh" false
|
|
|
|
system_verify "vim" false
|
|
|
|
system_verify "nvim" false
|
|
|
|
system_verify "tmux" false
|
|
|
|
}
|
|
|
|
|
2022-08-11 11:22:22 +02:00
|
|
|
# Downloads / updates dotfiles and symlinks them
|
2022-08-10 13:07:57 +02:00
|
|
|
function setup_dot_files () {
|
|
|
|
|
|
|
|
# Download / update dotfiles repo with git
|
|
|
|
if [[ ! -d "$DOTFILES_DIR" ]]
|
|
|
|
then
|
2022-08-29 00:15:42 +02:00
|
|
|
echo -e "${PURPLE}Dotfiles not yet present. Will download ${REPO_NAME} into ${DOTFILES_DIR}${RESET}"
|
2022-08-10 13:07:57 +02:00
|
|
|
mkdir -p "${DOTFILES_DIR}"
|
|
|
|
git clone --recursive ${REPO_PATH} ${DOTFILES_DIR}
|
|
|
|
else
|
2022-08-29 00:15:42 +02:00
|
|
|
echo -e "${PURPLE}Pulling changes from ${REPO_NAME} into ${DOTFILES_DIR}${RESET}"
|
2022-08-28 23:10:28 +02:00
|
|
|
cd "${DOTFILES_DIR}" && git pull origin master && git submodule update --recursive
|
2022-08-10 13:07:57 +02:00
|
|
|
fi
|
|
|
|
|
|
|
|
# If git clone / pull failed, then exit with error
|
|
|
|
ret=$?
|
|
|
|
if ! test "$ret" -eq 0
|
|
|
|
then
|
2022-08-11 11:22:22 +02:00
|
|
|
echo >&2 "${RED_B}Failed to fetch dotfiels $ret${RESET}"
|
|
|
|
terminate
|
2022-08-10 13:07:57 +02:00
|
|
|
fi
|
|
|
|
|
|
|
|
# Set up symlinks with dotbot
|
2022-08-29 00:15:42 +02:00
|
|
|
echo -e "${PURPLE}Setting up Symlinks${RESET}"
|
2022-08-10 13:07:57 +02:00
|
|
|
cd "${DOTFILES_DIR}"
|
|
|
|
git -C "${DOTBOT_DIR}" submodule sync --quiet --recursive
|
|
|
|
git submodule update --init --recursive "${DOTBOT_DIR}"
|
|
|
|
chmod +x dotbot/bin/dotbot
|
2022-09-13 14:29:13 +02:00
|
|
|
"${DOTFILES_DIR}/${DOTBOT_DIR}/${DOTBOT_BIN}" -d "${DOTFILES_DIR}" -c "${SYMLINK_FILE}" "${@}"
|
2022-08-10 13:07:57 +02:00
|
|
|
}
|
|
|
|
|
2022-08-28 23:10:28 +02:00
|
|
|
# Applies application-specific preferences, and runs some setup tasks
|
|
|
|
function apply_preferences () {
|
|
|
|
|
|
|
|
# If ZSH not the default shell, ask user if they'd like to set it
|
|
|
|
if [[ $SHELL != *"zsh"* ]] && command_exists zsh; then
|
2022-08-29 00:15:42 +02:00
|
|
|
read -t $PROMPT_TIMEOUT -p "$(echo -e $CYAN_B)Would you like to set ZSH as your default shell? (y/N)" -n 1 -r
|
2022-08-28 23:10:28 +02:00
|
|
|
echo
|
|
|
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
2022-08-29 00:15:42 +02:00
|
|
|
echo -e "${PURPLE}Setting ZSH as default shell${RESET}"
|
2022-08-28 23:10:28 +02:00
|
|
|
chsh -s $(which zsh) $USER
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Install / update vim plugins with Plug
|
2022-08-29 00:15:42 +02:00
|
|
|
echo -e "${PURPLE}Installing Vim Plugins${RESET}"
|
2022-08-28 23:10:28 +02:00
|
|
|
vim +PlugInstall +qall
|
|
|
|
|
|
|
|
# Install / update Tmux plugins with TPM
|
2022-08-29 00:15:42 +02:00
|
|
|
echo -e "${PURPLE}Installing TMUX Plugins${RESET}"
|
2022-08-28 23:10:28 +02:00
|
|
|
chmod ug+x "${XDG_DATA_HOME}/tmux/tpm"
|
2022-08-30 18:39:35 +02:00
|
|
|
sh "${TMUX_PLUGIN_MANAGER_PATH}/tpm/bin/install_plugins"
|
2022-08-29 00:15:42 +02:00
|
|
|
sh "${XDG_DATA_HOME}/tmux/plugins/tpm/bin/install_plugins"
|
|
|
|
|
|
|
|
|
|
|
|
# Install / update ZSH plugins with Antigen
|
|
|
|
echo -e "${PURPLE}Installing ZSH Plugins${RESET}"
|
|
|
|
/bin/zsh -i -c "antigen update && antigen-apply"
|
2022-08-28 23:10:28 +02:00
|
|
|
}
|
|
|
|
|
2022-09-13 14:29:13 +02:00
|
|
|
# Setup Brew, install / update packages, organize launchpad and checks for macOS updates
|
2022-09-08 21:45:44 +02:00
|
|
|
function intall_macos_packages () {
|
|
|
|
# Homebrew not installed, ask user if they'd like to download it now
|
|
|
|
if ! command_exists brew; then
|
|
|
|
read -t $PROMPT_TIMEOUT -p "$(echo -e $CYAN_B)Would you like to install Homebrew? (y/N)" -n 1 -r
|
|
|
|
echo
|
|
|
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
2022-09-13 14:29:13 +02:00
|
|
|
echo -en "🍺 ${PURPLE}Installing Homebrew...${RESET}\n"
|
2022-09-08 21:45:44 +02:00
|
|
|
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
|
|
export PATH=/opt/homebrew/bin:$PATH
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
# Update / Install the Homebrew packages in ~/.Brewfile
|
|
|
|
if command_exists brew && [ -f "$HOME/.Brewfile" ]
|
|
|
|
then
|
|
|
|
echo -e "${PURPLE}Updating homebrew and packages...${RESET}"
|
|
|
|
brew update
|
|
|
|
brew upgrade
|
|
|
|
brew bundle --global --file $HOME/.Brewfile
|
|
|
|
brew cleanup
|
2022-09-13 14:29:13 +02:00
|
|
|
else
|
|
|
|
echo -e "${PURPLE}Skipping Homebrew as requirements not met${RESET}"
|
2022-09-08 21:45:44 +02:00
|
|
|
fi
|
|
|
|
# Restore launchpad structure with lporg
|
|
|
|
if ! command_exists lporg && [ -f "$DOTFILES_DIR/configs/macos/launchpad.yml" ]; then
|
|
|
|
echo -e "${PURPLE}Restoring Launchpad Layout...${RESET}"
|
2022-09-13 14:29:13 +02:00
|
|
|
lporg load "$DOTFILES_DIR/configs/macos/launchpad.yml"
|
2022-09-08 21:45:44 +02:00
|
|
|
fi
|
|
|
|
# Check for MacOS software updates, and ask user if they'd like to install
|
|
|
|
echo -e "${PURPLE}Checking for software updates...${RESET}"
|
|
|
|
pending_updates=$(softwareupdate -l 2>&1)
|
|
|
|
if [[ ! $pending_updates == *"No new software available."* ]]; then
|
|
|
|
read -t $PROMPT_TIMEOUT -p "$(echo -e $CYAN_B)A new macOS software update is available.\
|
|
|
|
Would you like to install it now?$(echo -e $RESET) (y/N)" -n 1 -r
|
|
|
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
|
|
softwareupdate -i -a
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
echo -e "${GREEN}System is up-to-date."\
|
|
|
|
"Running $(sw_vers -productName) version $(sw_vers -productVersion)${RESET}"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2022-08-11 11:22:22 +02:00
|
|
|
# Based on system type, uses appropriate package manager to install / updates apps
|
2022-08-10 13:07:57 +02:00
|
|
|
function install_packages () {
|
2022-08-28 23:10:28 +02:00
|
|
|
|
2022-08-29 00:15:42 +02:00
|
|
|
read -t $PROMPT_TIMEOUT -p "$(echo -e $CYAN_B)Would you like to install / update system packages? (y/N) " -n 1 -r
|
2022-08-28 23:10:28 +02:00
|
|
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
|
|
echo -e "\n${PURPLE}Skipping package installs${RESET}"
|
|
|
|
return
|
|
|
|
fi
|
2022-09-08 21:45:44 +02:00
|
|
|
# Ask for users password
|
|
|
|
echo -e "\n${PURPLE}Some install steps may require elevated permissions.${CYAN_B}\n\
|
|
|
|
You can enter your password now, to avoid typing it for each stage, or Ctrl+C to skip.${RESET}"
|
|
|
|
sudo -v
|
2022-08-28 23:10:28 +02:00
|
|
|
# Mac OS
|
|
|
|
if [ "$system_type" = "Darwin" ]; then
|
2022-09-08 21:45:44 +02:00
|
|
|
intall_macos_packages
|
2022-08-28 23:10:28 +02:00
|
|
|
fi
|
2022-08-10 13:07:57 +02:00
|
|
|
}
|
|
|
|
|
2022-08-11 11:22:22 +02:00
|
|
|
# Updates current session, and outputs summary
|
2022-08-10 13:07:57 +02:00
|
|
|
function finishing_up () {
|
|
|
|
# Update source to ZSH entry point
|
|
|
|
source "${HOME}/.zshenv"
|
|
|
|
|
|
|
|
# Print success message, and time taken
|
|
|
|
total_time=$((`date +%s`-start_time))
|
|
|
|
make_banner "✨ Dotfiles configured succesfully in $total_time seconds" ${GREEN_B} 1
|
2022-09-13 14:29:13 +02:00
|
|
|
|
|
|
|
# Exit script with success code
|
2022-08-10 13:07:57 +02:00
|
|
|
exit 0
|
|
|
|
}
|
|
|
|
|
2022-09-13 14:29:13 +02:00
|
|
|
# Let's Begin!
|
2022-08-10 13:07:57 +02:00
|
|
|
pre_setup_tasks # Print start message, and check requirements are met
|
2022-08-11 11:22:22 +02:00
|
|
|
setup_dot_files # Clone / updatae dotfiles, and create the symlinks
|
2022-09-13 14:29:13 +02:00
|
|
|
apply_preferences # Apply settings for individual applications
|
2022-08-11 11:22:22 +02:00
|
|
|
install_packages # Prompt to install / update OS-specific packages
|
2022-09-13 14:29:13 +02:00
|
|
|
finishing_up # Refresh current session, print summary and exit
|
|
|
|
# All done :)
|