mirror of
https://github.com/ivuorinen/dotfiles.git
synced 2026-01-26 11:14:08 +00:00
520 lines
14 KiB
Bash
Executable File
520 lines
14 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Dotfiles manager and install helper
|
|
# (c) Ismo Vuorinen <https://github.com/ivuorinen> 2022
|
|
# Licensed under MIT, see LICENSE
|
|
#
|
|
# shellcheck source-path=$HOME/.dotfiles/local/bin
|
|
#
|
|
# Helper variables, override with ENVs like `VERBOSE=1 dfm help`
|
|
: "${VERBOSE:=0}"
|
|
: "${DOTFILES:=$HOME/.dotfiles}"
|
|
: "${BREWFILE:=$DOTFILES/config/homebrew/Brewfile}"
|
|
: "${HOSTFILES:=$DOTFILES/hosts}"
|
|
|
|
SCRIPT=$(basename "$0")
|
|
|
|
if ! declare -f msg > /dev/null; then
|
|
# Function to print messages if VERBOSE is enabled
|
|
# $1 - message (string)
|
|
msg()
|
|
{
|
|
[ "$VERBOSE" -eq 1 ] && echo "$1"
|
|
return 0
|
|
}
|
|
fi
|
|
|
|
if ! declare -f msg_err > /dev/null; then
|
|
# Function to print error messages and exit
|
|
# $1 - error message (string)
|
|
msg_err()
|
|
{
|
|
echo "(!) ERROR: $1" >&2
|
|
exit 1
|
|
}
|
|
fi
|
|
|
|
if ! declare -f msg_done > /dev/null; then
|
|
# Function to print done message
|
|
# $1 - message (string)
|
|
msg_done()
|
|
{
|
|
echo "✓ $1"
|
|
return 0
|
|
}
|
|
fi
|
|
|
|
VERSION_NVM="v0.39.5"
|
|
|
|
# Loads configs for better installation experience
|
|
source "$DOTFILES/config/shared.sh"
|
|
|
|
source "${DOTFILES}/local/bin/msgr"
|
|
|
|
# -- Menu builder -- #
|
|
menu_section()
|
|
{
|
|
LINE=$(printf '%-18s [ %-15s ]\n' "$1" "$2")
|
|
echo -e " $(__log_marker) $LINE"
|
|
}
|
|
menu_item()
|
|
{
|
|
LINE=$(printf '%-15s %-30s\n' "$1" "$2")
|
|
echo -e "$(__log_indent)$(__log_marker) $LINE"
|
|
}
|
|
|
|
# Takes a bash array ("cow:moo", "dinosaur:roar") and loops
|
|
# through the keys to build menu section listing.
|
|
menu_usage_header()
|
|
{
|
|
MENU_CMD="$1"
|
|
shift
|
|
MENU_ARRAY=("$@")
|
|
|
|
KEYS=""
|
|
for item in "${MENU_ARRAY[@]}"; do
|
|
CMD=$(echo "${item}" | awk -F ":" '{print $1}')
|
|
KEYS+="${CMD} | "
|
|
done
|
|
|
|
# "???" removes 3 last characters, being " | " from the end
|
|
menu_section "$MENU_CMD" "${KEYS%???}"
|
|
}
|
|
|
|
# Takes the usage command "$0 dotfiles" and a
|
|
# bash array ("cow:moo" "dinosaur:roar") and loops
|
|
# through in building a menu for dfm command usage listing.
|
|
menu_usage()
|
|
{
|
|
MENU_CMD="$1"
|
|
shift
|
|
MENU_ARRAY=("$@")
|
|
|
|
msg "$MENU_CMD"
|
|
|
|
for item in "${MENU_ARRAY[@]}"; do
|
|
CMD=$(echo "${item}" | awk -F ":" '{print $1}')
|
|
DESC=$(echo "${item}" | awk -F ":" '{print $2}')
|
|
menu_item "$CMD" "$DESC"
|
|
done
|
|
}
|
|
|
|
section_install()
|
|
{
|
|
USAGE_PREFIX="$SCRIPT install <command>"
|
|
|
|
MENU=(
|
|
"all:Installs everything in the correct order"
|
|
"antigen:Updates the antigen.zsh file"
|
|
"cargo:Install rust/cargo packages"
|
|
"cheat-databases:Install cheat external cheatsheet databases"
|
|
"composer:Install composer"
|
|
"dotenv:Install dotenv-linter"
|
|
"fonts:Install programming fonts"
|
|
"gh:Install GitHub CLI Extensions"
|
|
"go:Install Go Packages"
|
|
"imagick:Install ImageMagick CLI"
|
|
"starship:Install starship.rs"
|
|
"macos:Setup nice macOS defaults"
|
|
"neofetch:Install neofetch"
|
|
"nvm:Install Node Version Manager (nvm)"
|
|
"nvm-latest:Install latest lts node using nvm"
|
|
"npm:Install NPM Packages"
|
|
"ntfy:Install ntfy"
|
|
"ohmybash:Install oh-my-bash"
|
|
"pip:Install pip/python packages"
|
|
"z:Install z"
|
|
)
|
|
|
|
case "$1" in
|
|
all)
|
|
msgr msg "Starting to install all and reloading configurations..."
|
|
$0 install macos
|
|
$0 install fonts
|
|
$0 install antigen
|
|
$0 brew install
|
|
$0 install ohmyposh
|
|
$0 install asdf
|
|
# $0 install ohmybash
|
|
# $0 install pip
|
|
# $0 install cargo
|
|
$0 install composer
|
|
# $0 install dotenv
|
|
$0 install fzf
|
|
# $0 install gh
|
|
# $0 install go
|
|
$0 install cheat-databases
|
|
$0 install imagick
|
|
# $0 install neofetch
|
|
# $0 install nvm
|
|
# $0 install npm
|
|
$0 install ntfy
|
|
$0 install z
|
|
msgr msg "Reloading configurations again..."
|
|
source "$DOTFILES/config/shared.sh"
|
|
msgr yay "All done!"
|
|
;;
|
|
antigen)
|
|
msg "Installing antigen..."
|
|
curl -sSfL git.io/antigen -o "$DOTFILES/local/bin/antigen.zsh" \
|
|
&& msg_yay "New antigen installed!"
|
|
;;
|
|
asdf)
|
|
msg "Installing asdf..."
|
|
bash "$DOTFILES/scripts/install-asdf.sh both" \
|
|
&& msg_yay "asdf installed!"
|
|
;;
|
|
cargo)
|
|
msg "Installing cargo packages..."
|
|
bash "$DOTFILES/scripts/install-cargo-packages.sh" \
|
|
&& msg_yay "cargo packages installed!"
|
|
;;
|
|
cheat-databases)
|
|
msg "Installing cheat databases..."
|
|
for database in "$DOTFILES"/scripts/install-cheat-*; do
|
|
bash "$database" \
|
|
&& msg_yay "Cheat: $database run"
|
|
done
|
|
;;
|
|
composer)
|
|
msg "Installing composer..."
|
|
bash "$DOTFILES/scripts/install-composer.sh" \
|
|
&& msg_yay "composer installed!"
|
|
;;
|
|
dotenv)
|
|
msg "Installing dotenv-linter..."
|
|
curl -sSfL \
|
|
https://raw.githubusercontent.com/dotenv-linter/dotenv-linter/master/install.sh \
|
|
| sh -s -- -b "$XDG_BIN_HOME" \
|
|
&& msg_yay "dotenv-linter installed!"
|
|
;;
|
|
fonts)
|
|
msg "Installing fonts..."
|
|
bash "$DOTFILES/scripts/install-fonts.sh" \
|
|
&& msg_yay "Installed fonts!"
|
|
;;
|
|
fzf)
|
|
msg "Installing fzf..."
|
|
bash "$DOTFILES/scripts/install-fzf.sh" \
|
|
&& msg_yay "fzf installed!"
|
|
;;
|
|
gh)
|
|
msg "Installing GitHub CLI Extensions..."
|
|
bash "$DOTFILES/scripts/install-gh-extensions.sh" \
|
|
&& msg_yay "github cli extensions installed!"
|
|
;;
|
|
go)
|
|
msg "Installing Go Packages..."
|
|
bash "$DOTFILES/scripts/install-go-packages.sh" \
|
|
&& msg_yay "go packages installed!"
|
|
;;
|
|
imagick)
|
|
msg "Installing ImageMagick CLI..."
|
|
curl -L https://imagemagick.org/archive/binaries/magick > "$XDG_BIN_HOME/magick" \
|
|
&& chmod +x "$XDG_BIN_HOME/magick" \
|
|
&& msg_yay "imagick installed!"
|
|
;;
|
|
starship)
|
|
msg "Installing starship.rs..."
|
|
curl -sS https://starship.rs/install.sh | sh -s -- \
|
|
--bin-dir ~/.local/bin \
|
|
--yes \
|
|
&& msg_yay "starship installed!"
|
|
;;
|
|
macos)
|
|
msg "Setting up macOS defaults..."
|
|
bash "$DOTFILES/scripts/set-macos-defaults.sh" \
|
|
&& msg_yay "Brewfile defined apps has been installed!"
|
|
;;
|
|
neofetch)
|
|
msg "Installing neofetch..."
|
|
bash "$DOTFILES/scripts/install-neofetch.sh" \
|
|
&& msg_yay "neofetch installed!"
|
|
;;
|
|
nvm)
|
|
msg "Installing nvm..."
|
|
curl -o- "https://raw.githubusercontent.com/nvm-sh/nvm/$VERSION_NVM/install.sh" | bash
|
|
git checkout "$DOTFILES/base/zshrc"
|
|
git checkout "$DOTFILES/base/bashrc"
|
|
$0 install nvm-latest
|
|
msg_yay "nvm installed!"
|
|
;;
|
|
nvm-latest)
|
|
msg "Installing latest lts node..."
|
|
if [ -n "$NVM_DIR" ]; then
|
|
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
|
fi
|
|
nvm install --lts --latest-npm --default
|
|
git checkout "$DOTFILES/base/zshrc"
|
|
git checkout "$DOTFILES/base/bashrc"
|
|
msg_yay "latest lts node installed!"
|
|
;;
|
|
npm)
|
|
msg "NPM Packages install started..."
|
|
bash "$DOTFILES/scripts/install-npm-packages.sh" \
|
|
&& msg_yay "NPM Packages have been installed!"
|
|
;;
|
|
ntfy)
|
|
msg "ntfy install started..."
|
|
bash "$DOTFILES/scripts/install-ntfy.sh" \
|
|
&& msg_yay "ntfy installed!"
|
|
;;
|
|
ohmybash)
|
|
msg "oh-my-bash install started..."
|
|
bash "$DOTFILES/scripts/install-ohmybash.sh" \
|
|
&& msg_yay "oh-my-bash installed!"
|
|
;;
|
|
ohmyposh)
|
|
msg "oh-my-posh install started..."
|
|
bash "$DOTFILES/scripts/install-ohmyposh.sh" \
|
|
&& msg_yay "oh-my-posh installed!"
|
|
;;
|
|
pip)
|
|
msg "pip install started..."
|
|
bash "$DOTFILES/scripts/install-pip-packages.sh"
|
|
;;
|
|
z)
|
|
msg "Installing z..."
|
|
bash "$DOTFILES/scripts/install-z.sh" \
|
|
&& msg_yay "z has been installed!"
|
|
;;
|
|
*) menu_usage "$USAGE_PREFIX" "${MENU[@]}" ;;
|
|
esac
|
|
}
|
|
|
|
section_brew()
|
|
{
|
|
USAGE_PREFIX="$SCRIPT brew <command>"
|
|
|
|
MENU=(
|
|
"install:Installs items defined in Brewfile"
|
|
"update:Updates and upgrades brew packages"
|
|
"updatebundle:Updates Brewfile with descriptions"
|
|
"autoupdate:Setups brew auto-update and runs it immediately"
|
|
"leaves:List brew leaves (installed on request)"
|
|
"clean:Clean up brew packages"
|
|
)
|
|
|
|
x-have brew && {
|
|
case "$1" in
|
|
install)
|
|
brew bundle install --file="$BREWFILE" --force --quiet && msg_yay "Done!"
|
|
;;
|
|
update)
|
|
brew update && brew outdated && brew upgrade && brew cleanup
|
|
msg_yay "Done!"
|
|
;;
|
|
updatebundle)
|
|
# Updates .dotfiles/homebrew/Brewfile with descriptions
|
|
brew bundle dump \
|
|
--force \
|
|
--file="$BREWFILE" \
|
|
--cleanup \
|
|
--tap \
|
|
--formula \
|
|
--cask \
|
|
--describe && msg_yay "Done!"
|
|
;;
|
|
leaves)
|
|
brew leaves --installed-on-request
|
|
;;
|
|
clean)
|
|
brew bundle cleanup --file="$BREWFILE" && msg_yay "Done!"
|
|
;;
|
|
autoupdate)
|
|
brew autoupdate delete
|
|
brew autoupdate start 43200 --upgrade --cleanup --immediate
|
|
;;
|
|
*)
|
|
menu_usage "$USAGE_PREFIX" "${MENU[@]}"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
! x-have brew && menu_section "$USAGE_PREFIX" "brew not available on this system"
|
|
}
|
|
|
|
section_helpers()
|
|
{
|
|
USAGE_PREFIX="$SCRIPT helpers <command>"
|
|
MENU=(
|
|
"path:Show \$PATH dir by dir"
|
|
)
|
|
|
|
case "$1" in
|
|
path)
|
|
# shellcheck disable=2001
|
|
for i in $(echo "$PATH" | sed 's/:/ /g'); do echo "$i"; done
|
|
;;
|
|
*) menu_usage "$USAGE_PREFIX" "${MENU[@]}" ;;
|
|
esac
|
|
}
|
|
|
|
section_docs()
|
|
{
|
|
USAGE_PREFIX="$SCRIPT docs <command>"
|
|
|
|
MENU=(
|
|
"all:Update all keybindings documentations"
|
|
"tmux:Update tmux keybindings documentation"
|
|
"nvim:Update nvim keybindings documentation"
|
|
"wezterm:Update wezterm keybindings documentation"
|
|
)
|
|
|
|
case "$1" in
|
|
all)
|
|
$0 docs tmux
|
|
$0 docs nvim
|
|
$0 docs wezterm
|
|
;;
|
|
tmux) bash "$DOTFILES/local/bin/x-dfm-docs-xterm-keybindings" ;;
|
|
nvim) bash "$DOTFILES/scripts/create-nvim-keymaps.sh" ;;
|
|
wezterm) bash "$DOTFILES/scripts/create-wezterm-keymaps.sh" ;;
|
|
*) menu_usage "$USAGE_PREFIX" "${MENU[@]}" ;;
|
|
esac
|
|
}
|
|
|
|
section_dotfiles()
|
|
{
|
|
USAGE_PREFIX="$SCRIPT dotfiles <command>"
|
|
|
|
MENU=(
|
|
"fmt:Run all formatters"
|
|
"yamlfmt:Run yamlfmt to all dotfiles, which are in our control"
|
|
"shfmt:Run shfmt to all dotfiles"
|
|
"reset_all:Reset everything, runs all configured reset actions"
|
|
"reset_nvim:Resets nvim. Deletes caches, removes nvim folders and relinks nvim folders"
|
|
)
|
|
|
|
case "$1" in
|
|
fmt)
|
|
msg_ok "Running all formatters"
|
|
$0 dotfiles yamlfmt
|
|
$0 dotfiles shfmt
|
|
msg_done "...done!"
|
|
;;
|
|
reset_all)
|
|
msg_ok "Running all reset commands"
|
|
$0 dotfiles reset_nvim
|
|
;;
|
|
reset_nvim)
|
|
rm -rf \
|
|
~/.local/share/nvim \
|
|
~/.local/state/nvim \
|
|
~/.cache/nvim \
|
|
~/.config/nvim
|
|
msg_ok "Deleted old nvim files (share, state and cache + config)"
|
|
ln -s "$DOTFILES/config/nvim" ~/.config/nvim
|
|
msg_ok "Linked nvim and astronvim"
|
|
x-have npm && $0 install npm
|
|
msg_ok "Installed packages"
|
|
msg_done "nvim reset!"
|
|
;;
|
|
yamlfmt)
|
|
# format yaml files
|
|
x-have yamlfmt && yamlfmt -conf "$DOTFILES/.yamlfmt"
|
|
! x-have yamlfmt && msg_err "yamlfmt not found"
|
|
;;
|
|
shfmt)
|
|
# If system doesn't have fd or shfmt installed, exit
|
|
! x-have fd && msg_err "fd not found, install with asdf"
|
|
! x-have shfmt && msg_err "shfmt not found, install with asdf"
|
|
# Format shell scripts according to following rules.
|
|
fd --full-path "$DOTFILES" -tx \
|
|
-E '*.pl' -E '*.php' -E '*.py' -E '*.zsh' -E 'plugins' -E 'fzf' -E 'dotbot' \
|
|
-x shfmt \
|
|
--language-dialect bash \
|
|
--func-next-line --list --write \
|
|
--indent 2 --case-indent --space-redirects \
|
|
--binary-next-line {} \;
|
|
msg_yay "dotfiles have been shfmt formatted!"
|
|
;;
|
|
*) menu_usage "$USAGE_PREFIX" "${MENU[@]}" ;;
|
|
esac
|
|
}
|
|
|
|
section_check()
|
|
{
|
|
USAGE_PREFIX="$SCRIPT check <command>"
|
|
X_HOSTNAME=$(hostname)
|
|
X_ARCH=$(uname)
|
|
|
|
MENU=(
|
|
"arch <arch>:Empty <arch> returns current. Exit code 0=match to current, 1=no match."
|
|
"host <host>:Empty <host> returns current. Exit code 0=match to current, 1=no match."
|
|
)
|
|
|
|
case "$1" in
|
|
a | arch)
|
|
[[ "$2" = "" ]] && echo "$X_ARCH" && exit 0
|
|
[[ $X_ARCH = "$2" ]] && exit 0 || exit 1
|
|
;;
|
|
h | host | hostname)
|
|
[[ "$2" = "" ]] && echo "$X_HOSTNAME" && exit 0
|
|
[[ $X_HOSTNAME = "$2" ]] && exit 0 || exit 1
|
|
;;
|
|
*) menu_usage "$USAGE_PREFIX" "${MENU[@]}" ;;
|
|
esac
|
|
}
|
|
|
|
# Secret menu for visual tests
|
|
section_tests()
|
|
{
|
|
USAGE_PREFIX="$SCRIPT tests <command>"
|
|
|
|
MENU=(
|
|
"msg:List all log functions from shared.sh"
|
|
)
|
|
|
|
case "$1" in
|
|
msg)
|
|
msg "msg"
|
|
msg_done "msg_done"
|
|
msg_done_suffix "msg_done_suffix"
|
|
msg_err "msg_err"
|
|
msg_nested "msg_nested"
|
|
msg_nested_done "msg_nested_done"
|
|
msg_ok "msg_ok"
|
|
msg_prompt "msg_prompt"
|
|
msg_prompt_done "msg_prompt_done"
|
|
msg_run "msg_run" "second_param"
|
|
msg_run_done "msg_run_done" "second_param"
|
|
msg_warn "msg_warn"
|
|
msg_yay "msg_yay"
|
|
msg_yay_done "msg_yay_done"
|
|
;;
|
|
*) menu_usage "$USAGE_PREFIX" "${MENU[@]}" ;;
|
|
esac
|
|
}
|
|
|
|
usage()
|
|
{
|
|
echo ""
|
|
msg_prompt "Usage: $SCRIPT <section> <command>"
|
|
echo $" Empty <command> prints <section> help."
|
|
echo ""
|
|
section_install
|
|
echo ""
|
|
section_brew
|
|
echo ""
|
|
section_check
|
|
echo ""
|
|
section_dotfiles
|
|
echo ""
|
|
section_docs
|
|
echo ""
|
|
section_helpers
|
|
}
|
|
|
|
# The main loop. first keyword after $0 triggers section, or help.
|
|
case "$1" in
|
|
install) section_install "$2" ;;
|
|
brew) section_brew "$2" ;;
|
|
check) section_check "$2" ;;
|
|
dotfiles) section_dotfiles "$2" ;;
|
|
helpers) section_helpers "$2" ;;
|
|
docs) section_docs "$2" ;;
|
|
tests) section_tests "$2" ;;
|
|
*) usage && exit 0 ;;
|
|
esac
|