dotfiles/bootstrap
Fernando Schauenburg 5d10202121 Remove support for light background
I never seemed to used and the complexity added by this was a bit
annoying.
2021-07-27 23:28:48 +02:00

219 lines
5.9 KiB
Bash
Executable file

#!/bin/sh
set -eu
DRY_RUN=false
DEFAULT_GIT_USER="Fernando Schauenburg"
DEFAULT_GIT_EMAIL="fernando@schauenburg.me"
XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
DOTFILES_DIR="$(dirname "$(realpath "$0")")"
DIRS=$(cat <<EOF
${HOME}/.local/bin
${HOME}/.local/etc/git
${HOME}/.jupyter/custom
${HOME}/.jupyter/nbconfig
${HOME}/.ssh
${XDG_CONFIG_HOME}/alacritty
${XDG_CONFIG_HOME}/git
${XDG_CONFIG_HOME}/mintty
${XDG_CONFIG_HOME}/python
${XDG_CONFIG_HOME}/readline
${XDG_CONFIG_HOME}/tmux
${XDG_CONFIG_HOME}/nvim
${XDG_CONFIG_HOME}/nvim/autoload
${XDG_DATA_HOME}/bash
${XDG_DATA_HOME}/bash-completion/completions
${XDG_DATA_HOME}/less
${XDG_DATA_HOME}/python
${XDG_DATA_HOME}/nvim
${XDG_DATA_HOME}/nvim/plugged
${XDG_DATA_HOME}/nvim/shada
EOF
)
DOTFILES=$(cat <<EOF
files/xcompose ${HOME}/.XCompose
files/bashrc ${HOME}/.bash_profile
files/bashrc ${HOME}/.bashrc
files/jupyter_custom.js ${HOME}/.jupyter/custom/custom.js
files/jupyter_notebook.json ${HOME}/.jupyter/nbconfig/notebook.json
files/ssh_config ${HOME}/.ssh/config
files/alacritty.yml ${XDG_CONFIG_HOME}/alacritty/alacritty.yml
files/gitconfig ${XDG_CONFIG_HOME}/git/config
files/gitignore ${XDG_CONFIG_HOME}/git/ignore
files/inputrc ${XDG_CONFIG_HOME}/readline/inputrc
files/minttyrc ${XDG_CONFIG_HOME}/mintty/config
files/plug.vim ${XDG_CONFIG_HOME}/nvim/autoload/plug.vim
files/python-startup.py ${XDG_CONFIG_HOME}/python/startup.py
files/tmux.conf ${XDG_CONFIG_HOME}/tmux/tmux.conf
files/init.vim ${XDG_CONFIG_HOME}/nvim/init.vim
EOF
)
rst=$(tput sgr0)
red=$(tput setaf 1)
green=$(tput setaf 2)
yellow=$(tput setaf 3)
blue=$(tput setaf 4)
heading() { printf '%s\n' "${blue}===== $1 ==========${rst}"; }
info() { printf '%s\n' "${green}${1}${rst}"; }
warn() { printf '%s\n' "${yellow}${1}${rst}"; }
error() { printf '%s\n' "${red}${1}${rst}"; }
directory_present() { # Make sure directory $1 exists.
if [ -d "$1" ]; then
info "OK: $1"
else
warn "creating $1"
$DRY_RUN || mkdir -p "$1"
fi
}
file_absent() { # Make sure file $1 does not exist.
if [ ! -f "$1" ]; then
info "OK: $1"
else
warn "removing $1"
$DRY_RUN || rm "$1"
fi
}
file_touch() { # Make sure file $1 exists (content is irrelevant).
if [ -f "$1" ]; then
info "OK: $1"
else
warn "creating $1"
$DRY_RUN || touch "$1"
fi
}
prune_link() { # Remove $1 if it's a broken link to a dotfile script.
if [ -h "$1" ]; then # it's a symbolic link
target="$(readlink "$1")"
case "$target" in
"$DOTFILES_DIR/bin/"*) # it points into dotfiles bin
if [ ! -e "$1" ]; then # target of the link missing
warn "pruning $1 -> $target"
$DRY_RUN || rm -f "$1"
fi
;;
esac
fi
}
file_link() { # Make sure $1 is a link to $2.
target="$(realpath "$2")"
if [ "$(readlink "$1")" = "$target" ]; then
info "OK: $1"
else
warn "linking $1 -> $target"
$DRY_RUN || ln -sf "$target" "$1"
fi
}
file_content() { # Ensure $1 and $2 contents are equal, updating $1 if needed.
if diff "$1" "$2" >/dev/null 2>&1; then
info "OK: $1"
else
warn "overwriting $1 with $2:"
cat "$2"
$DRY_RUN || cp -f "$2" "$1"
fi
}
task_gather_user_info() {
heading "Gather user information"
printf 'git name [%s]: ' "$DEFAULT_GIT_USER"
read -r git_user
printf 'git e-mail [%s]: ' "$DEFAULT_GIT_EMAIL"
read -r git_email
}
task_remove_bash_profile() {
heading "Remove pre-installed bash profile"
for f in .bash_logout .profile; do
file_absent "$HOME/$f"
done
}
task_ensure_directories() {
heading "Ensure existence of directories used by dotfiles"
echo "$DIRS" | while read -r d; do directory_present "$d"; done
}
task_link_dotfiles() {
heading "Link dotfiles"
echo "$DOTFILES" | while read -r dest src; do
file_link "$src" "$DOTFILES_DIR/$dest"
done
}
task_deploy_templates() {
heading "Deploy templates"
temp_git="$(mktemp)"
cat >"$temp_git" <<EOF
# *************************************
# * DO NOT EDIT THIS FILE *
# *************************************
#
# This file was generated by the bootstrap script and any changes will be
# overwritten the next time the it is run. For local settings, use this
# instead:
#
# ~/.local/etc/git/config
#
EOF
git config -f "$temp_git" user.name "${git_user:-$DEFAULT_GIT_USER}"
git config -f "$temp_git" user.email "${git_email:-$DEFAULT_GIT_EMAIL}"
file_content "$HOME/.local/etc/git/config.host" "$temp_git"
}
task_prune_broken_bin() {
heading "Prune broken links to commands"
for cmd in $HOME/.local/bin/*; do
prune_link "$cmd"
done
}
task_link_local_bin() {
heading "Link local commands"
for cmd in "$DOTFILES_DIR/bin/"*; do
file_link "$HOME/.local/bin/$(basename "$cmd")" "$cmd"
done
}
task_make_logins_silent() {
heading "Make logins silent"
file_touch "$HOME/.hushlogin"
}
task_install_nvim_plugins() {
heading "Install neovim plugins"
if command -v nvim >/dev/null 2>&1; then
warn "Installing neovim plugins"
$DRY_RUN || nvim -nes -u "$XDG_CONFIG_HOME/nvim/init.vim" -c 'PlugInstall | qall!'
else
error "neovim is not installed; skipping plugin installation..."
fi
}
main() {
$DRY_RUN && warn "Dry run: no changes will actually be made."
task_gather_user_info
task_remove_bash_profile
task_ensure_directories
task_link_dotfiles
task_deploy_templates
task_prune_broken_bin
task_link_local_bin
task_make_logins_silent
task_install_nvim_plugins
}
main