Skip to content

Instantly share code, notes, and snippets.

@wyattowalsh
Last active October 20, 2023 20:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wyattowalsh/03cb9559dc981a69d410e3ff5ee085fb to your computer and use it in GitHub Desktop.
Save wyattowalsh/03cb9559dc981a69d410e3ff5ee085fb to your computer and use it in GitHub Desktop.
Mac Setup Scripts
#!/bin/zsh
<<COMMENT
-------------------------------------------------
setup.zsh: A macOS configuration setup script
Purpose:
Automates the setup process for a new macOS machine by installing desired Homebrew packages, cask apps, and configuring zsh.
Usage Examples:
./setup.zsh : Run the setup
./setup.zsh -v : Run the setup with verbose output
./setup.zsh -d : Run a dry run with verbose output
-------------------------------------------------
COMMENT
readonly SCRIPT_VERSION="0.1.0"
readonly CONFIG_FILE="./setup_config.sh"
source "setup_functions.sh"
parse_arguments "$@"
load_config "$CONFIG_FILE"
main
###################################################
# Configuration settings for setup.zsh
#
# Define the packages, applications, and shell configurations you want for your macOS setup.
###################################################
# Homebrew packages to install
PACKAGES=(
docker-completion
docker-compose
gcc
gh
git
graphviz
java
make
nvm
poetry
pyenv
rbenv
ruby-build
sphinx-doc
speedtest_cli
tree
unar
watchman
wget
zsh
zsh-completions
)
# Cask apps to install
APPS=(
db-browser-for-sqlite
docker
glance
github
google-chrome
google-drive
iina
jupyter-notebook-ql
logi-options-plus
mark-text
miniconda
notion
obsidian
qlmarkdown
quicklook-csv
responsively
slack
spotify
visual-studio-code
WebPQuickLook
zotero
)
# PATH exports and other shell configurations
SHELL_CONFIGS=(
'export PATH="/opt/homebrew/opt/make/libexec/gnubin:$PATH"'
'export PATH="/opt/homebrew/opt/sphinx-doc/bin:$PATH"'
'alias brew="env PATH=\"${PATH//$(pyenv root)\/shims:/}\" brew"'
'export PYENV_ROOT="$HOME/.pyenv"'
'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"'
'eval "$(rbenv init - zsh)"'
'export NVM_DIR="$HOME/.nvm"'
'[ -s "$HOMEBREW_PREFIX/opt/nvm/nvm.sh" ] && . "$HOMEBREW_PREFIX/opt/nvm/nvm.sh"'
'[ -s "$HOMEBREW_PREFIX/opt/nvm/etc/bash_completion.d/nvm" ] && . "$HOMEBREW_PREFIX/opt/nvm/etc/bash_completion.d/nvm"'
'export PATH="/opt/homebrew/opt/openjdk/bin:$PATH"'
'export CPPFLAGS="-I/opt/homebrew/opt/openjdk/include"'
'export PATH="/opt/homebrew/opt/curl/bin:$PATH"'
'export LDFLAGS="-L/opt/homebrew/opt/curl/lib"'
'export CPPFLAGS="-I/opt/homebrew/opt/curl/include"'
'export PKG_CONFIG_PATH="/opt/homebrew/opt/curl/lib/pkgconfig"'
'export PATH="/opt/homebrew/opt/qt@5/bin:$PATH"'
'export LDFLAGS="-L/opt/homebrew/opt/qt@5/lib"'
'export CPPFLAGS="-I/opt/homebrew/opt/qt@5/include"'
'export PKG_CONFIG_PATH="/opt/homebrew/opt/qt@5/lib/pkgconfig"'
'fpath+=~/.zfunc'
'alias c="clear"'
'source $(brew --prefix)/share/powerlevel10k/powerlevel10k.zsh-theme'
'[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh' # Load the p10k configuration if it exists
'eval "$(rbenv init - zsh)"'
)
#!/usr/bin/env zsh
###################################################
# Utility functions and core logic for setup.zsh
###################################################
set -e
trap handle_error ERR
handle_error() {
local exit_code="$?"
log "An error occurred in function $FUNCNAME at line $LINENO." red
return "$exit_code"
}
# Enhanced logging with colored output
# Parameters:
# $1 - Message to be displayed
# $2 - Color for the output (green/red, or none for default)
log() {
local message="[SETUP] $1"
local color="$2"
case $color in
green) print -P "%F{green}$message%f" ;;
red) print -P "%F{red}$message%f" ;;
*) $VERBOSE && echo "$message" ;;
esac
}
# Parse command-line arguments and set flags
# Parameters: Arguments passed to the script
parse_arguments() {
VERBOSE=false
DRY_RUN=false
while getopts ":vd" opt; do
case $opt in
v) VERBOSE=true ;;
d) DRY_RUN=true; VERBOSE=true ;;
\?)
log "Invalid option: -$OPTARG" red
exit 1
;;
esac
done
}
# Load the configuration file
# Parameters:
# $1 - Path to the configuration file
load_config() {
local config_file="$1"
if [[ ! -f "$config_file" ]]; then
log "Configuration file not found: $config_file. Exiting." red
exit 1
else
source "$config_file"
fi
}
# Verify the script is being run on macOS
check_macos_compatibility() {
if [[ $(uname) != "Darwin" ]]; then
log "This script is intended for macOS only." red
exit 1
fi
}
# Check if a given command exists in the system
# Parameters:
# $1 - Command to check
check_command_exists() {
if ! command -v $1 &> /dev/null; then
log "$1 is not installed or not in PATH. Exiting." red
exit 1
fi
}
# Verify all dependencies are installed
check_dependencies() {
local dependencies=("curl")
for dep in "${dependencies[@]}"; do
check_command_exists "$dep"
done
}
# Installs Homebrew on macOS
install_homebrew() {
if ! command -v brew &> /dev/null; then
log "Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" || return 1
else
log "Homebrew is already installed."
fi
}
# Installs Xcode Command Line Tools
install_xcode() {
if ! xcode-select --print-path &> /dev/null; then
log "Installing Xcode Command Line Tools..."
xcode-select --install || return 1
else
log "Xcode Command Line Tools are already installed."
fi
}
# Installs predefined packages using Homebrew
install_packages() {
for pkg in "${PACKAGES[@]}"; do
if ! brew list "$pkg" &> /dev/null; then
log "Installing package: $pkg..."
brew install "$pkg"
else
log "$pkg is already installed."
fi
done
}
# Installs predefined apps using Homebrew Cask
install_apps_with_cask() {
for app in "${APPS[@]}"; do
if ! brew list --cask "$app" &> /dev/null; then
log "Installing app: $app..."
brew install --cask "$app"
else
log "$app is already installed."
fi
done
}
# Installs Oh My Zsh shell framework
install_oh_my_zsh() {
if [[ ! -d "$HOME/.oh-my-zsh" ]]; then
log "Installing Oh My Zsh..."
# Prevent restart
sh -c "RUNZSH=no $(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
return $?
else
log "Oh My Zsh is already installed."
fi
}
# Installs Powerlevel10k Zsh theme
install_powerlevel10k() {
if [[ ! -d "${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k" ]]; then
log "Installing Powerlevel10k theme..."
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git "${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k"
else
log "Powerlevel10k is already installed."
fi
}
# Appends additional shell configurations to .zshrc
append_shell_configs_to_zshrc() {
for config in "${SHELL_CONFIGS[@]}"; do
echo "$config" >> $HOME/.zshrc
done
}
# Sets up Java environment on macOS
setup_java() {
if ! command -v java &> /dev/null; then
log "Installing Java..."
brew install openjdk
else
log "Java is already installed."
fi
}
# Installs Node Version Manager (NVM) and the latest Node.js
# Installs Node Version Manager (NVM) and the latest Node.js
setup_nvm_node() {
if [[ ! -d "$HOME/.nvm" ]]; then
log "Installing NVM..."
# Dynamic version retrieval
local NVM_LATEST_VERSION=$(curl -s https://api.github.com/repos/nvm-sh/nvm/releases/latest | grep 'tag_name' | cut -d\" -f4)
curl -o- "https://raw.githubusercontent.com/nvm-sh/nvm/$NVM_LATEST_VERSION/install.sh" | bash
source $HOME/.zshrc
nvm install node
else
log "NVM is already installed."
fi
}
# Ensures that Zsh is set as the default shell
check_default_shell() {
if [[ $SHELL != "/bin/zsh" ]]; then
log "Setting Zsh as the default shell..."
chsh -s /bin/zsh
else
log "Zsh is already set as the default shell."
fi
}
# Main function that orchestrates the setup process
function main() {
log "Running setup.zsh version $SCRIPT_VERSION"
# Check if the system meets the necessary criteria
check_macos_compatibility
check_dependencies
# Define the list of setup functions to execute
local setup_funcs=(
install_homebrew
install_xcode
install_packages
install_apps_with_cask
install_oh_my_zsh
install_powerlevel10k
append_shell_configs_to_zshrc
setup_java
setup_nvm_node
check_default_shell
)
# Execute each setup function in sequence with dry run check
for func in "${setup_funcs[@]}"; do
if $DRY_RUN; then
log "[DRY-RUN] Would run $func"
else
if ! $func; then
log "$func failed." red
continue
fi
fi
done
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment