- write_zshrc_kali now sets HISTFILE/HISTSIZE/SAVEHIST and share_history/ hist_ignore_dups so command history survives across sessions (previously unset, so history was in-memory only despite shipping zsh-history-substring-search and fzf history search). - apply_terminal_look now guards install_terminal_prereqs and returns 0 with a skip message on failure, matching apply_hyprland's existing pattern, so an unrecognized package manager no longer aborts the whole script under set -euo pipefail and blocks a Hyprland module that would otherwise succeed. Addresses findings 1 and 2 from the final whole-branch review.
502 lines
18 KiB
Bash
Executable File
502 lines
18 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# ${BASH_SOURCE[0]} is unset (not just empty) when this script arrives as a
|
|
# `bash -c "$(curl ...)"` command string rather than a real file -- guard it
|
|
# so `set -u` doesn't blow up. `dirname ""` -> "." (current dir), which
|
|
# ensure_repo_files() below correctly treats as "no local checkout, fetch."
|
|
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-}")" && pwd)"
|
|
CONFIG_HOME="${CONFIG_HOME:-${XDG_CONFIG_HOME:-$HOME/.config}}"
|
|
LOCAL_BIN="${LOCAL_BIN:-$HOME/.local/bin}"
|
|
DOTEVO_RAW_BASE="${DOTEVO_RAW_BASE:-https://git.edemilov.ru/edemilov/dotevo/raw/branch/master}"
|
|
OMZ_DIR="${OMZ_DIR:-$HOME/.oh-my-zsh}"
|
|
ZSH_CUSTOM_DIR="${ZSH_CUSTOM_DIR:-$HOME/.dotevo-zsh-custom}"
|
|
ASSETS_DIR="${ASSETS_DIR:-$HOME/.dotevo}"
|
|
|
|
check_arch() {
|
|
command -v pacman >/dev/null 2>&1
|
|
}
|
|
|
|
detect_pkg_manager() {
|
|
if command -v pacman >/dev/null 2>&1; then
|
|
echo pacman
|
|
elif command -v apt-get >/dev/null 2>&1; then
|
|
echo apt
|
|
elif command -v dnf >/dev/null 2>&1; then
|
|
echo dnf
|
|
elif command -v zypper >/dev/null 2>&1; then
|
|
echo zypper
|
|
else
|
|
echo unknown
|
|
fi
|
|
}
|
|
|
|
install_terminal_prereqs() {
|
|
local mgr
|
|
mgr=$(detect_pkg_manager)
|
|
case "$mgr" in
|
|
pacman) sudo pacman -S --needed --noconfirm zsh git curl fzf ;;
|
|
apt) sudo apt-get update && sudo apt-get install -y zsh git curl fzf ;;
|
|
dnf) sudo dnf install -y zsh git curl fzf ;;
|
|
zypper) sudo zypper install -y zsh git curl fzf ;;
|
|
*)
|
|
echo "dotevo: package manager not recognized -- install zsh git curl fzf manually" >&2
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# When install.sh is curl-piped straight into bash (the normal way to run it),
|
|
# $BASH_SOURCE resolves to a transient fd path (e.g. /dev/fd/63) with no
|
|
# sibling files at all -- there's no local checkout of the rest of the repo.
|
|
# Detect that case and fetch the handful of files apply_hyprland() needs into a fresh
|
|
# temp dir instead, then repoint REPO_DIR there. Running from a real git
|
|
# checkout (packages.txt already sits next to this script) is left untouched.
|
|
ensure_repo_files() {
|
|
if [[ -f "$REPO_DIR/packages.txt" ]]; then
|
|
return 0
|
|
fi
|
|
|
|
local tmp_dir
|
|
tmp_dir="$(mktemp -d)"
|
|
mkdir -p "$tmp_dir/hypr" "$tmp_dir/local-bin" "$tmp_dir/terminal/p10k" "$tmp_dir/terminal/kali"
|
|
|
|
curl -fsSL "$DOTEVO_RAW_BASE/packages.txt" -o "$tmp_dir/packages.txt"
|
|
curl -fsSL "$DOTEVO_RAW_BASE/hypr/hyprland.conf" -o "$tmp_dir/hypr/hyprland.conf"
|
|
curl -fsSL "$DOTEVO_RAW_BASE/local-bin/capture-menu.sh" -o "$tmp_dir/local-bin/capture-menu.sh"
|
|
curl -fsSL "$DOTEVO_RAW_BASE/local-bin/screenshot.sh" -o "$tmp_dir/local-bin/screenshot.sh"
|
|
curl -fsSL "$DOTEVO_RAW_BASE/local-bin/toggle-recording.sh" -o "$tmp_dir/local-bin/toggle-recording.sh"
|
|
curl -fsSL "$DOTEVO_RAW_BASE/terminal/p10k/.p10k.zsh" -o "$tmp_dir/terminal/p10k/.p10k.zsh"
|
|
curl -fsSL "$DOTEVO_RAW_BASE/terminal/kali/prompt.zsh" -o "$tmp_dir/terminal/kali/prompt.zsh"
|
|
|
|
REPO_DIR="$tmp_dir"
|
|
}
|
|
|
|
slot_package() {
|
|
local slot="$1" choice="$2"
|
|
case "$slot:$choice" in
|
|
Terminal:Konsole) echo "konsole" ;;
|
|
Terminal:Terminator) echo "terminator" ;;
|
|
Terminal:Kitty) echo "kitty" ;;
|
|
Terminal:Alacritty) echo "alacritty" ;;
|
|
FileManager:Dolphin) echo "dolphin" ;;
|
|
FileManager:Nautilus) echo "nautilus" ;;
|
|
FileManager:Thunar) echo "thunar" ;;
|
|
Mail:Thunderbird) echo "thunderbird" ;;
|
|
Mail:KMail) echo "kmail" ;;
|
|
CloudSync:Nextcloud) echo "nextcloud-client" ;;
|
|
CloudSync:Syncthing) echo "syncthing" ;;
|
|
*) echo "dotevo: unknown slot/choice pair: $slot/$choice" >&2; return 1 ;;
|
|
esac
|
|
}
|
|
|
|
slot_binary() {
|
|
local slot="$1" choice="$2"
|
|
case "$slot:$choice" in
|
|
Terminal:Konsole) echo "konsole" ;;
|
|
Terminal:Terminator) echo "terminator" ;;
|
|
Terminal:Kitty) echo "kitty" ;;
|
|
Terminal:Alacritty) echo "alacritty" ;;
|
|
FileManager:Dolphin) echo "dolphin" ;;
|
|
FileManager:Nautilus) echo "nautilus" ;;
|
|
FileManager:Thunar) echo "thunar" ;;
|
|
Mail:Thunderbird) echo "thunderbird" ;;
|
|
Mail:KMail) echo "kmail" ;;
|
|
CloudSync:Nextcloud) echo "nextcloud --background" ;;
|
|
*) echo "dotevo: unknown slot/choice pair: $slot/$choice" >&2; return 1 ;;
|
|
esac
|
|
}
|
|
|
|
terminal_desktop_id() {
|
|
local choice="$1"
|
|
case "$choice" in
|
|
Konsole) echo "org.kde.konsole.desktop" ;;
|
|
Terminator) echo "terminator.desktop" ;;
|
|
Kitty) echo "kitty.desktop" ;;
|
|
Alacritty) echo "Alacritty.desktop" ;;
|
|
*) echo "dotevo: unknown terminal choice: $choice" >&2; return 1 ;;
|
|
esac
|
|
}
|
|
|
|
toggle_packages() {
|
|
local toggle="$1"
|
|
case "$toggle" in
|
|
Telegram) echo "telegram-desktop" ;;
|
|
Bitwarden) echo "bitwarden" ;;
|
|
ScreenCapture) echo "grim slurp satty wl-clipboard wf-recorder fuzzel libnotify" ;;
|
|
*) echo "dotevo: unknown toggle: $toggle" >&2; return 1 ;;
|
|
esac
|
|
}
|
|
|
|
run_picker() {
|
|
if [[ "${DOTEVO_NONINTERACTIVE:-0}" == "1" ]]; then
|
|
PICK_TERMINAL="${DOTEVO_TERMINAL:?DOTEVO_TERMINAL required in non-interactive mode}"
|
|
PICK_FILEMANAGER="${DOTEVO_FILEMANAGER:?DOTEVO_FILEMANAGER required in non-interactive mode}"
|
|
PICK_MAIL="${DOTEVO_MAIL:?DOTEVO_MAIL required in non-interactive mode}"
|
|
PICK_CLOUDSYNC="${DOTEVO_CLOUDSYNC:?DOTEVO_CLOUDSYNC required in non-interactive mode}"
|
|
read -ra PICK_TOGGLES <<< "${DOTEVO_TOGGLES:-}"
|
|
return 0
|
|
fi
|
|
|
|
PICK_TERMINAL=$(whiptail --title "dotevo" --radiolist \
|
|
"Choose your terminal emulator" 15 60 4 \
|
|
Konsole "" ON Terminator "" OFF Kitty "" OFF Alacritty "" OFF \
|
|
3>&1 1>&2 2>&3)
|
|
|
|
PICK_FILEMANAGER=$(whiptail --title "dotevo" --radiolist \
|
|
"Choose your file manager" 15 60 3 \
|
|
Dolphin "" ON Nautilus "" OFF Thunar "" OFF \
|
|
3>&1 1>&2 2>&3)
|
|
|
|
PICK_MAIL=$(whiptail --title "dotevo" --radiolist \
|
|
"Choose your mail client" 15 60 2 \
|
|
Thunderbird "" ON KMail "" OFF \
|
|
3>&1 1>&2 2>&3)
|
|
|
|
PICK_CLOUDSYNC=$(whiptail --title "dotevo" --radiolist \
|
|
"Choose your cloud sync client" 15 60 2 \
|
|
Nextcloud "" ON Syncthing "" OFF \
|
|
3>&1 1>&2 2>&3)
|
|
|
|
local toggle_raw
|
|
toggle_raw=$(whiptail --title "dotevo" --checklist \
|
|
"Choose optional apps (space to toggle, enter to confirm)" 15 70 3 \
|
|
Telegram "" OFF ScreenCapture "Screenshot/record via Print key" OFF Bitwarden "" OFF \
|
|
3>&1 1>&2 2>&3)
|
|
# whiptail --checklist returns space-separated quoted tokens, e.g. "Telegram" "Bitwarden"
|
|
read -ra PICK_TOGGLES <<< "$(echo "$toggle_raw" | tr -d '"')"
|
|
}
|
|
|
|
confirm_summary() {
|
|
local summary
|
|
summary="Terminal: $PICK_TERMINAL
|
|
File manager: $PICK_FILEMANAGER
|
|
Mail client: $PICK_MAIL
|
|
Cloud sync: $PICK_CLOUDSYNC
|
|
Telegram: $([[ " ${PICK_TOGGLES[*]} " == *" Telegram "* ]] && echo yes || echo no)
|
|
Screen capture: $([[ " ${PICK_TOGGLES[*]} " == *" ScreenCapture "* ]] && echo yes || echo no)
|
|
Bitwarden: $([[ " ${PICK_TOGGLES[*]} " == *" Bitwarden "* ]] && echo yes || echo no)"
|
|
|
|
if [[ "${DOTEVO_NONINTERACTIVE:-0}" == "1" ]]; then
|
|
echo "$summary"
|
|
return 0
|
|
fi
|
|
|
|
whiptail --title "dotevo -- confirm" --yesno "$summary
|
|
|
|
Install with these choices?" 18 60
|
|
}
|
|
|
|
build_extras_conf() {
|
|
echo "# Generated by dotevo -- rebuilt fresh on every install run, do not hand-edit"
|
|
|
|
if [[ " ${PICK_TOGGLES[*]} " == *" ScreenCapture "* ]]; then
|
|
echo "bind = , Print, exec, ~/.local/bin/capture-menu.sh"
|
|
fi
|
|
|
|
if [[ "$PICK_CLOUDSYNC" == "Nextcloud" ]]; then
|
|
echo "exec-once = $(slot_binary CloudSync Nextcloud)"
|
|
fi
|
|
|
|
if [[ " ${PICK_TOGGLES[*]} " == *" Telegram "* ]]; then
|
|
echo "exec-once = Telegram -startintray"
|
|
fi
|
|
|
|
if [[ " ${PICK_TOGGLES[*]} " == *" Bitwarden "* ]]; then
|
|
echo "exec-once = bitwarden-desktop --disable-gpu"
|
|
fi
|
|
}
|
|
|
|
render_hyprland_conf() {
|
|
local src_path="$1"
|
|
local terminal_bin fm_bin
|
|
terminal_bin=$(slot_binary Terminal "$PICK_TERMINAL")
|
|
fm_bin=$(slot_binary FileManager "$PICK_FILEMANAGER")
|
|
|
|
sed \
|
|
-e "s/^\$terminal = .*/\$terminal = ${terminal_bin}/" \
|
|
-e "s/^\$fileManager = .*/\$fileManager = ${fm_bin}/" \
|
|
"$src_path"
|
|
}
|
|
|
|
build_package_list() {
|
|
local pkgs=()
|
|
mapfile -t pkgs < "$REPO_DIR/packages.txt"
|
|
|
|
pkgs+=("$(slot_package Terminal "$PICK_TERMINAL")")
|
|
pkgs+=("$(slot_package FileManager "$PICK_FILEMANAGER")")
|
|
pkgs+=("$(slot_package Mail "$PICK_MAIL")")
|
|
pkgs+=("$(slot_package CloudSync "$PICK_CLOUDSYNC")")
|
|
|
|
local toggle pkg
|
|
for toggle in "${PICK_TOGGLES[@]}"; do
|
|
[[ -z "$toggle" ]] && continue
|
|
for pkg in $(toggle_packages "$toggle"); do
|
|
pkgs+=("$pkg")
|
|
done
|
|
done
|
|
|
|
printf '%s\n' "${pkgs[@]}" | awk '!seen[$0]++' | tr '\n' ' '
|
|
}
|
|
|
|
install_session_target() {
|
|
mkdir -p "$CONFIG_HOME/systemd/user"
|
|
cat > "$CONFIG_HOME/systemd/user/hyprland-session.target" <<'EOF'
|
|
[Unit]
|
|
Description=Hyprland Session Target
|
|
Requires=graphical-session.target
|
|
After=graphical-session.target
|
|
Wants=xdg-desktop-autostart.target
|
|
After=xdg-desktop-autostart.target
|
|
EOF
|
|
|
|
systemctl --user daemon-reload
|
|
systemctl --user add-wants hyprland-session.target dms.service
|
|
}
|
|
|
|
configure_dms_dock() {
|
|
if ! command -v dms >/dev/null 2>&1; then
|
|
echo "dotevo: dms not on PATH yet, skipping dock settings -- log into Hyprland once, then re-run dotevo (or run manually: dms ipc call settings set showDock true)"
|
|
return 0
|
|
fi
|
|
|
|
if ! dms ipc call settings get showDock >/dev/null 2>&1; then
|
|
echo "dotevo: DMS not running yet, skipping dock settings -- log into Hyprland once, then re-run dotevo (or run manually: dms ipc call settings set showDock true / dockAutoHide true / dockUseOverlayLayer true)"
|
|
return 0
|
|
fi
|
|
|
|
dms ipc call settings set showDock true
|
|
dms ipc call settings set dockAutoHide true
|
|
dms ipc call settings set dockUseOverlayLayer true
|
|
}
|
|
|
|
backup_if_exists() {
|
|
local target="$1"
|
|
[[ -e "$target" ]] || return 0
|
|
local backup_root
|
|
backup_root="$CONFIG_HOME/old2026_1/dotevo-backup-$(date +%Y%m%d-%H%M%S)"
|
|
local rel="${target#"$HOME"/}"
|
|
mkdir -p "$(dirname "$backup_root/$rel")"
|
|
mv "$target" "$backup_root/$rel"
|
|
}
|
|
|
|
clone_or_update_repo() {
|
|
local url="$1" dest="$2"
|
|
if [[ -d "$dest/.git" ]]; then
|
|
git -C "$dest" pull --ff-only
|
|
else
|
|
mkdir -p "$(dirname "$dest")"
|
|
git clone --depth 1 "$url" "$dest"
|
|
fi
|
|
}
|
|
|
|
run_component_picker() {
|
|
if [[ "${DOTEVO_NONINTERACTIVE:-0}" == "1" ]]; then
|
|
read -ra PICK_COMPONENTS <<< "${DOTEVO_COMPONENTS:?DOTEVO_COMPONENTS required in non-interactive mode}"
|
|
return 0
|
|
fi
|
|
|
|
local raw
|
|
while true; do
|
|
raw=$(whiptail --title "dotevo" --checklist \
|
|
"Choose what to set up (space to toggle, enter to confirm)" 15 60 2 \
|
|
Hyprland "Hyprland + DMS desktop rice" ON \
|
|
TerminalLook "zsh + prompt (Powerlevel10k or Kali)" OFF \
|
|
3>&1 1>&2 2>&3)
|
|
read -ra PICK_COMPONENTS <<< "$(echo "$raw" | tr -d '"')"
|
|
[[ "${#PICK_COMPONENTS[@]}" -gt 0 ]] && break
|
|
whiptail --title "dotevo" --msgbox "Pick at least one." 8 40
|
|
done
|
|
}
|
|
|
|
apply_hyprland() {
|
|
if ! check_arch; then
|
|
echo "dotevo: skipping Hyprland rice -- pacman not found"
|
|
return 0
|
|
fi
|
|
|
|
run_picker
|
|
|
|
if ! confirm_summary; then
|
|
echo "dotevo: Hyprland rice cancelled, nothing was changed."
|
|
return 0
|
|
fi
|
|
|
|
backup_if_exists "$CONFIG_HOME/hypr/hyprland.conf"
|
|
backup_if_exists "$CONFIG_HOME/hypr/extras.conf"
|
|
backup_if_exists "$CONFIG_HOME/xdg-terminals.list"
|
|
backup_if_exists "$LOCAL_BIN/capture-menu.sh"
|
|
backup_if_exists "$LOCAL_BIN/screenshot.sh"
|
|
backup_if_exists "$LOCAL_BIN/toggle-recording.sh"
|
|
|
|
# Sync + upgrade first. Without this, a local package database that's
|
|
# drifted from the mirrors can reference a package build that's already
|
|
# been rotated off every mirror (404 on install), and a bare `-Sy`
|
|
# without `-u` risks a partial upgrade -- unsupported on Arch and can
|
|
# break dependencies. `-Syu` is the only safe way to bring the database
|
|
# in sync before installing anything new.
|
|
sudo pacman -Syu --noconfirm
|
|
|
|
local pkg_list
|
|
pkg_list="$(build_package_list)"
|
|
# shellcheck disable=SC2086
|
|
sudo pacman -S --needed --noconfirm $pkg_list
|
|
|
|
mkdir -p "$CONFIG_HOME/hypr"
|
|
render_hyprland_conf "$REPO_DIR/hypr/hyprland.conf" > "$CONFIG_HOME/hypr/hyprland.conf"
|
|
build_extras_conf > "$CONFIG_HOME/hypr/extras.conf"
|
|
terminal_desktop_id "$PICK_TERMINAL" > "$CONFIG_HOME/xdg-terminals.list"
|
|
|
|
install_session_target
|
|
configure_dms_dock
|
|
|
|
if [[ " ${PICK_TOGGLES[*]} " == *" ScreenCapture "* ]]; then
|
|
mkdir -p "$LOCAL_BIN"
|
|
cp "$REPO_DIR/local-bin/capture-menu.sh" "$LOCAL_BIN/"
|
|
cp "$REPO_DIR/local-bin/screenshot.sh" "$LOCAL_BIN/"
|
|
cp "$REPO_DIR/local-bin/toggle-recording.sh" "$LOCAL_BIN/"
|
|
chmod +x "$LOCAL_BIN/capture-menu.sh" "$LOCAL_BIN/screenshot.sh" "$LOCAL_BIN/toggle-recording.sh"
|
|
fi
|
|
|
|
if [[ "$PICK_CLOUDSYNC" == "Syncthing" ]]; then
|
|
systemctl enable --now --user syncthing.service
|
|
fi
|
|
|
|
if [[ -n "${HYPRLAND_INSTANCE_SIGNATURE:-}" ]]; then
|
|
hyprctl reload
|
|
else
|
|
echo "dotevo: log into Hyprland to see changes."
|
|
fi
|
|
}
|
|
|
|
run_terminal_look_picker() {
|
|
if [[ "${DOTEVO_NONINTERACTIVE:-0}" == "1" ]]; then
|
|
PICK_TERMINAL_LOOK="${DOTEVO_TERMINAL_LOOK:?DOTEVO_TERMINAL_LOOK required in non-interactive mode}"
|
|
return 0
|
|
fi
|
|
|
|
# shellcheck disable=SC2034
|
|
PICK_TERMINAL_LOOK=$(whiptail --title "dotevo" --radiolist \
|
|
"Choose your terminal look" 12 60 2 \
|
|
P10k "Powerlevel10k (your current setup)" ON \
|
|
Kali "Kali-style box prompt" OFF \
|
|
3>&1 1>&2 2>&3)
|
|
}
|
|
|
|
write_zshrc_p10k() {
|
|
local dest="$1"
|
|
cat > "$dest" <<'EOF'
|
|
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
|
|
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
|
|
fi
|
|
|
|
export ZSH="$HOME/.oh-my-zsh"
|
|
export ZSH_CUSTOM="$HOME/.dotevo-zsh-custom"
|
|
ZSH_THEME="powerlevel10k/powerlevel10k"
|
|
plugins=(git fzf zsh-autosuggestions zsh-syntax-highlighting zsh-history-substring-search)
|
|
source $ZSH/oh-my-zsh.sh
|
|
|
|
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
|
|
|
|
if command -v fzf >/dev/null 2>&1; then
|
|
eval "$(fzf --zsh)"
|
|
fi
|
|
EOF
|
|
}
|
|
|
|
apply_terminal_look_p10k() {
|
|
clone_or_update_repo "https://github.com/ohmyzsh/ohmyzsh.git" "$OMZ_DIR"
|
|
clone_or_update_repo "https://github.com/romkatv/powerlevel10k.git" "$ZSH_CUSTOM_DIR/themes/powerlevel10k"
|
|
clone_or_update_repo "https://github.com/zsh-users/zsh-autosuggestions.git" "$ZSH_CUSTOM_DIR/plugins/zsh-autosuggestions"
|
|
clone_or_update_repo "https://github.com/zsh-users/zsh-syntax-highlighting.git" "$ZSH_CUSTOM_DIR/plugins/zsh-syntax-highlighting"
|
|
clone_or_update_repo "https://github.com/zsh-users/zsh-history-substring-search.git" "$ZSH_CUSTOM_DIR/plugins/zsh-history-substring-search"
|
|
|
|
backup_if_exists "$HOME/.p10k.zsh"
|
|
cp "$REPO_DIR/terminal/p10k/.p10k.zsh" "$HOME/.p10k.zsh"
|
|
|
|
backup_if_exists "$HOME/.zshrc"
|
|
write_zshrc_p10k "$HOME/.zshrc"
|
|
}
|
|
|
|
write_zshrc_kali() {
|
|
local dest="$1"
|
|
cat > "$dest" <<'EOF'
|
|
HISTFILE=~/.zsh_history
|
|
HISTSIZE=10000
|
|
SAVEHIST=10000
|
|
setopt share_history hist_ignore_dups
|
|
|
|
source "$HOME/.dotevo/kali-prompt.zsh"
|
|
source "$HOME/.dotevo-zsh-custom/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh"
|
|
source "$HOME/.dotevo-zsh-custom/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh"
|
|
source "$HOME/.dotevo-zsh-custom/plugins/zsh-history-substring-search/zsh-history-substring-search.zsh"
|
|
|
|
if command -v fzf >/dev/null 2>&1; then
|
|
eval "$(fzf --zsh)"
|
|
fi
|
|
EOF
|
|
}
|
|
|
|
apply_terminal_look_kali() {
|
|
clone_or_update_repo "https://github.com/zsh-users/zsh-autosuggestions.git" "$ZSH_CUSTOM_DIR/plugins/zsh-autosuggestions"
|
|
clone_or_update_repo "https://github.com/zsh-users/zsh-syntax-highlighting.git" "$ZSH_CUSTOM_DIR/plugins/zsh-syntax-highlighting"
|
|
clone_or_update_repo "https://github.com/zsh-users/zsh-history-substring-search.git" "$ZSH_CUSTOM_DIR/plugins/zsh-history-substring-search"
|
|
|
|
mkdir -p "$ASSETS_DIR"
|
|
backup_if_exists "$ASSETS_DIR/kali-prompt.zsh"
|
|
cp "$REPO_DIR/terminal/kali/prompt.zsh" "$ASSETS_DIR/kali-prompt.zsh"
|
|
|
|
backup_if_exists "$HOME/.zshrc"
|
|
write_zshrc_kali "$HOME/.zshrc"
|
|
}
|
|
|
|
chsh_to_zsh() {
|
|
local zsh_path
|
|
zsh_path="$(command -v zsh)"
|
|
if [[ "${SHELL:-}" != "$zsh_path" ]]; then
|
|
chsh -s "$zsh_path"
|
|
fi
|
|
}
|
|
|
|
apply_terminal_look() {
|
|
if ! install_terminal_prereqs; then
|
|
echo "dotevo: skipping Terminal look -- prerequisites unavailable"
|
|
return 0
|
|
fi
|
|
|
|
run_terminal_look_picker
|
|
|
|
case "$PICK_TERMINAL_LOOK" in
|
|
P10k) apply_terminal_look_p10k ;;
|
|
Kali) apply_terminal_look_kali ;;
|
|
*) echo "dotevo: unknown terminal look: $PICK_TERMINAL_LOOK" >&2; return 1 ;;
|
|
esac
|
|
|
|
chsh_to_zsh
|
|
}
|
|
|
|
main() {
|
|
ensure_repo_files
|
|
run_component_picker
|
|
|
|
if [[ " ${PICK_COMPONENTS[*]} " == *" Hyprland "* ]]; then
|
|
apply_hyprland
|
|
fi
|
|
|
|
if [[ " ${PICK_COMPONENTS[*]} " == *" TerminalLook "* ]]; then
|
|
apply_terminal_look
|
|
fi
|
|
|
|
echo "dotevo: done."
|
|
}
|
|
|
|
# `return` only succeeds at top level when the script is being sourced (as
|
|
# tests/install.bats does). Direct execution -- a real file, `bash -c "..."`,
|
|
# or `bash <(curl ...)` process substitution -- all fail `return`, so `main`
|
|
# runs. This is more robust here than comparing $BASH_SOURCE/$0: under
|
|
# `bash -c "$(curl ...)"` there's no backing file at all, so BASH_SOURCE is
|
|
# empty and $0 is just "bash" -- they'd never match even with a safe default.
|
|
if ! (return 0 2>/dev/null); then
|
|
main "$@"
|
|
fi
|