156 lines
4.2 KiB
Bash
Executable File
156 lines
4.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -Eeuo pipefail
|
|
|
|
readonly APP_NAME='dotfiles'
|
|
readonly REPO_URI="${REPO_URI:-https://github.com/Donaldttt/dotfiles.git}"
|
|
readonly REPO_BRANCH="${REPO_BRANCH:-main}"
|
|
|
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" 2>/dev/null && pwd -P || true)"
|
|
if [[ -n "$SCRIPT_DIR" && -e "$SCRIPT_DIR/.git" ]]; then
|
|
APP_PATH="${APP_PATH:-$SCRIPT_DIR}"
|
|
else
|
|
APP_PATH="${APP_PATH:-$HOME/.$APP_NAME}"
|
|
fi
|
|
readonly APP_PATH
|
|
readonly VIM_PATH="${VIM_PATH:-$HOME/.vim}"
|
|
readonly MANAGED_START='# >>> dotfiles >>>'
|
|
readonly MANAGED_END='# <<< dotfiles <<<'
|
|
|
|
info() { printf '\033[34m[•]\033[0m %s\n' "$*"; }
|
|
success() { printf '\033[32m[✔]\033[0m %s\n' "$*"; }
|
|
warn() { printf '\033[33m[!]\033[0m %s\n' "$*" >&2; }
|
|
die() { printf '\033[31m[✘]\033[0m %s\n' "$*" >&2; exit 1; }
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: ./install.sh [all|vim|shell|tmux]...
|
|
|
|
With no arguments, installs every component. Components can be combined, for
|
|
example: ./install.sh vim tmux
|
|
EOF
|
|
}
|
|
|
|
require() {
|
|
command -v "$1" >/dev/null 2>&1 || die "Required program not found: $1"
|
|
}
|
|
|
|
ensure_repo() {
|
|
require git
|
|
if [[ -d "$APP_PATH/.git" ]]; then
|
|
return
|
|
fi
|
|
[[ ! -e "$APP_PATH" ]] || die "$APP_PATH exists but is not a Git repository."
|
|
info "Cloning $REPO_URI into $APP_PATH"
|
|
git clone --branch "$REPO_BRANCH" --depth 1 "$REPO_URI" "$APP_PATH"
|
|
}
|
|
|
|
backup_path() {
|
|
local target=$1
|
|
if [[ -e "$target" || -L "$target" ]]; then
|
|
local backup="${target}.backup.$(date +%Y%m%d_%H%M%S)" suffix=0
|
|
while [[ -e "$backup" || -L "$backup" ]]; do
|
|
((suffix += 1))
|
|
backup="${target}.backup.$(date +%Y%m%d_%H%M%S).$suffix"
|
|
done
|
|
mv -- "$target" "$backup"
|
|
warn "Backed up $target to $backup"
|
|
fi
|
|
}
|
|
|
|
link_config() {
|
|
local source=$1 target=$2 current=''
|
|
if [[ -L "$target" ]]; then
|
|
current=$(readlink "$target" || true)
|
|
[[ "$current" == "$source" ]] && return
|
|
fi
|
|
backup_path "$target"
|
|
ln -s "$source" "$target"
|
|
success "Linked $target -> $source"
|
|
}
|
|
|
|
remove_managed_block() {
|
|
local file=$1 temp
|
|
[[ -f "$file" ]] || return
|
|
temp=$(mktemp)
|
|
awk -v start="$MANAGED_START" -v end="$MANAGED_END" '
|
|
$0 == start { managed = 1; next }
|
|
$0 == end { managed = 0; next }
|
|
!managed { print }
|
|
' "$file" > "$temp"
|
|
cat "$temp" > "$file"
|
|
rm -f "$temp"
|
|
}
|
|
|
|
install_vim() {
|
|
require vim
|
|
require curl
|
|
if ! vim --clean -Nu NONE -n -es \
|
|
'+if v:version < 900 | cquit | endif' '+qall'; then
|
|
die 'Vim 9 or newer is required.'
|
|
fi
|
|
|
|
link_config "$APP_PATH/.vimrc" "$HOME/.vimrc"
|
|
mkdir -p "$VIM_PATH/autoload"
|
|
local temp
|
|
temp=$(mktemp)
|
|
curl --fail --location --silent --show-error \
|
|
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim \
|
|
--output "$temp"
|
|
mv "$temp" "$VIM_PATH/autoload/plug.vim"
|
|
vim -Nu "$APP_PATH/.vimrc" -n -es \
|
|
'+set nomore' '+PlugInstall --sync' '+qall'
|
|
success 'Installed Vim configuration and plugins.'
|
|
}
|
|
|
|
install_shell() {
|
|
local bashrc="$HOME/.bashrc" quoted_source
|
|
touch "$bashrc"
|
|
remove_managed_block "$bashrc"
|
|
printf -v quoted_source '%q' "$APP_PATH/bash_tools.sh"
|
|
{
|
|
printf '\n%s\n' "$MANAGED_START"
|
|
printf '[ -r %s ] && source %s\n' "$quoted_source" "$quoted_source"
|
|
printf 'command -v zoxide >/dev/null 2>&1 && eval "$(zoxide init bash)"\n'
|
|
printf '%s\n' "$MANAGED_END"
|
|
} >> "$bashrc"
|
|
success "Installed managed Bash block in $bashrc"
|
|
}
|
|
|
|
install_tmux() {
|
|
require tmux
|
|
link_config "$APP_PATH/.tmux.conf" "$HOME/.tmux.conf"
|
|
local tpm="$HOME/.tmux/plugins/tpm"
|
|
if [[ ! -d "$tpm/.git" ]]; then
|
|
[[ ! -e "$tpm" ]] || die "$tpm exists but is not a Git repository."
|
|
mkdir -p "$(dirname "$tpm")"
|
|
git clone --depth 1 https://github.com/tmux-plugins/tpm "$tpm"
|
|
fi
|
|
success 'Installed tmux configuration and TPM.'
|
|
}
|
|
|
|
main() {
|
|
case "${1:-}" in
|
|
-h|--help) usage; return ;;
|
|
esac
|
|
|
|
ensure_repo
|
|
local components=("$@") component
|
|
((${#components[@]})) || components=(all)
|
|
for component in "${components[@]}"; do
|
|
case "$component" in
|
|
all)
|
|
install_vim
|
|
install_shell
|
|
install_tmux
|
|
;;
|
|
vim) install_vim ;;
|
|
shell) install_shell ;;
|
|
tmux) install_tmux ;;
|
|
*) usage; die "Unknown component: $component" ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
main "$@"
|