zdharma-continuum.zinit/scripts/install.sh
2025-02-18 17:51:33 +01:00

334 lines
8.9 KiB
Bash
Executable file
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
{ # Colors
COLOR_RESET=''
COLOR_BOLD_RED=''
COLOR_BOLD_GREEN=''
COLOR_BOLD_YELLOW=''
COLOR_BOLD_BLUE=''
COLOR_BOLD_MAGENTA=''
COLOR_BOLD_CYAN=''
# The over-the-top fancy ones
COLOR_PALE_MAGENTA=''
COLOR_BOLD_WHITE_ON_BLACK=''
}
echo_fancy() {
emoji="$1"
color="$2"
shift 2
msg=""
# prepend emoji, unless NO_EMOJI is set
if [ -z "$NO_EMOJI" ]; then
msg="$emoji"
fi
# wrap every word in color (needed in case there are custom colors in
# the message itself), unless NO_COLOR is set
for str in "$@"; do
# FIXME: NO_COLOR only applies if there are no colors in the msg
if [ -z "$NO_COLOR" ]; then
msg="${msg}${color}"
fi
msg="${msg}${str}"
done
# Actual output
echo "${msg}${COLOR_RESET}" >&2
# fake "local" vars
unset emoji color str msg
}
echo_info() {
echo_fancy "🔵" "${COLOR_BOLD_BLUE}" "INFO: ${*}"
}
echo_success() {
echo_fancy "✅" "${COLOR_BOLD_GREEN}" "SUCCESS: ${*}"
}
echo_warning() {
echo_fancy "🚧" "${COLOR_BOLD_YELLOW}" "WARNING: ${*}"
}
echo_error() {
echo_fancy "❌" "${COLOR_BOLD_RED}" "ERROR: ${*}"
}
check_dependencies() {
zsh_min_version=5.8
if ! zsh -sfc \
'autoload is-at-least;
is-at-least $1 $ZSH_VERSION' "$zsh_min_version"; then
echo_warning "ZSH version 5.5+ is recommended for zinit." \
"It'll still work, but be warned."
fi
if ! command -v git > /dev/null 2>&1; then
echo_error "${COLOR_BOLD_GREEN}git${COLOR_RESET} is not installed"
exit 1
fi
unset zsh_min_version
}
show_environment() {
echo_info "About to setup zinit from $ZINIT_REPO" \
"(branch: $ZINIT_BRANCH - commit: ${ZINIT_COMMIT:-N/A})" \
"to ${ZINIT_INSTALL_DIR}"
}
create_zinit_home() {
if ! test -d "${ZINIT_HOME}"; then
mkdir -p "${ZINIT_HOME}"
chmod g-w "${ZINIT_HOME}"
chmod o-w "${ZINIT_HOME}"
fi
}
create_zinit_tmpdir() {
# use -d instead of --directory for macos (BSD) compatibility
ZINIT_TMPDIR="$(mktemp -d)"
if [ ! -d "$ZINIT_TMPDIR" ]; then
echo_error "Tempdir creation failed. This ain't good"
exit 1
fi
trap 'rm -rvf "$ZINIT_TMPDIR"' EXIT INT
}
# Get the download-progress bar tool
download_git_output_processor() {
url="https://raw.githubusercontent.com/${ZINIT_REPO}/${ZINIT_COMMIT:-${ZINIT_BRANCH}}/share/git-process-output.zsh"
script_path="${ZINIT_TMPDIR}/git-process-output.zsh"
echo_info "Fetching git-process-output.zsh from $url"
if command -v curl > /dev/null 2>&1; then
curl -fsSL -o "$script_path" "$url"
elif command -v wget > /dev/null 2>&1; then
wget -q -O "$script_path" "$url"
fi
# shellcheck disable=2181
if [ "$?" -eq 0 ]; then
chmod a+x "$script_path" 2> /dev/null
echo_success 'Download finished!'
else
echo_warning "Download failed."
fi
unset url script_path
}
zinit_git_exec() {
command git -C "${ZINIT_INSTALL_DIR}" "$@"
}
zinit_checkout_ref() {
ref="${ZINIT_BRANCH}"
git_obj_type="branch"
if [ -n "$ZINIT_COMMIT" ]; then
ref="$ZINIT_COMMIT"
git_obj_type="commit"
fi
if zinit_git_exec checkout "$ref" > /dev/null 2>&1; then
echo_success "Checked out $git_obj_type $ref"
else
echo_error "Failed to check out $git_obj_type $ref"
fi
unset ref git_obj_type
}
zinit_current_version() {
zinit_git_exec describe --tags 2> /dev/null
}
zinit_update() {
cd "${ZINIT_INSTALL_DIR}" || {
echo_error "Failed to cd to ${ZINIT_INSTALL_DIR}"
exit 1
}
echo_info "Updating ${COLOR_BOLD_CYAN}zinit${COLOR_RESET} in" \
"in ${COLOR_BOLD_MAGENTA}${ZINIT_INSTALL_DIR}"
{ # Clean up repo
zinit_git_exec clean -d -f -f
zinit_git_exec reset --hard HEAD
} > /dev/null 2>&1
# fetch our branch (to ensure the target commit exists locally)
zinit_git_exec fetch origin "$ZINIT_BRANCH"
zinit_checkout_ref
if zinit_git_exec pull origin "$ZINIT_BRANCH"; then
echo_success "Updated zinit to $(zinit_current_version)"
fi
}
zinit_install() {
cd "${ZINIT_HOME}" || {
echo_error "Failed to cd to ${ZINIT_HOME}"
exit 1
}
echo_info "Installing ${COLOR_BOLD_CYAN}zinit${COLOR_RESET} to " \
"${COLOR_BOLD_MAGENTA}${ZINIT_INSTALL_DIR}"
{
command git clone --progress --branch "$ZINIT_BRANCH" \
"https://github.com/${ZINIT_REPO}" \
"${ZINIT_REPO_DIR_NAME}" 2>&1 | {
"${ZINIT_TMPDIR}/git-process-output.zsh" || cat
}
} 2> /dev/null
zinit_checkout_ref
if [ -d "${ZINIT_REPO_DIR_NAME}" ]; then
echo_success "Zinit succesfully installed to " \
"${COLOR_BOLD_GREEN}${ZINIT_INSTALL_DIR}"
echo_info "Zinit Version: ${COLOR_BOLD_GREEN}$(zinit_current_version)"
else
echo_error "Failed to install Zinit to ${COLOR_BOLD_YELLOW}${ZINIT_INSTALL_DIR}"
fi
}
# Modify .zshrc
edit_zshrc() {
rc_update=1
if grep -E '(zinit|zplugin)\.zsh' "${ZSHRC}" > /dev/null 2>&1; then
echo_warning "${ZSHRC} already contains zinit commands. Not making any changes."
rc_update=0
fi
if [ $rc_update -eq 1 ]; then
echo_info "Updating ${ZSHRC} (10 lines of code, at the bottom)"
zinit_home_escaped=${ZINIT_HOME//$HOME/\$HOME}
command cat <<- EOF >> "$ZSHRC"
### Added by Zinit's installer
if [[ ! -f ${zinit_home_escaped}/${ZINIT_REPO_DIR_NAME}/zinit.zsh ]]; then
print -P "%F{33} %F{220}Installing %F{33}ZDHARMA-CONTINUUM%F{220} Initiative Plugin Manager (%F{33}${ZINIT_REPO}%F{220})…%f"
command mkdir -p "${zinit_home_escaped}" && command chmod g-rwX "${zinit_home_escaped}"
command git clone https://github.com/${ZINIT_REPO} "${zinit_home_escaped}/${ZINIT_REPO_DIR_NAME}" && \\
print -P "%F{33} %F{34}Installation successful.%f%b" || \\
print -P "%F{160} The clone has failed.%f%b"
fi
source "${zinit_home_escaped}/${ZINIT_REPO_DIR_NAME}/zinit.zsh"
autoload -Uz _zinit
(( \${+_comps} )) && _comps[zinit]=_zinit
EOF
fi
unset rc_update zinit_home_escaped
}
query_for_annexes() {
zshrc_annex_file="$(mktemp)"
command cat <<- EOF >> "$zshrc_annex_file"
# Load a few important annexes, without Turbo
# (this is currently required for annexes)
zinit light-mode for \\
zdharma-continuum/zinit-annex-as-monitor \\
zdharma-continuum/zinit-annex-bin-gem-node \\
zdharma-continuum/zinit-annex-patch-dl \\
zdharma-continuum/zinit-annex-rust
EOF
# Ask user if we should add the annexes to their zshrc
# If NO_INPUT is set, but NO_ANNEXES is the annexes bit gets appended to the
# config (ie. default to yes if NO_INPUT, unless NO_ANNEXES)
reply=n
if [ -n "$NO_INPUT" ]; then
[ -z "$NO_ANNEXES" ] && reply=y
else
echo "${COLOR_PALE_MAGENTA}${COLOR_RESET} Would you like to add 4 useful plugins" \
"- the most useful annexes (Zinit extensions that add new" \
"functions-features to the plugin manager) to the zshrc as well?" \
"It will be the following snippet:"
command cat "$zshrc_annex_file"
# shellcheck disable=2059
printf "${COLOR_PALE_MAGENTA}${COLOR_RESET} Enter y/n and press Return: "
read -r reply
fi
if [ "$reply" = y ] || [ "$reply" = Y ]; then
command cat "$zshrc_annex_file" >> "$ZSHRC"
echo_info "Installing annexes"
zsh -ic "@zinit-scheduler burst"
echo_success 'Done!'
else
echo_warning "Skipped the annexes."
fi
command cat <<- EOF >> "$ZSHRC"
### End of Zinit's installer chunk
EOF
unset reply zshrc_annex_file
}
display_tutorial() {
command cat <<- EOF
🌻 ${COLOR_BOLD_WHITE_ON_BLACK}Welcome!${COLOR_RESET}
Now to get started you can check out the following:
- The ${COLOR_BOLD_WHITE_ON_BLACK}README${COLOR_RESET} section on the ice-modifiers:
🧊 https://github.com/${ZINIT_REPO}#ice-modifiers
- There's also an ${COLOR_BOLD_WHITE_ON_BLACK}introduction${COLOR_RESET} to Zinit on the wiki:
📚 https://zdharma-continuum.github.io/zinit/wiki/INTRODUCTION/
- The ${COLOR_BOLD_WHITE_ON_BLACK}For-Syntax${COLOR_RESET} article on the wiki, which highlights some best practices:
📖 https://zdharma-continuum.github.io/zinit/wiki/For-Syntax/
💁 Need help?
- 💬 Get in touch with us on Gitter: https://gitter.im/zdharma-continuum
- 🔖 Or on GitHub: https://github.com/zdharma-continuum
EOF
}
# Globals. Can be overridden.
ZINIT_REPO="${ZINIT_REPO:-zdharma-continuum/zinit}"
ZINIT_BRANCH="${ZINIT_BRANCH:-main}"
ZINIT_COMMIT="${ZINIT_COMMIT:-}" # no default value
ZINIT_HOME="${ZINIT_HOME:-${XDG_DATA_HOME:-${HOME}/.local/share}/zinit}"
ZINIT_REPO_DIR_NAME="${ZINIT_REPO_DIR_NAME:-zinit.git}"
ZINIT_INSTALL_DIR=${ZINIT_INSTALL_DIR:-${ZINIT_HOME}/${ZINIT_REPO_DIR_NAME}}
ZSHRC="${ZSHRC:-${ZDOTDIR:-${HOME}}/.zshrc}"
show_environment
check_dependencies
create_zinit_home
create_zinit_tmpdir
download_git_output_processor
if [ -d "${ZINIT_INSTALL_DIR}/.git" ]; then
zinit_update
ZINIT_UPDATE=1
else
zinit_install
fi
if [ -z "$NO_EDIT" ]; then
edit_zshrc
[ -z "$ZINIT_UPDATE" ] && query_for_annexes
fi
if [ -z "$NO_TUTORIAL" ]; then
display_tutorial
fi
# Local Variables:
# mode: Shell-Script
# sh-indentation: 2
# indent-tabs-mode: nil
# sh-basic-offset: 2
# End:
# vim: ft=bash sw=2 ts=2 et