Compare commits
16
Commits
75d031e222
...
8a6f0fe413
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a6f0fe413 | ||
|
|
cc9282dfd4 | ||
|
|
6183c7859b | ||
|
|
2c5fe486fe | ||
|
|
efd3a0e754 | ||
|
|
5a0629468b | ||
|
|
73edf11a23 | ||
|
|
f6b2d929f2 | ||
|
|
56016bda3b | ||
|
|
5693fd1680 | ||
|
|
153e64d785 | ||
|
|
3a795b290b | ||
|
|
540046d3ed | ||
|
|
715f52192d | ||
|
|
eb1a79352f | ||
|
|
0dcd754e1e |
No files matched your search
@@ -0,0 +1 @@
|
||||
.worktrees/
|
||||
@@ -1,31 +1,30 @@
|
||||
# hyprevo
|
||||
# dotevo
|
||||
|
||||
A one-command installer for Hyprland + DankMaterialShell (DMS) on any
|
||||
Arch-based Linux (plain Arch, CachyOS, Manjaro, EndeavourOS, or anything else
|
||||
with `pacman`). Installs the desktop shell itself unconditionally, then lets
|
||||
you pick which extra apps you want via an interactive menu -- no fixed bundle
|
||||
of KDE tools you didn't ask for.
|
||||
A one-command installer for popular Linux desktop and terminal configurations.
|
||||
Currently includes **Hyprland rice** (Hyprland + DankMaterialShell) and
|
||||
**Terminal look** (zsh with Powerlevel10k or Kali-style prompt) — more modules
|
||||
coming later.
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
bash -c "$(curl -fsSL https://git.edemilov.ru/edemilov/hyprevo/raw/branch/master/install.sh)"
|
||||
bash -c "$(curl -fsSL https://git.edemilov.ru/edemilov/dotevo/raw/branch/master/install.sh)"
|
||||
```
|
||||
|
||||
(Works from any login shell, including fish/zsh -- it's plain command
|
||||
substitution, not bash's `<(...)` process substitution, which fish doesn't
|
||||
support.)
|
||||
|
||||
## What's always installed
|
||||
|
||||
Hyprland, DankMaterialShell (panel bar + dock + app launcher), the scrolling
|
||||
(niri-style) window layout, workspace/window keybinds, and a fix for a
|
||||
common secret-service hang (`ksecretd`).
|
||||
|
||||
## What you pick
|
||||
|
||||
A `whiptail` menu walks you through:
|
||||
A `whiptail` menu walks you through component selection first, then
|
||||
module-specific options:
|
||||
|
||||
**Top-level component checklist** (space to toggle, enter to confirm):
|
||||
- **Hyprland** -- Desktop rice (Hyprland + DankMaterialShell + keybinds) *(on by default)*
|
||||
- **TerminalLook** -- zsh + prompt style (Powerlevel10k or Kali) *(off by default)*
|
||||
|
||||
If you pick **Hyprland**, you'll then choose:
|
||||
- **Terminal** -- Konsole / Terminator / Kitty / Alacritty (pick one, becomes your `$terminal` default)
|
||||
- **File manager** -- Dolphin / Nautilus / Thunar (pick one)
|
||||
- **Mail client** -- Thunderbird / KMail (pick one)
|
||||
@@ -34,18 +33,28 @@ A `whiptail` menu walks you through:
|
||||
- **Screen capture** -- grim/slurp/satty/wf-recorder behind one Print-key menu (yes/no)
|
||||
- **Bitwarden** (yes/no)
|
||||
|
||||
If you pick **TerminalLook**, you'll choose:
|
||||
- **Powerlevel10k** -- Recreates your current zsh setup
|
||||
- **Kali-style** -- Fresh box-drawing prompt
|
||||
|
||||
Want a second terminal or a different mail client later? Install it manually
|
||||
afterward -- the picker is single-choice per slot on purpose.
|
||||
|
||||
## What it does NOT do
|
||||
## Hyprland rice
|
||||
|
||||
The Hyprland-rice module installs Hyprland, DankMaterialShell (panel bar + dock + app launcher), the scrolling
|
||||
(niri-style) window layout, workspace/window keybinds, and a fix for a
|
||||
common secret-service hang (`ksecretd`).
|
||||
|
||||
### What it does NOT do
|
||||
|
||||
- Doesn't touch an existing desktop environment -- Hyprland installs as an
|
||||
additional login session, nothing else is removed or reconfigured.
|
||||
- Never needs the AUR -- everything it installs is in Arch's official repos.
|
||||
- Doesn't overwrite your existing configs without backing them up first
|
||||
(`~/.config/old2026_1/hyprevo-backup-<timestamp>/`).
|
||||
(`~/.config/old2026_1/dotevo-backup-<timestamp>/`).
|
||||
|
||||
## Keybind cheat-sheet
|
||||
### Keybind cheat-sheet
|
||||
|
||||
| Keys | Action |
|
||||
|---|---|
|
||||
@@ -67,8 +76,40 @@ afterward -- the picker is single-choice per slot on purpose.
|
||||
| `Super + mouse drag` (left/right button) | Move/resize window |
|
||||
| `Print` | Capture menu (screenshot/record) -- only if Screen capture was picked |
|
||||
|
||||
## Terminal look
|
||||
|
||||
The Terminal-look module sets up zsh with your chosen prompt style:
|
||||
|
||||
- **Powerlevel10k** -- Recreates your current setup: Oh My Zsh + Powerlevel10k theme + standard plugins (git, fzf, zsh-autosuggestions, zsh-syntax-highlighting, zsh-history-substring-search) + `.p10k.zsh` config + fzf integration. The theme renders your prompt with git branch/status icons and a right-side return code.
|
||||
|
||||
- **Kali-style** -- A fresh alternative: zsh with Kali Linux's box-drawing prompt style + core plugins (zsh-autosuggestions, zsh-syntax-highlighting, zsh-history-substring-search) + fzf integration. No Oh My Zsh or complex theme framework, just a simple box prompt and essentials.
|
||||
|
||||
Both looks install the terminal prerequisites (zsh, git, curl, fzf) across Arch, Debian, Fedora, and openSUSE via their native package managers.
|
||||
|
||||
Once a prompt style is chosen and applied, the module automatically changes
|
||||
your login shell to zsh via `chsh` (if it isn't already zsh). `chsh` will
|
||||
prompt you for your Unix account password (via PAM) when it runs.
|
||||
|
||||
`~/.zshrc` is replaced wholesale, not merged: any existing personal
|
||||
customizations (PATH exports, environment variables, custom functions,
|
||||
aliases, etc.) in your current `.zshrc` are moved into the backup directory
|
||||
rather than preserved in the new file. Check
|
||||
`~/.config/old2026_1/dotevo-backup-<timestamp>/` afterward if you had custom
|
||||
additions you want to bring back.
|
||||
|
||||
### What it does NOT do
|
||||
|
||||
- Doesn't touch an existing shell config without backing it up first
|
||||
(`~/.config/old2026_1/dotevo-backup-<timestamp>/`).
|
||||
- Doesn't add any CLI tools beyond the prompt framework and plugins
|
||||
(zsh, git, curl, fzf, and the theme/prompt files themselves).
|
||||
|
||||
## Customize
|
||||
|
||||
Re-run the installer to change your picks (it rebuilds `~/.config/hypr/extras.conf`
|
||||
fresh each time). For anything more specific, edit `~/.config/hypr/hyprland.conf`
|
||||
or `~/.config/hypr/extras.conf` directly afterward.
|
||||
Re-run the installer to change your picks. For the Hyprland-rice module,
|
||||
it rebuilds `~/.config/hypr/extras.conf` fresh each time. For the Terminal-look
|
||||
module, it re-runs the setup and updates your `.zshrc` and prompt config.
|
||||
|
||||
For anything more specific:
|
||||
- Hyprland: edit `~/.config/hypr/hyprland.conf` or `~/.config/hypr/extras.conf` directly
|
||||
- Terminal: modify your `.zshrc` or `~/.p10k.zsh` (Powerlevel10k) / `~/.dotevo/kali-prompt.zsh` (Kali)
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,202 @@
|
||||
# dotevo: Rename + Terminal-Look Module — Design
|
||||
|
||||
Extends `hyprevo` (public one-command Arch-based Hyprland+DMS installer,
|
||||
see [`2026-08-29-hyprevo-design-v2.md`](2026-08-29-hyprevo-design-v2.md))
|
||||
into a broader personal-environment installer covering more than one
|
||||
desktop piece. This round: rename the repo and add a **Terminal-look**
|
||||
module. A future round adds a **KDE-rice** module (deferred — needs its own
|
||||
design pass, see Non-goals).
|
||||
|
||||
## Goal
|
||||
|
||||
One public repo, renamed `dotevo`, where each environment piece is an
|
||||
independent, separately-picked module — not a single fixed bundle. This
|
||||
round ships two modules:
|
||||
|
||||
1. **Hyprland + DMS rice** — the existing `hyprevo` flow, unchanged.
|
||||
2. **Terminal look** — new. Sets up zsh with a choice of look:
|
||||
- **Powerlevel10k** — reproduces the user's actual current setup
|
||||
(oh-my-zsh + p10k + zsh-autosuggestions + zsh-syntax-highlighting +
|
||||
zsh-history-substring-search).
|
||||
- **Kali** — a fresh, hand-rolled prompt matching Kali Linux's real
|
||||
default (`┌──(user㉿host)-[~]` box style), no oh-my-zsh at all, same
|
||||
three plugin scripts layered on top for the same fish-like typing
|
||||
feel.
|
||||
|
||||
Critically, **Terminal look must work on any Linux distro** (the motivating
|
||||
case is bare Debian/Proxmox hosts — old bash, no DE, `apt` not `pacman`),
|
||||
while Hyprland rice stays Arch/pacman-only as before. This is why the two
|
||||
are picked independently rather than forced together.
|
||||
|
||||
## Non-goals (this round)
|
||||
|
||||
- **KDE-rice module**: deferred. The current `dotfiles` repo's KDE configs
|
||||
are a raw personal dump (this machine's `kdeglobals`/`kwinrc`/etc.), not
|
||||
a curated public "rice" — building that is its own design/build round,
|
||||
same treatment Hyprland's `hyprland.conf` already got. The component
|
||||
picker below leaves a slot for it, but it isn't built yet.
|
||||
- **GUI/app wrapper**: mentioned as a future direction but out of scope.
|
||||
Keeping the shell-script core clean and callable on its own (no assumed
|
||||
terminal UI beyond `whiptail`) means a future GUI can shell out to the
|
||||
same `install.sh` without a rewrite.
|
||||
- Same non-goals `hyprevo` v2 already had for the Hyprland module: no AUR,
|
||||
no hardware-specific tuning, doesn't touch an existing DE, Hyprland's own
|
||||
app-picker slots stay single-choice.
|
||||
- Terminal-look doesn't add config toggles/extras beyond the two looks
|
||||
(no zoxide/eza/bat wiring, etc.) — matches "just the exact setup, no
|
||||
toggles" from the design discussion. Anyone who wants more installs it
|
||||
themselves afterward.
|
||||
|
||||
## Component picker (new top-level step)
|
||||
|
||||
Before any of the existing Hyprland-specific screens, one `whiptail
|
||||
--checklist` (multi-select, unlike the single-choice slots inside Hyprland
|
||||
setup):
|
||||
|
||||
```
|
||||
[x] Hyprland + DMS desktop rice
|
||||
[ ] Terminal look (zsh + prompt)
|
||||
```
|
||||
|
||||
(KDE rice joins this list as a third checkbox once it's built — no
|
||||
structural change needed then, just a new case in the dispatch below.)
|
||||
|
||||
At least one box must be checked — re-show the screen if the user confirms
|
||||
with nothing selected. Selected modules run in order: Hyprland rice (if
|
||||
checked) → Terminal look (if checked). Each module owns its own
|
||||
prerequisite check, backup, and idempotency — picking one doesn't require
|
||||
or block the other.
|
||||
|
||||
**Hyprland rice module**: runs its `pacman` check *inside* the module, not
|
||||
at the top of the script. If `pacman` is missing, that module alone prints
|
||||
a one-line skip message and continues to whatever else was picked, instead
|
||||
of aborting the whole run — this is what lets someone select both boxes
|
||||
inadvertently on a non-Arch box without losing Terminal-look.
|
||||
|
||||
## Terminal-look module
|
||||
|
||||
### Look A — Powerlevel10k (reproduce current setup)
|
||||
|
||||
- `ZSH="$HOME/.oh-my-zsh"`, `ZSH_CUSTOM="$HOME/.dotevo-zsh-custom"` — both
|
||||
user-owned. (This directly fixes the real bug found while scoping this
|
||||
project: CachyOS installs oh-my-zsh system-wide at
|
||||
`/usr/share/oh-my-zsh`, root-owned, so anything dropped in the
|
||||
conventional `~/.oh-my-zsh/custom/` path silently never loads. dotevo
|
||||
never touches that system path — always its own user-owned tree.)
|
||||
- git-clone (or `git -C <dir> pull` if already present — idempotent) into
|
||||
that tree:
|
||||
- `ohmyzsh/ohmyzsh` → `~/.oh-my-zsh`
|
||||
- `romkatv/powerlevel10k` → `$ZSH_CUSTOM/themes/powerlevel10k`
|
||||
- `zsh-users/zsh-autosuggestions` → `$ZSH_CUSTOM/plugins/zsh-autosuggestions`
|
||||
- `zsh-users/zsh-syntax-highlighting` → `$ZSH_CUSTOM/plugins/zsh-syntax-highlighting`
|
||||
- `zsh-users/zsh-history-substring-search` → `$ZSH_CUSTOM/plugins/zsh-history-substring-search`
|
||||
- Ships `terminal/p10k/.p10k.zsh` (the user's actual current config) →
|
||||
`~/.p10k.zsh`.
|
||||
- Writes `~/.zshrc`: p10k instant-prompt block, `ZSH_THEME="powerlevel10k/powerlevel10k"`,
|
||||
`plugins=(git fzf zsh-autosuggestions zsh-syntax-highlighting zsh-history-substring-search)`,
|
||||
`source $ZSH/oh-my-zsh.sh`, `source ~/.p10k.zsh`, `fzf --zsh` (modern fzf's
|
||||
built-in shell-integration flag — no hardcoded distro-specific
|
||||
`key-bindings.zsh`/`completion.zsh` paths needed).
|
||||
|
||||
### Look B — Kali (fresh)
|
||||
|
||||
- No oh-my-zsh clone at all. Only the three standalone plugin repos,
|
||||
git-cloned into `$ZSH_CUSTOM/plugins/...` (same paths as above, so
|
||||
switching looks later doesn't leave orphaned clones).
|
||||
- Ships `terminal/kali/prompt.zsh` — the hand-rolled prompt: `autoload -Uz
|
||||
colors && colors`, the actual Kali `PROMPT`/`RPROMPT` (box-drawing
|
||||
characters, red/blue segments, root shown in red), `autoload -Uz compinit
|
||||
&& compinit`.
|
||||
- Writes `~/.zshrc`: sources `prompt.zsh`, then the three plugin scripts
|
||||
directly by their cloned path (`source
|
||||
$ZSH_CUSTOM/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh`, etc. —
|
||||
no framework loading them), `fzf --zsh`.
|
||||
|
||||
### Shared steps (both looks)
|
||||
|
||||
1. **Package-manager detection** for exactly four binaries needed either
|
||||
way — `zsh git curl fzf`:
|
||||
```
|
||||
pacman -> pacman -S --needed --noconfirm zsh git curl fzf
|
||||
apt -> apt-get install -y zsh git curl fzf
|
||||
dnf -> dnf install -y zsh git curl fzf
|
||||
zypper -> zypper install -y zsh git curl fzf
|
||||
```
|
||||
Anything else: print "package manager not recognized, install `zsh git
|
||||
curl fzf` manually" and stop *this module only* (Hyprland module, if
|
||||
also picked, is unaffected).
|
||||
2. **Backup**: any existing `~/.zshrc` / `~/.p10k.zsh` moves to
|
||||
`~/old2026_1/dotevo-backup-<timestamp>/` first (same never-overwrite
|
||||
rule as `hyprevo`'s `~/.config/old2026_1/...`, just rooted at `$HOME`
|
||||
since these files live there, not under `.config`).
|
||||
3. **Look picker**: one `whiptail --radiolist` — Powerlevel10k / Kali.
|
||||
4. **Shell change**: `chsh -s "$(command -v zsh)"` only if `$SHELL` isn't
|
||||
already zsh.
|
||||
5. Re-running the module re-picks the look and rewrites `~/.zshrc` fresh
|
||||
each time (same "rebuilt, not diffed" idempotency pattern as
|
||||
`extras.conf`) — the backup step still fires first, so nothing from a
|
||||
previous run is silently lost.
|
||||
|
||||
## Repo layout (additions)
|
||||
|
||||
```
|
||||
dotevo/ # renamed from hyprevo
|
||||
├── install.sh # + component checklist, + terminal-look module, dispatch logic
|
||||
├── terminal/
|
||||
│ ├── p10k/
|
||||
│ │ └── .p10k.zsh # shipped, the user's real current config
|
||||
│ └── kali/
|
||||
│ └── prompt.zsh # hand-rolled PROMPT/RPROMPT
|
||||
├── hypr/... # unchanged
|
||||
├── local-bin/... # unchanged
|
||||
├── packages.txt # unchanged (Hyprland-only; terminal packages mapped inline like existing app-picker packages)
|
||||
└── README.md # updated — see below
|
||||
```
|
||||
|
||||
## README changes
|
||||
|
||||
- New name/description at the top: personal environment installer, pick
|
||||
your pieces (Hyprland rice today, more later).
|
||||
- Install one-liner updated to the new repo path once renamed.
|
||||
- New section: **Terminal look** — what each look includes, the same
|
||||
"what it does NOT do" style callout (doesn't touch an existing shell
|
||||
config without backing it up, doesn't add extra CLI tools beyond the
|
||||
picked look).
|
||||
- Existing Hyprland sections (keybind cheat-sheet, app menu table, etc.)
|
||||
carried over unchanged, just re-scoped as "the Hyprland-rice module"
|
||||
rather than the whole repo.
|
||||
|
||||
## Rename mechanics
|
||||
|
||||
- Gitea repo rename `hyprevo` → `dotevo` via the web UI (Settings →
|
||||
repository name) on `git.edemilov.ru`.
|
||||
- Update the local remote if the URL changes, update the install one-liner
|
||||
everywhere it's referenced (README, any vault notes, memory).
|
||||
- Note for the plan: confirm whether this Gitea version leaves an
|
||||
auto-redirect from the old `hyprevo` path — if not, the old
|
||||
curl-one-liner in any existing bookmarks/notes breaks silently, worth a
|
||||
one-line README note either way.
|
||||
|
||||
## Testing plan
|
||||
|
||||
Same discipline as `hyprevo` v2 (TDD via `bats` + `shellcheck`, existing
|
||||
`tests/install.bats` extended rather than replaced):
|
||||
|
||||
- New bats tests for: package-manager detection (mock each of the four),
|
||||
backup-before-write for `.zshrc`/`.p10k.zsh`, idempotent re-run (second
|
||||
run with a different look picked leaves no leftover config from the
|
||||
first), the "Hyprland module skips cleanly when `pacman` missing, other
|
||||
picked modules still run" behavior.
|
||||
- **Live test 1 (this desktop, Cachyos7800xt)**: already has the real
|
||||
p10k setup — running Terminal-look → Powerlevel10k here is the
|
||||
regression check (does it faithfully reproduce what's already dialed
|
||||
in, backup working correctly on a machine with real data to lose).
|
||||
Also run it a second time picking Kali on the same box to visually
|
||||
confirm the fresh prompt renders correctly.
|
||||
- **Live test 2 (a Proxmox host, e.g. `pile` or `vanga`)**: bash-only
|
||||
Debian box, no zsh installed — the actual motivating cross-distro case.
|
||||
Confirms `apt` detection path, git-clone fallback (no CachyOS-style
|
||||
packages available there), and `chsh` working correctly outside Arch.
|
||||
- **Regression**: re-run the existing Hyprland-only flow (component
|
||||
picker with only that box checked) to confirm it behaves exactly as
|
||||
`hyprevo` v2 did — no behavior change for that module.
|
||||
+220
-42
@@ -8,16 +8,48 @@ set -euo pipefail
|
||||
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-}")" && pwd)"
|
||||
CONFIG_HOME="${CONFIG_HOME:-${XDG_CONFIG_HOME:-$HOME/.config}}"
|
||||
LOCAL_BIN="${LOCAL_BIN:-$HOME/.local/bin}"
|
||||
HYPREVO_RAW_BASE="${HYPREVO_RAW_BASE:-https://git.edemilov.ru/edemilov/hyprevo/raw/branch/master}"
|
||||
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() needs into a fresh
|
||||
# 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() {
|
||||
@@ -27,13 +59,15 @@ ensure_repo_files() {
|
||||
|
||||
local tmp_dir
|
||||
tmp_dir="$(mktemp -d)"
|
||||
mkdir -p "$tmp_dir/hypr" "$tmp_dir/local-bin"
|
||||
mkdir -p "$tmp_dir/hypr" "$tmp_dir/local-bin" "$tmp_dir/terminal/p10k" "$tmp_dir/terminal/kali"
|
||||
|
||||
curl -fsSL "$HYPREVO_RAW_BASE/packages.txt" -o "$tmp_dir/packages.txt"
|
||||
curl -fsSL "$HYPREVO_RAW_BASE/hypr/hyprland.conf" -o "$tmp_dir/hypr/hyprland.conf"
|
||||
curl -fsSL "$HYPREVO_RAW_BASE/local-bin/capture-menu.sh" -o "$tmp_dir/local-bin/capture-menu.sh"
|
||||
curl -fsSL "$HYPREVO_RAW_BASE/local-bin/screenshot.sh" -o "$tmp_dir/local-bin/screenshot.sh"
|
||||
curl -fsSL "$HYPREVO_RAW_BASE/local-bin/toggle-recording.sh" -o "$tmp_dir/local-bin/toggle-recording.sh"
|
||||
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"
|
||||
}
|
||||
@@ -52,7 +86,7 @@ slot_package() {
|
||||
Mail:KMail) echo "kmail" ;;
|
||||
CloudSync:Nextcloud) echo "nextcloud-client" ;;
|
||||
CloudSync:Syncthing) echo "syncthing" ;;
|
||||
*) echo "hyprevo: unknown slot/choice pair: $slot/$choice" >&2; return 1 ;;
|
||||
*) echo "dotevo: unknown slot/choice pair: $slot/$choice" >&2; return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -69,7 +103,7 @@ slot_binary() {
|
||||
Mail:Thunderbird) echo "thunderbird" ;;
|
||||
Mail:KMail) echo "kmail" ;;
|
||||
CloudSync:Nextcloud) echo "nextcloud --background" ;;
|
||||
*) echo "hyprevo: unknown slot/choice pair: $slot/$choice" >&2; return 1 ;;
|
||||
*) echo "dotevo: unknown slot/choice pair: $slot/$choice" >&2; return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -80,7 +114,7 @@ terminal_desktop_id() {
|
||||
Terminator) echo "terminator.desktop" ;;
|
||||
Kitty) echo "kitty.desktop" ;;
|
||||
Alacritty) echo "Alacritty.desktop" ;;
|
||||
*) echo "hyprevo: unknown terminal choice: $choice" >&2; return 1 ;;
|
||||
*) echo "dotevo: unknown terminal choice: $choice" >&2; return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -90,42 +124,42 @@ toggle_packages() {
|
||||
Telegram) echo "telegram-desktop" ;;
|
||||
Bitwarden) echo "bitwarden" ;;
|
||||
ScreenCapture) echo "grim slurp satty wl-clipboard wf-recorder fuzzel libnotify" ;;
|
||||
*) echo "hyprevo: unknown toggle: $toggle" >&2; return 1 ;;
|
||||
*) echo "dotevo: unknown toggle: $toggle" >&2; return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
run_picker() {
|
||||
if [[ "${HYPREVO_NONINTERACTIVE:-0}" == "1" ]]; then
|
||||
PICK_TERMINAL="${HYPREVO_TERMINAL:?HYPREVO_TERMINAL required in non-interactive mode}"
|
||||
PICK_FILEMANAGER="${HYPREVO_FILEMANAGER:?HYPREVO_FILEMANAGER required in non-interactive mode}"
|
||||
PICK_MAIL="${HYPREVO_MAIL:?HYPREVO_MAIL required in non-interactive mode}"
|
||||
PICK_CLOUDSYNC="${HYPREVO_CLOUDSYNC:?HYPREVO_CLOUDSYNC required in non-interactive mode}"
|
||||
read -ra PICK_TOGGLES <<< "${HYPREVO_TOGGLES:-}"
|
||||
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 "hyprevo" --radiolist \
|
||||
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 "hyprevo" --radiolist \
|
||||
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 "hyprevo" --radiolist \
|
||||
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 "hyprevo" --radiolist \
|
||||
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 "hyprevo" --checklist \
|
||||
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)
|
||||
@@ -143,18 +177,18 @@ Telegram: $([[ " ${PICK_TOGGLES[*]} " == *" Telegram "* ]] && echo yes || echo n
|
||||
Screen capture: $([[ " ${PICK_TOGGLES[*]} " == *" ScreenCapture "* ]] && echo yes || echo no)
|
||||
Bitwarden: $([[ " ${PICK_TOGGLES[*]} " == *" Bitwarden "* ]] && echo yes || echo no)"
|
||||
|
||||
if [[ "${HYPREVO_NONINTERACTIVE:-0}" == "1" ]]; then
|
||||
if [[ "${DOTEVO_NONINTERACTIVE:-0}" == "1" ]]; then
|
||||
echo "$summary"
|
||||
return 0
|
||||
fi
|
||||
|
||||
whiptail --title "hyprevo -- confirm" --yesno "$summary
|
||||
whiptail --title "dotevo -- confirm" --yesno "$summary
|
||||
|
||||
Install with these choices?" 18 60
|
||||
}
|
||||
|
||||
build_extras_conf() {
|
||||
echo "# Generated by hyprevo -- rebuilt fresh on every install run, do not hand-edit"
|
||||
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"
|
||||
@@ -222,12 +256,12 @@ EOF
|
||||
|
||||
configure_dms_dock() {
|
||||
if ! command -v dms >/dev/null 2>&1; then
|
||||
echo "hyprevo: dms not on PATH yet, skipping dock settings -- log into Hyprland once, then re-run hyprevo (or run manually: dms ipc call settings set showDock true)"
|
||||
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 "hyprevo: DMS not running yet, skipping dock settings -- log into Hyprland once, then re-run hyprevo (or run manually: dms ipc call settings set showDock true / dockAutoHide true / dockUseOverlayLayer true)"
|
||||
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
|
||||
|
||||
@@ -240,13 +274,54 @@ backup_if_exists() {
|
||||
local target="$1"
|
||||
[[ -e "$target" ]] || return 0
|
||||
local backup_root
|
||||
backup_root="$CONFIG_HOME/old2026_1/hyprevo-backup-$(date +%Y%m%d-%H%M%S)"
|
||||
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"
|
||||
}
|
||||
|
||||
apply() {
|
||||
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"
|
||||
@@ -290,26 +365,129 @@ apply() {
|
||||
if [[ -n "${HYPRLAND_INSTANCE_SIGNATURE:-}" ]]; then
|
||||
hyprctl reload
|
||||
else
|
||||
echo "hyprevo: log into Hyprland to see changes."
|
||||
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() {
|
||||
if ! check_arch; then
|
||||
echo "hyprevo is Arch-based only -- pacman not found"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ensure_repo_files
|
||||
run_picker
|
||||
run_component_picker
|
||||
|
||||
if ! confirm_summary; then
|
||||
echo "hyprevo: cancelled, nothing was changed."
|
||||
exit 0
|
||||
if [[ " ${PICK_COMPONENTS[*]} " == *" Hyprland "* ]]; then
|
||||
apply_hyprland
|
||||
fi
|
||||
|
||||
apply
|
||||
echo "hyprevo: done."
|
||||
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
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# Kali-style prompt -- matches Kali Linux's real default box prompt from
|
||||
# /etc/zsh/zshrc (the kali-defaults package). No framework, no theme
|
||||
# file, just zsh's own prompt escapes and the `colors` module.
|
||||
autoload -Uz colors && colors
|
||||
setopt prompt_subst
|
||||
|
||||
PROMPT='%F{%(#.blue.green)}┌──(%B%F{%(#.red.blue)}%n@%m%b%F{%(#.blue.green)})-[%B%F{reset}%(6~.%-1~/…/%4~.%5~)%b%F{%(#.blue.green)}]
|
||||
└─%B%(#.%F{red}#.%F{blue}$)%b%F{reset} '
|
||||
RPROMPT='%(?..%F{red}[%?]%f)'
|
||||
|
||||
autoload -Uz compinit && compinit
|
||||
@@ -0,0 +1,199 @@
|
||||
# Generated by Powerlevel10k configuration wizard on 2026-05-09 at 14:00 EEST.
|
||||
# Based on romkatv/powerlevel10k/config/p10k-pure.zsh, checksum 07533.
|
||||
# Wizard options: nerdfont-v3 + powerline, large icons, pure, snazzy, 24h time, 2 lines,
|
||||
# compact, transient_prompt, instant_prompt=verbose.
|
||||
# Type `p10k configure` to generate another config.
|
||||
#
|
||||
# Config file for Powerlevel10k with the style of Pure (https://github.com/sindresorhus/pure).
|
||||
#
|
||||
# Differences from Pure:
|
||||
#
|
||||
# - Git:
|
||||
# - `@c4d3ec2c` instead of something like `v1.4.0~11` when in detached HEAD state.
|
||||
# - No automatic `git fetch` (the same as in Pure with `PURE_GIT_PULL=0`).
|
||||
#
|
||||
# Apart from the differences listed above, the replication of Pure prompt is exact. This includes
|
||||
# even the questionable parts. For example, just like in Pure, there is no indication of Git status
|
||||
# being stale; prompt symbol is the same in command, visual and overwrite vi modes; when prompt
|
||||
# doesn't fit on one line, it wraps around with no attempt to shorten it.
|
||||
#
|
||||
# If you like the general style of Pure but not particularly attached to all its quirks, type
|
||||
# `p10k configure` and pick "Lean" style. This will give you slick minimalist prompt while taking
|
||||
# advantage of Powerlevel10k features that aren't present in Pure.
|
||||
|
||||
# Temporarily change options.
|
||||
'builtin' 'local' '-a' 'p10k_config_opts'
|
||||
[[ ! -o 'aliases' ]] || p10k_config_opts+=('aliases')
|
||||
[[ ! -o 'sh_glob' ]] || p10k_config_opts+=('sh_glob')
|
||||
[[ ! -o 'no_brace_expand' ]] || p10k_config_opts+=('no_brace_expand')
|
||||
'builtin' 'setopt' 'no_aliases' 'no_sh_glob' 'brace_expand'
|
||||
|
||||
() {
|
||||
emulate -L zsh -o extended_glob
|
||||
|
||||
# Unset all configuration options.
|
||||
unset -m '(POWERLEVEL9K_*|DEFAULT_USER)~POWERLEVEL9K_GITSTATUS_DIR'
|
||||
|
||||
# Zsh >= 5.1 is required.
|
||||
[[ $ZSH_VERSION == (5.<1->*|<6->.*) ]] || return
|
||||
|
||||
# Prompt colors.
|
||||
local grey='242'
|
||||
local red='#FF5C57'
|
||||
local yellow='#F3F99D'
|
||||
local blue='#57C7FF'
|
||||
local magenta='#FF6AC1'
|
||||
local cyan='#9AEDFE'
|
||||
local white='#F1F1F0'
|
||||
|
||||
# Left prompt segments.
|
||||
typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(
|
||||
# =========================[ Line #1 ]=========================
|
||||
context # user@host
|
||||
dir # current directory
|
||||
vcs # git status
|
||||
command_execution_time # previous command duration
|
||||
# =========================[ Line #2 ]=========================
|
||||
newline # \n
|
||||
virtualenv # python virtual environment
|
||||
prompt_char # prompt symbol
|
||||
)
|
||||
|
||||
# Right prompt segments.
|
||||
typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(
|
||||
# =========================[ Line #1 ]=========================
|
||||
# command_execution_time # previous command duration
|
||||
# virtualenv # python virtual environment
|
||||
# context # user@host
|
||||
time # current time
|
||||
# =========================[ Line #2 ]=========================
|
||||
newline # \n
|
||||
)
|
||||
|
||||
# Basic style options that define the overall prompt look.
|
||||
typeset -g POWERLEVEL9K_BACKGROUND= # transparent background
|
||||
typeset -g POWERLEVEL9K_{LEFT,RIGHT}_{LEFT,RIGHT}_WHITESPACE= # no surrounding whitespace
|
||||
typeset -g POWERLEVEL9K_{LEFT,RIGHT}_SUBSEGMENT_SEPARATOR=' ' # separate segments with a space
|
||||
typeset -g POWERLEVEL9K_{LEFT,RIGHT}_SEGMENT_SEPARATOR= # no end-of-line symbol
|
||||
typeset -g POWERLEVEL9K_VISUAL_IDENTIFIER_EXPANSION= # no segment icons
|
||||
|
||||
# Add an empty line before each prompt except the first. This doesn't emulate the bug
|
||||
# in Pure that makes prompt drift down whenever you use the Alt-C binding from fzf or similar.
|
||||
typeset -g POWERLEVEL9K_PROMPT_ADD_NEWLINE=false
|
||||
|
||||
# Magenta prompt symbol if the last command succeeded.
|
||||
typeset -g POWERLEVEL9K_PROMPT_CHAR_OK_{VIINS,VICMD,VIVIS}_FOREGROUND=$magenta
|
||||
# Red prompt symbol if the last command failed.
|
||||
typeset -g POWERLEVEL9K_PROMPT_CHAR_ERROR_{VIINS,VICMD,VIVIS}_FOREGROUND=$red
|
||||
# Default prompt symbol.
|
||||
typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIINS_CONTENT_EXPANSION='❯'
|
||||
# Prompt symbol in command vi mode.
|
||||
typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VICMD_CONTENT_EXPANSION='❮'
|
||||
# Prompt symbol in visual vi mode is the same as in command mode.
|
||||
typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIVIS_CONTENT_EXPANSION='❮'
|
||||
# Prompt symbol in overwrite vi mode is the same as in command mode.
|
||||
typeset -g POWERLEVEL9K_PROMPT_CHAR_OVERWRITE_STATE=false
|
||||
|
||||
# Grey Python Virtual Environment.
|
||||
typeset -g POWERLEVEL9K_VIRTUALENV_FOREGROUND=$grey
|
||||
# Don't show Python version.
|
||||
typeset -g POWERLEVEL9K_VIRTUALENV_SHOW_PYTHON_VERSION=false
|
||||
typeset -g POWERLEVEL9K_VIRTUALENV_{LEFT,RIGHT}_DELIMITER=
|
||||
|
||||
# Blue current directory.
|
||||
typeset -g POWERLEVEL9K_DIR_FOREGROUND=$blue
|
||||
|
||||
# Context format when root: user@host. The first part white, the rest grey.
|
||||
typeset -g POWERLEVEL9K_CONTEXT_ROOT_TEMPLATE="%F{$white}%n%f%F{$grey}@%m%f"
|
||||
# Context format when not root: user@host. The whole thing grey.
|
||||
typeset -g POWERLEVEL9K_CONTEXT_TEMPLATE="%F{$grey}%n@%m%f"
|
||||
# Don't show context unless root or in SSH.
|
||||
typeset -g POWERLEVEL9K_CONTEXT_{DEFAULT,SUDO}_CONTENT_EXPANSION=
|
||||
|
||||
# Show previous command duration only if it's >= 5s.
|
||||
typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_THRESHOLD=5
|
||||
# Don't show fractional seconds. Thus, 7s rather than 7.3s.
|
||||
typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_PRECISION=0
|
||||
# Duration format: 1d 2h 3m 4s.
|
||||
typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FORMAT='d h m s'
|
||||
# Yellow previous command duration.
|
||||
typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FOREGROUND=$yellow
|
||||
|
||||
# Grey Git prompt. This makes stale prompts indistinguishable from up-to-date ones.
|
||||
typeset -g POWERLEVEL9K_VCS_FOREGROUND=$grey
|
||||
|
||||
# Disable async loading indicator to make directories that aren't Git repositories
|
||||
# indistinguishable from large Git repositories without known state.
|
||||
typeset -g POWERLEVEL9K_VCS_LOADING_TEXT=
|
||||
|
||||
# Don't wait for Git status even for a millisecond, so that prompt always updates
|
||||
# asynchronously when Git state changes.
|
||||
typeset -g POWERLEVEL9K_VCS_MAX_SYNC_LATENCY_SECONDS=0
|
||||
|
||||
# Cyan ahead/behind arrows.
|
||||
typeset -g POWERLEVEL9K_VCS_{INCOMING,OUTGOING}_CHANGESFORMAT_FOREGROUND=$cyan
|
||||
# Don't show remote branch, current tag or stashes.
|
||||
typeset -g POWERLEVEL9K_VCS_GIT_HOOKS=(vcs-detect-changes git-untracked git-aheadbehind)
|
||||
# Don't show the branch icon.
|
||||
typeset -g POWERLEVEL9K_VCS_BRANCH_ICON=
|
||||
# When in detached HEAD state, show @commit where branch normally goes.
|
||||
typeset -g POWERLEVEL9K_VCS_COMMIT_ICON='@'
|
||||
# Don't show staged, unstaged, untracked indicators.
|
||||
typeset -g POWERLEVEL9K_VCS_{STAGED,UNSTAGED,UNTRACKED}_ICON=
|
||||
# Show '*' when there are staged, unstaged or untracked files.
|
||||
typeset -g POWERLEVEL9K_VCS_DIRTY_ICON='*'
|
||||
# Show '⇣' if local branch is behind remote.
|
||||
typeset -g POWERLEVEL9K_VCS_INCOMING_CHANGES_ICON=':⇣'
|
||||
# Show '⇡' if local branch is ahead of remote.
|
||||
typeset -g POWERLEVEL9K_VCS_OUTGOING_CHANGES_ICON=':⇡'
|
||||
# Don't show the number of commits next to the ahead/behind arrows.
|
||||
typeset -g POWERLEVEL9K_VCS_{COMMITS_AHEAD,COMMITS_BEHIND}_MAX_NUM=1
|
||||
# Remove space between '⇣' and '⇡' and all trailing spaces.
|
||||
typeset -g POWERLEVEL9K_VCS_CONTENT_EXPANSION='${${${P9K_CONTENT/⇣* :⇡/⇣⇡}// }//:/ }'
|
||||
|
||||
# Grey current time.
|
||||
typeset -g POWERLEVEL9K_TIME_FOREGROUND=$grey
|
||||
# Format for the current time: 09:51:02. See `man 3 strftime`.
|
||||
typeset -g POWERLEVEL9K_TIME_FORMAT='%D{%H:%M:%S}'
|
||||
# If set to true, time will update when you hit enter. This way prompts for the past
|
||||
# commands will contain the start times of their commands rather than the end times of
|
||||
# their preceding commands.
|
||||
typeset -g POWERLEVEL9K_TIME_UPDATE_ON_COMMAND=false
|
||||
|
||||
# Transient prompt works similarly to the builtin transient_rprompt option. It trims down prompt
|
||||
# when accepting a command line. Supported values:
|
||||
#
|
||||
# - off: Don't change prompt when accepting a command line.
|
||||
# - always: Trim down prompt when accepting a command line.
|
||||
# - same-dir: Trim down prompt when accepting a command line unless this is the first command
|
||||
# typed after changing current working directory.
|
||||
typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=always
|
||||
|
||||
# Instant prompt mode.
|
||||
#
|
||||
# - off: Disable instant prompt. Choose this if you've tried instant prompt and found
|
||||
# it incompatible with your zsh configuration files.
|
||||
# - quiet: Enable instant prompt and don't print warnings when detecting console output
|
||||
# during zsh initialization. Choose this if you've read and understood
|
||||
# https://github.com/romkatv/powerlevel10k#instant-prompt.
|
||||
# - verbose: Enable instant prompt and print a warning when detecting console output during
|
||||
# zsh initialization. Choose this if you've never tried instant prompt, haven't
|
||||
# seen the warning, or if you are unsure what this all means.
|
||||
typeset -g POWERLEVEL9K_INSTANT_PROMPT=verbose
|
||||
|
||||
# Hot reload allows you to change POWERLEVEL9K options after Powerlevel10k has been initialized.
|
||||
# For example, you can type POWERLEVEL9K_BACKGROUND=red and see your prompt turn red. Hot reload
|
||||
# can slow down prompt by 1-2 milliseconds, so it's better to keep it turned off unless you
|
||||
# really need it.
|
||||
typeset -g POWERLEVEL9K_DISABLE_HOT_RELOAD=true
|
||||
|
||||
# If p10k is already loaded, reload configuration.
|
||||
# This works even with POWERLEVEL9K_DISABLE_HOT_RELOAD=true.
|
||||
(( ! $+functions[p10k] )) || p10k reload
|
||||
}
|
||||
|
||||
# Tell `p10k configure` which file it should overwrite.
|
||||
typeset -g POWERLEVEL9K_CONFIG_FILE=${${(%):-%x}:a}
|
||||
|
||||
(( ${#p10k_config_opts} )) && setopt ${p10k_config_opts[@]}
|
||||
'builtin' 'unset' 'p10k_config_opts'
|
||||
+516
-37
@@ -34,6 +34,8 @@ case "$url" in
|
||||
*/local-bin/capture-menu.sh) echo "stub-capture-menu" > "$out" ;;
|
||||
*/local-bin/screenshot.sh) echo "stub-screenshot" > "$out" ;;
|
||||
*/local-bin/toggle-recording.sh) echo "stub-toggle-recording" > "$out" ;;
|
||||
*/terminal/p10k/.p10k.zsh) echo "stub-p10k" > "$out" ;;
|
||||
*/terminal/kali/prompt.zsh) echo "stub-kali-prompt" > "$out" ;;
|
||||
*) echo "unexpected url: $url" >&2; exit 1 ;;
|
||||
esac
|
||||
EOF
|
||||
@@ -50,6 +52,8 @@ EOF
|
||||
[ "$(cat "$REPO_DIR/local-bin/capture-menu.sh")" = "stub-capture-menu" ]
|
||||
[ "$(cat "$REPO_DIR/local-bin/screenshot.sh")" = "stub-screenshot" ]
|
||||
[ "$(cat "$REPO_DIR/local-bin/toggle-recording.sh")" = "stub-toggle-recording" ]
|
||||
[ "$(cat "$REPO_DIR/terminal/p10k/.p10k.zsh")" = "stub-p10k" ]
|
||||
[ "$(cat "$REPO_DIR/terminal/kali/prompt.zsh")" = "stub-kali-prompt" ]
|
||||
|
||||
rm -rf "$fake_repo_dir" "$stub_bin"
|
||||
}
|
||||
@@ -137,12 +141,12 @@ EOF
|
||||
|
||||
@test "run_picker reads picks from env vars in non-interactive mode" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
HYPREVO_NONINTERACTIVE=1 \
|
||||
HYPREVO_TERMINAL=Kitty \
|
||||
HYPREVO_FILEMANAGER=Thunar \
|
||||
HYPREVO_MAIL=Thunderbird \
|
||||
HYPREVO_CLOUDSYNC=Syncthing \
|
||||
HYPREVO_TOGGLES="Telegram Bitwarden" \
|
||||
DOTEVO_NONINTERACTIVE=1 \
|
||||
DOTEVO_TERMINAL=Kitty \
|
||||
DOTEVO_FILEMANAGER=Thunar \
|
||||
DOTEVO_MAIL=Thunderbird \
|
||||
DOTEVO_CLOUDSYNC=Syncthing \
|
||||
DOTEVO_TOGGLES="Telegram Bitwarden" \
|
||||
run_picker
|
||||
|
||||
[ "$PICK_TERMINAL" = "Kitty" ]
|
||||
@@ -156,11 +160,11 @@ EOF
|
||||
|
||||
@test "run_picker defaults toggles to empty when unset in non-interactive mode" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
HYPREVO_NONINTERACTIVE=1 \
|
||||
HYPREVO_TERMINAL=Konsole \
|
||||
HYPREVO_FILEMANAGER=Dolphin \
|
||||
HYPREVO_MAIL=Thunderbird \
|
||||
HYPREVO_CLOUDSYNC=Nextcloud \
|
||||
DOTEVO_NONINTERACTIVE=1 \
|
||||
DOTEVO_TERMINAL=Konsole \
|
||||
DOTEVO_FILEMANAGER=Dolphin \
|
||||
DOTEVO_MAIL=Thunderbird \
|
||||
DOTEVO_CLOUDSYNC=Nextcloud \
|
||||
run_picker
|
||||
|
||||
[ "${#PICK_TOGGLES[@]}" -eq 0 ]
|
||||
@@ -170,7 +174,7 @@ EOF
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
PICK_TERMINAL=Konsole PICK_FILEMANAGER=Dolphin PICK_MAIL=Thunderbird PICK_CLOUDSYNC=Nextcloud
|
||||
PICK_TOGGLES=()
|
||||
HYPREVO_NONINTERACTIVE=1 run confirm_summary
|
||||
DOTEVO_NONINTERACTIVE=1 run confirm_summary
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@@ -230,12 +234,12 @@ EOF
|
||||
|
||||
cat > "$stub_bin/systemctl" <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
echo "systemctl $*" >> "$HYPREVO_TEST_LOG"
|
||||
echo "systemctl $*" >> "$DOTEVO_TEST_LOG"
|
||||
exit 0
|
||||
EOF
|
||||
chmod +x "$stub_bin/systemctl"
|
||||
|
||||
export HYPREVO_TEST_LOG="$tmp_home/log"
|
||||
export DOTEVO_TEST_LOG="$tmp_home/log"
|
||||
export PATH="$stub_bin:$PATH"
|
||||
export CONFIG_HOME="$tmp_home/.config"
|
||||
|
||||
@@ -246,8 +250,8 @@ EOF
|
||||
grep -q '^Requires=graphical-session.target$' "$unit_file"
|
||||
grep -q '^Wants=xdg-desktop-autostart.target$' "$unit_file"
|
||||
|
||||
grep -q 'daemon-reload' "$HYPREVO_TEST_LOG"
|
||||
grep -q 'add-wants hyprland-session.target dms.service' "$HYPREVO_TEST_LOG"
|
||||
grep -q 'daemon-reload' "$DOTEVO_TEST_LOG"
|
||||
grep -q 'add-wants hyprland-session.target dms.service' "$DOTEVO_TEST_LOG"
|
||||
|
||||
rm -rf "$tmp_home" "$stub_bin"
|
||||
}
|
||||
@@ -285,12 +289,12 @@ EOF
|
||||
stub_bin="$(mktemp -d)"
|
||||
cat > "$stub_bin/dms" <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
echo "dms $*" >> "$HYPREVO_TEST_LOG"
|
||||
echo "dms $*" >> "$DOTEVO_TEST_LOG"
|
||||
exit 0
|
||||
EOF
|
||||
chmod +x "$stub_bin/dms"
|
||||
|
||||
HYPREVO_TEST_LOG="$tmp_home/log" PATH="$stub_bin:$PATH" configure_dms_dock
|
||||
DOTEVO_TEST_LOG="$tmp_home/log" PATH="$stub_bin:$PATH" configure_dms_dock
|
||||
|
||||
grep -q 'ipc call settings set showDock true' "$tmp_home/log"
|
||||
grep -q 'ipc call settings set dockAutoHide true' "$tmp_home/log"
|
||||
@@ -312,7 +316,7 @@ EOF
|
||||
[ "$count" -eq 1 ]
|
||||
}
|
||||
|
||||
@test "apply backs up an existing hyprland.conf, writes new config and extras.conf" {
|
||||
@test "apply_hyprland backs up an existing hyprland.conf, writes new config and extras.conf" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
|
||||
local tmp_home
|
||||
@@ -320,20 +324,20 @@ EOF
|
||||
local stub_bin
|
||||
stub_bin="$(mktemp -d)"
|
||||
|
||||
# Stub out every command apply() calls that would touch the real system.
|
||||
# Stub out every command apply_hyprland() calls that would touch the real system.
|
||||
cat > "$stub_bin/pacman" <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
echo "pacman $*" >> "$HYPREVO_TEST_LOG"
|
||||
echo "pacman $*" >> "$DOTEVO_TEST_LOG"
|
||||
exit 0
|
||||
EOF
|
||||
cat > "$stub_bin/systemctl" <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
echo "systemctl $*" >> "$HYPREVO_TEST_LOG"
|
||||
echo "systemctl $*" >> "$DOTEVO_TEST_LOG"
|
||||
exit 0
|
||||
EOF
|
||||
cat > "$stub_bin/hyprctl" <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
echo "hyprctl $*" >> "$HYPREVO_TEST_LOG"
|
||||
echo "hyprctl $*" >> "$DOTEVO_TEST_LOG"
|
||||
exit 0
|
||||
EOF
|
||||
cat > "$stub_bin/sudo" <<'EOF'
|
||||
@@ -342,7 +346,7 @@ exec "$@"
|
||||
EOF
|
||||
chmod +x "$stub_bin"/*
|
||||
|
||||
export HYPREVO_TEST_LOG="$tmp_home/log"
|
||||
export DOTEVO_TEST_LOG="$tmp_home/log"
|
||||
export PATH="$stub_bin:$PATH"
|
||||
export HOME="$tmp_home"
|
||||
export CONFIG_HOME="$tmp_home/.config"
|
||||
@@ -351,10 +355,14 @@ EOF
|
||||
mkdir -p "$CONFIG_HOME/hypr"
|
||||
echo "old config" > "$CONFIG_HOME/hypr/hyprland.conf"
|
||||
|
||||
PICK_TERMINAL=Kitty PICK_FILEMANAGER=Thunar PICK_MAIL=Thunderbird PICK_CLOUDSYNC=Syncthing
|
||||
PICK_TOGGLES=(ScreenCapture)
|
||||
export DOTEVO_NONINTERACTIVE=1
|
||||
export DOTEVO_TERMINAL=Kitty
|
||||
export DOTEVO_FILEMANAGER=Thunar
|
||||
export DOTEVO_MAIL=Thunderbird
|
||||
export DOTEVO_CLOUDSYNC=Syncthing
|
||||
export DOTEVO_TOGGLES="ScreenCapture"
|
||||
|
||||
apply
|
||||
apply_hyprland
|
||||
|
||||
# Old config was backed up, not deleted.
|
||||
backup_count=$(find "$CONFIG_HOME/old2026_1" -name "hyprland.conf" 2>/dev/null | wc -l)
|
||||
@@ -372,16 +380,16 @@ EOF
|
||||
# pacman was synced/upgraded first (avoids installing against a stale
|
||||
# local package database that no longer matches the mirrors), then the
|
||||
# actual package list was installed with --needed.
|
||||
grep -q '\-Syu' "$HYPREVO_TEST_LOG"
|
||||
grep -q '\-\-needed' "$HYPREVO_TEST_LOG"
|
||||
grep -q '\-Syu' "$DOTEVO_TEST_LOG"
|
||||
grep -q '\-\-needed' "$DOTEVO_TEST_LOG"
|
||||
|
||||
# Syncthing's systemd user service was enabled, since CloudSync=Syncthing.
|
||||
grep -q 'enable --now --user syncthing.service' "$HYPREVO_TEST_LOG"
|
||||
grep -q 'enable --now --user syncthing.service' "$DOTEVO_TEST_LOG"
|
||||
|
||||
# hyprland-session.target was written and dms.service wired to it, so
|
||||
# DMS actually launches on login (this was previously missing entirely).
|
||||
[ -f "$CONFIG_HOME/systemd/user/hyprland-session.target" ]
|
||||
grep -q 'add-wants hyprland-session.target dms.service' "$HYPREVO_TEST_LOG"
|
||||
grep -q 'add-wants hyprland-session.target dms.service' "$DOTEVO_TEST_LOG"
|
||||
|
||||
rm -rf "$tmp_home" "$stub_bin"
|
||||
}
|
||||
@@ -408,16 +416,487 @@ EOF
|
||||
|
||||
PATH="$stub_bin:$PATH" \
|
||||
HOME="$tmp_home" \
|
||||
HYPREVO_NONINTERACTIVE=1 \
|
||||
HYPREVO_TERMINAL=Konsole \
|
||||
HYPREVO_FILEMANAGER=Dolphin \
|
||||
HYPREVO_MAIL=Thunderbird \
|
||||
HYPREVO_CLOUDSYNC=Nextcloud \
|
||||
DOTEVO_NONINTERACTIVE=1 \
|
||||
DOTEVO_COMPONENTS="Hyprland" \
|
||||
DOTEVO_TERMINAL=Konsole \
|
||||
DOTEVO_FILEMANAGER=Dolphin \
|
||||
DOTEVO_MAIL=Thunderbird \
|
||||
DOTEVO_CLOUDSYNC=Nextcloud \
|
||||
run bash -c "$(cat "${BATS_TEST_DIRNAME}/../install.sh")"
|
||||
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"hyprevo: done."* ]]
|
||||
[[ "$output" == *"dotevo: done."* ]]
|
||||
[ -f "$tmp_home/.config/hypr/hyprland.conf" ]
|
||||
|
||||
rm -rf "$tmp_home" "$stub_bin"
|
||||
}
|
||||
|
||||
@test "run_component_picker reads picks from env var in non-interactive mode" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
DOTEVO_NONINTERACTIVE=1 DOTEVO_COMPONENTS="Hyprland TerminalLook" run_component_picker
|
||||
[ "${#PICK_COMPONENTS[@]}" -eq 2 ]
|
||||
[[ " ${PICK_COMPONENTS[*]} " == *" Hyprland "* ]]
|
||||
[[ " ${PICK_COMPONENTS[*]} " == *" TerminalLook "* ]]
|
||||
}
|
||||
|
||||
@test "run_component_picker requires DOTEVO_COMPONENTS in non-interactive mode" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
DOTEVO_NONINTERACTIVE=1 run run_component_picker
|
||||
[ "$status" -ne 0 ]
|
||||
}
|
||||
|
||||
@test "apply_hyprland skips cleanly when pacman is missing, without touching TerminalLook" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
local stub_bin
|
||||
stub_bin="$(mktemp -d)"
|
||||
PATH="$stub_bin" run apply_hyprland
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"skipping Hyprland rice"* ]]
|
||||
rm -rf "$stub_bin"
|
||||
}
|
||||
|
||||
@test "main dispatches only picked components (Hyprland skipped, TerminalLook runs) via bash -c" {
|
||||
local tmp_home
|
||||
tmp_home="$(mktemp -d)"
|
||||
local stub_bin
|
||||
stub_bin="$(mktemp -d)"
|
||||
# No pacman/sudo stub calling through to a Hyprland-specific command on
|
||||
# purpose -- proves the Hyprland module is skipped, not just that its
|
||||
# commands happen to no-op. apply_terminal_look() is real (Task 8), so it
|
||||
# still needs its own prereqs (pacman, sudo, git, zsh, chsh) stubbed to
|
||||
# run end-to-end without touching the real system.
|
||||
for cmd in curl pacman sudo git zsh chsh; do
|
||||
cat > "$stub_bin/$cmd" <<EOF
|
||||
#!/usr/bin/env bash
|
||||
exit 0
|
||||
EOF
|
||||
chmod +x "$stub_bin/$cmd"
|
||||
done
|
||||
|
||||
PATH="$stub_bin:/usr/bin:/bin" \
|
||||
HOME="$tmp_home" \
|
||||
DOTEVO_NONINTERACTIVE=1 \
|
||||
DOTEVO_COMPONENTS="TerminalLook" \
|
||||
DOTEVO_TERMINAL_LOOK="Kali" \
|
||||
run bash -c "$(cat "${BATS_TEST_DIRNAME}/../install.sh")"
|
||||
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" != *"skipping Hyprland rice"* ]]
|
||||
[[ "$output" == *"dotevo: done."* ]]
|
||||
rm -rf "$tmp_home" "$stub_bin"
|
||||
}
|
||||
|
||||
@test "main runs both components: Hyprland skips cleanly on missing prereq, TerminalLook still completes" {
|
||||
# Regression test for the Global Constraint that one module's failed
|
||||
# prerequisite check must never block another module from running.
|
||||
# Both components are picked; PATH is a clean room containing only the
|
||||
# exact binaries this path needs, with pacman deliberately never added
|
||||
# (not stubbed out -- simply absent), so apply_hyprland's check_arch
|
||||
# fails regardless of whether the host machine actually has pacman, and
|
||||
# it must skip via `return 0`, not abort the script under
|
||||
# `set -euo pipefail`. apply_terminal_look (Kali look, no oh-my-zsh clone
|
||||
# needed) must still run to completion afterward.
|
||||
local tmp_home
|
||||
tmp_home="$(mktemp -d)"
|
||||
local stub_bin
|
||||
stub_bin="$(mktemp -d)"
|
||||
|
||||
# Real passthrough binaries the Hyprland-skip + Kali terminal-look path
|
||||
# actually calls (bash for the outer `run bash -c`, plus coreutils/git
|
||||
# used by ensure_repo_files/apply_terminal_look_kali/write_zshrc_kali).
|
||||
for real in bash dirname mkdir cp cat git; do
|
||||
ln -s "$(command -v "$real")" "$stub_bin/$real"
|
||||
done
|
||||
|
||||
# No-op stand-ins for everything else the script shells out to on this
|
||||
# path -- deliberately no pacman here.
|
||||
for cmd in curl apt-get sudo zsh chsh; do
|
||||
cat > "$stub_bin/$cmd" <<'EOF'
|
||||
#!/bin/bash
|
||||
exit 0
|
||||
EOF
|
||||
chmod +x "$stub_bin/$cmd"
|
||||
done
|
||||
|
||||
PATH="$stub_bin" \
|
||||
HOME="$tmp_home" \
|
||||
DOTEVO_NONINTERACTIVE=1 \
|
||||
DOTEVO_COMPONENTS="Hyprland TerminalLook" \
|
||||
DOTEVO_TERMINAL_LOOK="Kali" \
|
||||
run bash -c "$(cat "${BATS_TEST_DIRNAME}/../install.sh")"
|
||||
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"skipping Hyprland rice"* ]]
|
||||
[[ "$output" != *"unbound variable"* ]]
|
||||
[[ "$output" != *"install.sh: line"* ]]
|
||||
[[ "$output" == *"dotevo: done."* ]]
|
||||
[ -f "$tmp_home/.zshrc" ]
|
||||
|
||||
rm -rf "$tmp_home" "$stub_bin"
|
||||
}
|
||||
|
||||
@test "detect_pkg_manager finds pacman first when present" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
local stub_bin
|
||||
stub_bin="$(mktemp -d)"
|
||||
touch "$stub_bin/pacman" && chmod +x "$stub_bin/pacman"
|
||||
PATH="$stub_bin" run detect_pkg_manager
|
||||
[ "$output" = "pacman" ]
|
||||
rm -rf "$stub_bin"
|
||||
}
|
||||
|
||||
@test "detect_pkg_manager finds apt-get, dnf, zypper when pacman absent" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
local stub_bin
|
||||
stub_bin="$(mktemp -d)"
|
||||
|
||||
touch "$stub_bin/apt-get" && chmod +x "$stub_bin/apt-get"
|
||||
PATH="$stub_bin" run detect_pkg_manager
|
||||
[ "$output" = "apt" ]
|
||||
rm -f "$stub_bin"/*
|
||||
|
||||
touch "$stub_bin/dnf" && chmod +x "$stub_bin/dnf"
|
||||
PATH="$stub_bin" run detect_pkg_manager
|
||||
[ "$output" = "dnf" ]
|
||||
rm -f "$stub_bin"/*
|
||||
|
||||
touch "$stub_bin/zypper" && chmod +x "$stub_bin/zypper"
|
||||
PATH="$stub_bin" run detect_pkg_manager
|
||||
[ "$output" = "zypper" ]
|
||||
|
||||
rm -rf "$stub_bin"
|
||||
}
|
||||
|
||||
@test "detect_pkg_manager returns unknown when nothing recognized is on PATH" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
local stub_bin
|
||||
stub_bin="$(mktemp -d)"
|
||||
PATH="$stub_bin" run detect_pkg_manager
|
||||
[ "$output" = "unknown" ]
|
||||
rm -rf "$stub_bin"
|
||||
}
|
||||
|
||||
@test "install_terminal_prereqs calls the right install command per package manager" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
local tmp_home stub_bin
|
||||
tmp_home="$(mktemp -d)"
|
||||
stub_bin="$(mktemp -d)"
|
||||
|
||||
for cmd in pacman apt-get sudo; do
|
||||
cat > "$stub_bin/$cmd" <<EOF
|
||||
#!/usr/bin/env bash
|
||||
echo "$cmd \$*" >> "$tmp_home/log"
|
||||
EOF
|
||||
chmod +x "$stub_bin/$cmd"
|
||||
done
|
||||
|
||||
PATH="$stub_bin:$PATH" DOTEVO_TEST_LOG="$tmp_home/log" install_terminal_prereqs
|
||||
grep -q 'pacman -S --needed --noconfirm zsh git curl fzf' "$tmp_home/log"
|
||||
|
||||
rm -rf "$tmp_home" "$stub_bin"
|
||||
}
|
||||
|
||||
@test "install_terminal_prereqs calls the right install command on apt (no pacman on PATH)" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
local tmp_home stub_bin
|
||||
tmp_home="$(mktemp -d)"
|
||||
stub_bin="$(mktemp -d)"
|
||||
|
||||
for cmd in apt-get sudo; do
|
||||
cat > "$stub_bin/$cmd" <<EOF
|
||||
#!/bin/bash
|
||||
echo "$cmd \$*" >> "$tmp_home/log"
|
||||
EOF
|
||||
chmod +x "$stub_bin/$cmd"
|
||||
done
|
||||
|
||||
PATH="$stub_bin" install_terminal_prereqs
|
||||
grep -q 'apt-get update' "$tmp_home/log"
|
||||
grep -q 'apt-get install -y zsh git curl fzf' "$tmp_home/log"
|
||||
|
||||
rm -rf "$tmp_home" "$stub_bin"
|
||||
}
|
||||
|
||||
@test "install_terminal_prereqs fails clearly on an unrecognized package manager" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
local stub_bin
|
||||
stub_bin="$(mktemp -d)"
|
||||
PATH="$stub_bin" run install_terminal_prereqs
|
||||
[ "$status" -ne 0 ]
|
||||
[[ "$output" == *"dotevo:"*"package manager not recognized"* ]]
|
||||
rm -rf "$stub_bin"
|
||||
}
|
||||
|
||||
@test "run_terminal_look_picker reads pick from env var in non-interactive mode" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
DOTEVO_NONINTERACTIVE=1 DOTEVO_TERMINAL_LOOK=Kali run_terminal_look_picker
|
||||
[ "$PICK_TERMINAL_LOOK" = "Kali" ]
|
||||
}
|
||||
|
||||
@test "run_terminal_look_picker requires DOTEVO_TERMINAL_LOOK in non-interactive mode" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
DOTEVO_NONINTERACTIVE=1 run run_terminal_look_picker
|
||||
[ "$status" -ne 0 ]
|
||||
}
|
||||
|
||||
@test "clone_or_update_repo clones on first call, pulls on second" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
local remote_dir work_dir dest
|
||||
remote_dir="$(mktemp -d)"
|
||||
work_dir="$(mktemp -d)"
|
||||
dest="$work_dir/dest"
|
||||
|
||||
git init --bare -q "$remote_dir/repo.git"
|
||||
git clone -q "$remote_dir/repo.git" "$work_dir/seed"
|
||||
(cd "$work_dir/seed" && git config user.email [email protected] && git config user.name t \
|
||||
&& echo v1 > file.txt && git add file.txt && git commit -q -m v1 && git push -q)
|
||||
|
||||
clone_or_update_repo "$remote_dir/repo.git" "$dest"
|
||||
[ -f "$dest/file.txt" ]
|
||||
[ "$(cat "$dest/file.txt")" = "v1" ]
|
||||
|
||||
(cd "$work_dir/seed" && echo v2 > file.txt && git commit -q -am v2 && git push -q)
|
||||
clone_or_update_repo "$remote_dir/repo.git" "$dest"
|
||||
[ "$(cat "$dest/file.txt")" = "v2" ]
|
||||
|
||||
rm -rf "$remote_dir" "$work_dir"
|
||||
}
|
||||
|
||||
@test "terminal/p10k/.p10k.zsh is the real shipped config" {
|
||||
[ -f "${BATS_TEST_DIRNAME}/../terminal/p10k/.p10k.zsh" ]
|
||||
grep -q 'Powerlevel10k configuration wizard' "${BATS_TEST_DIRNAME}/../terminal/p10k/.p10k.zsh"
|
||||
}
|
||||
|
||||
@test "write_zshrc_p10k writes a syntactically valid zsh file sourcing oh-my-zsh and p10k" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
local tmp_home
|
||||
tmp_home="$(mktemp -d)"
|
||||
OMZ_DIR="$tmp_home/.oh-my-zsh" ZSH_CUSTOM_DIR="$tmp_home/.dotevo-zsh-custom" \
|
||||
write_zshrc_p10k "$tmp_home/.zshrc"
|
||||
|
||||
grep -q 'ZSH_THEME="powerlevel10k/powerlevel10k"' "$tmp_home/.zshrc"
|
||||
grep -q 'plugins=(git fzf zsh-autosuggestions zsh-syntax-highlighting zsh-history-substring-search)' "$tmp_home/.zshrc"
|
||||
grep -q 'source \$ZSH/oh-my-zsh.sh' "$tmp_home/.zshrc"
|
||||
grep -q 'source ~/.p10k.zsh' "$tmp_home/.zshrc"
|
||||
grep -q 'fzf --zsh' "$tmp_home/.zshrc"
|
||||
|
||||
if command -v zsh >/dev/null 2>&1; then
|
||||
zsh -n "$tmp_home/.zshrc"
|
||||
fi
|
||||
|
||||
rm -rf "$tmp_home"
|
||||
}
|
||||
|
||||
@test "apply_terminal_look_p10k clones the right repos, backs up, and writes config" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
local tmp_home stub_bin
|
||||
tmp_home="$(mktemp -d)"
|
||||
stub_bin="$(mktemp -d)"
|
||||
|
||||
cat > "$stub_bin/git" <<EOF
|
||||
#!/usr/bin/env bash
|
||||
echo "git \$*" >> "$tmp_home/log"
|
||||
if [[ "\$1" == "clone" ]]; then mkdir -p "\${@: -1}/.git"; fi
|
||||
exit 0
|
||||
EOF
|
||||
chmod +x "$stub_bin/git"
|
||||
|
||||
echo "old zshrc" > "$tmp_home/.zshrc"
|
||||
|
||||
HOME="$tmp_home" \
|
||||
CONFIG_HOME="$tmp_home/.config" \
|
||||
REPO_DIR="${BATS_TEST_DIRNAME}/.." \
|
||||
OMZ_DIR="$tmp_home/.oh-my-zsh" \
|
||||
ZSH_CUSTOM_DIR="$tmp_home/.dotevo-zsh-custom" \
|
||||
PATH="$stub_bin:$PATH" \
|
||||
apply_terminal_look_p10k
|
||||
|
||||
grep -q "clone.*ohmyzsh/ohmyzsh.*$tmp_home/.oh-my-zsh" "$tmp_home/log"
|
||||
grep -q "clone.*romkatv/powerlevel10k.*themes/powerlevel10k" "$tmp_home/log"
|
||||
grep -q "clone.*zsh-users/zsh-autosuggestions" "$tmp_home/log"
|
||||
grep -q "clone.*zsh-users/zsh-syntax-highlighting" "$tmp_home/log"
|
||||
grep -q "clone.*zsh-users/zsh-history-substring-search" "$tmp_home/log"
|
||||
|
||||
[ -f "$tmp_home/.p10k.zsh" ]
|
||||
grep -q "old zshrc" "$(find "$tmp_home/.config/old2026_1" -name .zshrc)"
|
||||
grep -q 'ZSH_THEME="powerlevel10k/powerlevel10k"' "$tmp_home/.zshrc"
|
||||
|
||||
rm -rf "$tmp_home" "$stub_bin"
|
||||
}
|
||||
|
||||
@test "terminal/kali/prompt.zsh is syntactically valid zsh" {
|
||||
[ -f "${BATS_TEST_DIRNAME}/../terminal/kali/prompt.zsh" ]
|
||||
if command -v zsh >/dev/null 2>&1; then
|
||||
zsh -n "${BATS_TEST_DIRNAME}/../terminal/kali/prompt.zsh"
|
||||
fi
|
||||
}
|
||||
|
||||
@test "write_zshrc_kali sources prompt.zsh and the plugin scripts directly, no oh-my-zsh" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
local tmp_home
|
||||
tmp_home="$(mktemp -d)"
|
||||
ASSETS_DIR="$tmp_home/.dotevo" ZSH_CUSTOM_DIR="$tmp_home/.dotevo-zsh-custom" \
|
||||
write_zshrc_kali "$tmp_home/.zshrc"
|
||||
|
||||
grep -q 'source .*\.dotevo/kali-prompt.zsh' "$tmp_home/.zshrc"
|
||||
grep -q 'source .*zsh-autosuggestions/zsh-autosuggestions.zsh' "$tmp_home/.zshrc"
|
||||
grep -q 'source .*zsh-syntax-highlighting/zsh-syntax-highlighting.zsh' "$tmp_home/.zshrc"
|
||||
grep -q 'source .*zsh-history-substring-search/zsh-history-substring-search.zsh' "$tmp_home/.zshrc"
|
||||
grep -qv 'oh-my-zsh' "$tmp_home/.zshrc"
|
||||
grep -q 'fzf --zsh' "$tmp_home/.zshrc"
|
||||
|
||||
if command -v zsh >/dev/null 2>&1; then
|
||||
zsh -n "$tmp_home/.zshrc"
|
||||
fi
|
||||
|
||||
rm -rf "$tmp_home"
|
||||
}
|
||||
|
||||
@test "apply_terminal_look_kali clones only the three plugin repos, not oh-my-zsh" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
local tmp_home stub_bin
|
||||
tmp_home="$(mktemp -d)"
|
||||
stub_bin="$(mktemp -d)"
|
||||
|
||||
cat > "$stub_bin/git" <<EOF
|
||||
#!/usr/bin/env bash
|
||||
echo "git \$*" >> "$tmp_home/log"
|
||||
if [[ "\$1" == "clone" ]]; then mkdir -p "\${@: -1}/.git"; fi
|
||||
exit 0
|
||||
EOF
|
||||
chmod +x "$stub_bin/git"
|
||||
|
||||
HOME="$tmp_home" \
|
||||
CONFIG_HOME="$tmp_home/.config" \
|
||||
REPO_DIR="${BATS_TEST_DIRNAME}/.." \
|
||||
ASSETS_DIR="$tmp_home/.dotevo" \
|
||||
ZSH_CUSTOM_DIR="$tmp_home/.dotevo-zsh-custom" \
|
||||
PATH="$stub_bin:$PATH" \
|
||||
apply_terminal_look_kali
|
||||
|
||||
grep -q "zsh-users/zsh-autosuggestions" "$tmp_home/log"
|
||||
grep -q "zsh-users/zsh-syntax-highlighting" "$tmp_home/log"
|
||||
grep -q "zsh-users/zsh-history-substring-search" "$tmp_home/log"
|
||||
! grep -q "ohmyzsh" "$tmp_home/log"
|
||||
! grep -q "powerlevel10k" "$tmp_home/log"
|
||||
|
||||
[ -f "$tmp_home/.dotevo/kali-prompt.zsh" ]
|
||||
grep -q 'Kali-style prompt' "$tmp_home/.dotevo/kali-prompt.zsh"
|
||||
[[ "$(cat "$tmp_home/.zshrc")" == *"kali-prompt.zsh"* ]]
|
||||
|
||||
rm -rf "$tmp_home" "$stub_bin"
|
||||
}
|
||||
|
||||
@test "chsh_to_zsh switches shell only when current SHELL isn't zsh" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
local tmp_home stub_bin
|
||||
tmp_home="$(mktemp -d)"
|
||||
stub_bin="$(mktemp -d)"
|
||||
|
||||
cat > "$stub_bin/zsh" <<EOF
|
||||
#!/usr/bin/env bash
|
||||
exit 0
|
||||
EOF
|
||||
cat > "$stub_bin/chsh" <<EOF
|
||||
#!/usr/bin/env bash
|
||||
echo "chsh \$*" >> "$tmp_home/log"
|
||||
EOF
|
||||
chmod +x "$stub_bin/zsh" "$stub_bin/chsh"
|
||||
|
||||
SHELL="/bin/bash" PATH="$stub_bin:$PATH" chsh_to_zsh
|
||||
grep -q "chsh -s $stub_bin/zsh" "$tmp_home/log"
|
||||
|
||||
: > "$tmp_home/log"
|
||||
SHELL="$stub_bin/zsh" PATH="$stub_bin:$PATH" chsh_to_zsh
|
||||
[ ! -s "$tmp_home/log" ]
|
||||
|
||||
rm -rf "$tmp_home" "$stub_bin"
|
||||
}
|
||||
|
||||
@test "apply_terminal_look installs prereqs, picks a look, applies it, and switches shell" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
local tmp_home stub_bin
|
||||
tmp_home="$(mktemp -d)"
|
||||
stub_bin="$(mktemp -d)"
|
||||
|
||||
cat > "$stub_bin/pacman" <<EOF
|
||||
#!/usr/bin/env bash
|
||||
echo "pacman \$*" >> "$tmp_home/log"
|
||||
EOF
|
||||
# Stubbed directly (not just pacman) so this never reaches the real
|
||||
# sudo binary -- real sudo enforces its own secure_path and would
|
||||
# bypass our pacman stub, running the system's actual pacman instead.
|
||||
cat > "$stub_bin/sudo" <<EOF
|
||||
#!/usr/bin/env bash
|
||||
echo "sudo \$*" >> "$tmp_home/log"
|
||||
exec "\$@"
|
||||
EOF
|
||||
cat > "$stub_bin/git" <<EOF
|
||||
#!/usr/bin/env bash
|
||||
echo "git \$*" >> "$tmp_home/log"
|
||||
if [[ "\$1" == "clone" ]]; then mkdir -p "\${@: -1}/.git"; fi
|
||||
EOF
|
||||
cat > "$stub_bin/zsh" <<EOF
|
||||
#!/usr/bin/env bash
|
||||
exit 0
|
||||
EOF
|
||||
cat > "$stub_bin/chsh" <<EOF
|
||||
#!/usr/bin/env bash
|
||||
echo "chsh \$*" >> "$tmp_home/log"
|
||||
EOF
|
||||
chmod +x "$stub_bin"/*
|
||||
|
||||
HOME="$tmp_home" \
|
||||
CONFIG_HOME="$tmp_home/.config" \
|
||||
REPO_DIR="${BATS_TEST_DIRNAME}/.." \
|
||||
OMZ_DIR="$tmp_home/.oh-my-zsh" \
|
||||
ZSH_CUSTOM_DIR="$tmp_home/.dotevo-zsh-custom" \
|
||||
ASSETS_DIR="$tmp_home/.dotevo" \
|
||||
SHELL="/bin/bash" \
|
||||
PATH="$stub_bin:$PATH" \
|
||||
DOTEVO_NONINTERACTIVE=1 \
|
||||
DOTEVO_TERMINAL_LOOK=Kali \
|
||||
apply_terminal_look
|
||||
|
||||
grep -q 'pacman -S --needed --noconfirm zsh git curl fzf' "$tmp_home/log"
|
||||
grep -q "chsh -s $stub_bin/zsh" "$tmp_home/log"
|
||||
[ -f "$tmp_home/.zshrc" ]
|
||||
[[ "$(cat "$tmp_home/.zshrc")" == *"kali-prompt.zsh"* ]]
|
||||
|
||||
rm -rf "$tmp_home" "$stub_bin"
|
||||
}
|
||||
|
||||
@test "ensure_repo_files fetches terminal/ assets too when curl-piped" {
|
||||
source "${BATS_TEST_DIRNAME}/../install.sh"
|
||||
local fake_repo_dir stub_bin
|
||||
fake_repo_dir="$(mktemp -d)"
|
||||
stub_bin="$(mktemp -d)"
|
||||
|
||||
cat > "$stub_bin/curl" <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
url="${@: -1}"
|
||||
out=""
|
||||
for ((i=1; i<=$#; i++)); do
|
||||
if [[ "${!i}" == "-o" ]]; then j=$((i+1)); out="${!j}"; fi
|
||||
done
|
||||
case "$url" in
|
||||
*/packages.txt) echo stub > "$out" ;;
|
||||
*/hypr/hyprland.conf) echo stub > "$out" ;;
|
||||
*/local-bin/*.sh) echo stub > "$out" ;;
|
||||
*/terminal/p10k/.p10k.zsh) echo stub-p10k > "$out" ;;
|
||||
*/terminal/kali/prompt.zsh) echo stub-kali > "$out" ;;
|
||||
*) echo "unexpected url: $url" >&2; exit 1 ;;
|
||||
esac
|
||||
EOF
|
||||
chmod +x "$stub_bin/curl"
|
||||
|
||||
REPO_DIR="$fake_repo_dir"
|
||||
PATH="$stub_bin:$PATH"
|
||||
|
||||
ensure_repo_files
|
||||
|
||||
[ "$(cat "$REPO_DIR/terminal/p10k/.p10k.zsh")" = "stub-p10k" ]
|
||||
[ "$(cat "$REPO_DIR/terminal/kali/prompt.zsh")" = "stub-kali" ]
|
||||
|
||||
rm -rf "$fake_repo_dir" "$stub_bin"
|
||||
}
|
||||
Reference in new issue
Block a user