From d8eabf77a1c2188bb788ea2bf0bec6f4042e96b5 Mon Sep 17 00:00:00 2001
From: Salvydas Lukosius
Date: Fri, 15 May 2026 23:58:54 +0100
Subject: [PATCH 1/7] chore: remove deprecated files and configs
Remove obsolete cspell word lists, editorconfig, vscode settings,
and retired workflows (rebase, stale, sync-labels, wrangler).
Drop legacy installer scripts i.sh and install_alpha.sh.
---
.cspell/project-words.txt | 45 ---
.editorconfig | 60 ---
.github/.cspell/project-ignored.txt | 2 -
.github/.cspell/project-usernames.txt | 1 -
.github/.cspell/project-words.txt | 34 --
.github/workflows/rebase-action.yml | 29 --
.github/workflows/stale-action.yml | 35 --
.github/workflows/sync-labels.yml | 10 -
.github/workflows/wrangler.yml | 40 --
.gitignore | 4 +
.vscode/settings.json | 17 -
lib/sh/i.sh | 547 --------------------------
lib/sh/install_alpha.sh | 512 ------------------------
13 files changed, 4 insertions(+), 1332 deletions(-)
delete mode 100644 .cspell/project-words.txt
delete mode 100644 .editorconfig
delete mode 100644 .github/.cspell/project-ignored.txt
delete mode 100644 .github/.cspell/project-usernames.txt
delete mode 100644 .github/.cspell/project-words.txt
delete mode 100644 .github/workflows/rebase-action.yml
delete mode 100644 .github/workflows/stale-action.yml
delete mode 100644 .github/workflows/sync-labels.yml
delete mode 100644 .github/workflows/wrangler.yml
delete mode 100644 .vscode/settings.json
delete mode 100755 lib/sh/i.sh
delete mode 100755 lib/sh/install_alpha.sh
diff --git a/.cspell/project-words.txt b/.cspell/project-words.txt
deleted file mode 100644
index bb883fb..0000000
--- a/.cspell/project-words.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-AOPT
-atinit
-atload
-atpull
-autoload
-blockf
-BOPT
-CFLAGS
-Cgreen
-Checkig
-COLORTERM
-COMPINIT
-CPPFLAGS
-creinstall
-Creset
-distclean
-gdbm
-LDFLAGS
-mgit
-mhas
-mktemp
-mload
-nearcolor
-OMZL
-OMZP
-OMZT
-pname
-robbyrussell
-SAVEHIST
-setopt
-srand
-tcsetpgrp
-truecolor
-WORKDIR
-ZDOTDIR
-zicdreplay
-zicompinit
-zinit
-zmodload
-zmodules
-ZOPT
-ZPMOD
-zstyle
-zunit
-zzinit
diff --git a/.editorconfig b/.editorconfig
deleted file mode 100644
index c25c645..0000000
--- a/.editorconfig
+++ /dev/null
@@ -1,60 +0,0 @@
-# Space or Tabs?
-# https://stackoverflow.com/questions/35649847/objective-reasons-for-using-spaces-instead-of-tabs-for-indentation
-# https://stackoverflow.com/questions/12093748/how-to-use-tabs-instead-of-spaces-in-a-shell-script
-# https://github.com/editorconfig/editorconfig-defaults/blob/master/editorconfig-defaults.json
-#
-# 1. What happens when I press the Tab key in my text editor?
-# 2. What happens when I request my editor to indent one or more lines?
-# 3. What happens when I view a file containing U+0009 HORIZONTAL TAB characters?
-#
-# Answers:
-#
-# 1. Pressing the Tab key should indent the current line (or selected lines) one additional level.
-# 2. As a secondary alternative, I can also tolerate an editor that,
-# like Emacs, uses this key for a context-sensitive fix-my-indentation command.
-# 3. Indenting one or more lines should follow the reigning convention, if consensus is sufficiently strong; otherwise,
-# I greatly prefer 2-space indentation at each level. U+0009 characters should shift subsequent characters to the next tab stop.
-#
-# Note: VIM users should use alternate marks [[[ and ]]] as the original ones can confuse nested substitutions, e.g.: ${${${VAR}}}
-#
-# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
-# vim: ft=zsh sw=2 ts=2 et
-
-root = true
-
-[*]
-charset = utf-8
-indent_style = space
-indent_size = 2
-insert_final_newline = true
-trim_trailing_whitespace = true
-
-[*.sln]
-indent_style = tab
-
-[*.{md,mdx,rst}]
-trim_trailing_whitespace = false
-
-[*.{cmd,bat}]
-end_of_line = crlf
-
-[*za-*]
-end_of_line = lf
-
-[*.{sh,bash,zsh,fish}]
-end_of_line = lf
-
-[Makefile]
-indent_style = tab
-indent_size = 4
-
-[*.{py,rb}]
-indent_size = 4
-
-[*.{go,java,scala,groovy,kotlin}]
-indent_style = tab
-indent_size = 4
-
-[*.{cs,csx,cake,vb,vbx}]
-# Default Severity for all .NET Code Style rules below
-dotnet_analyzer_diagnostic.severity = warning
diff --git a/.github/.cspell/project-ignored.txt b/.github/.cspell/project-ignored.txt
deleted file mode 100644
index 01e9305..0000000
--- a/.github/.cspell/project-ignored.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-mhas
-mload
diff --git a/.github/.cspell/project-usernames.txt b/.github/.cspell/project-usernames.txt
deleted file mode 100644
index 43ee3d2..0000000
--- a/.github/.cspell/project-usernames.txt
+++ /dev/null
@@ -1 +0,0 @@
-robbyrussell
diff --git a/.github/.cspell/project-words.txt b/.github/.cspell/project-words.txt
deleted file mode 100644
index e09d106..0000000
--- a/.github/.cspell/project-words.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-AOPT
-atinit'COMPLETION
-atinit'setopt
-atinit'typeset
-atinit'ZI
-atinit'zstyle
-atload
-atpull
-autoload
-blockf
-BOPT
-CFLAGS
-COMPINIT
-CPPFLAGS
-creinstall
-distclean
-gdbm
-LDFLAGS
-mktemp
-OMZL
-OMZP
-OMZT
-SAVEHIST
-tcsetpgrp
-WORKDIR
-ZDOTDIR
-zicdreplay
-zicompinit
-zinit
-zmodload
-zmodules
-ZOPT
-zpmod
-zzinit
diff --git a/.github/workflows/rebase-action.yml b/.github/workflows/rebase-action.yml
deleted file mode 100644
index 83e6615..0000000
--- a/.github/workflows/rebase-action.yml
+++ /dev/null
@@ -1,29 +0,0 @@
----
-name: "๐ Rebase"
-on:
- issue_comment:
- types: [created]
-
-jobs:
- rebase:
- runs-on: ubuntu-latest
- name: ๐ Rebase
- # Automate with comments: /autosquash, /rebase
- if: >-
- github.event.issue.pull_request != '' &&
- (
- contains(github.event.comment.body, '/rebase') ||
- contains(github.event.comment.body, '/autosquash')
- )
- steps:
- - name: โคต๏ธ Check out code from GitHub
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- with:
- token: ${{ secrets.ORG_TOKEN }}
- fetch-depth: 0 # otherwise, you will fail to push refs to dest repo
- - name: ๐ Rebase
- uses: z-shell/.github/actions/rebase@91068ee88e8788deff439d6ee36b77329edeb98a # v1.0.8
- with:
- autosquash: ${{ contains(github.event.comment.body, '/autosquash') || contains(github.event.comment.body, '/rebase-autosquash') }}
- env:
- GITHUB_TOKEN: ${{ secrets.ORG_TOKEN }}
diff --git a/.github/workflows/stale-action.yml b/.github/workflows/stale-action.yml
deleted file mode 100644
index d6fd984..0000000
--- a/.github/workflows/stale-action.yml
+++ /dev/null
@@ -1,35 +0,0 @@
----
-name: "๐ป Stale"
-
-on:
- schedule:
- - cron: "0 8 * * *"
- workflow_dispatch:
-
-jobs:
- stale:
- name: "๐งน Clean up stale issues and PRs"
- runs-on: ubuntu-latest
- steps:
- - name: "๐ Run stale"
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9
- with:
- # ๐ https://github.com/actions/stale#all-options
- days-before-stale: 30
- days-before-close: 7
- exempt-all-pr-assignees: true
- exempt-all-pr-milestones: true
- remove-stale-when-updated: true
- stale-issue-label: "stale ๐ป"
- exempt-issue-labels: "no-stale ๐,help-wanted ๐ฅ"
- stale-issue-message: >
- There hasn't been any activity on this issue recently, and in order to prioritize active issues, it will be
- marked as stale. Please make sure to update to the latest version and check if that solves the issue. Let us
- know if that works for you by leaving a ๐ Because this issue is marked as stale, it will be closed and
- locked in 7 days if no further activity occurs. Thank you for your contributions!
- stale-pr-label: "stale ๐ป"
- exempt-pr-labels: "no-stale ๐"
- stale-pr-message: >
- There hasn't been any activity on this pull request recently, and in order to prioritize active work, it has
- been marked as stale. This PR will be closed and locked in 7 days if no further activity occurs. Thank you
- for your contributions!
diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml
deleted file mode 100644
index f5f02c3..0000000
--- a/.github/workflows/sync-labels.yml
+++ /dev/null
@@ -1,10 +0,0 @@
----
-name: "โป๏ธ Sync Labels"
-on:
- schedule:
- - cron: "22 2 * * 2"
- workflow_dispatch:
-jobs:
- labels:
- name: "โป๏ธ Sync labels"
- uses: z-shell/.github/.github/workflows/sync-labels.yml@91068ee88e8788deff439d6ee36b77329edeb98a # v1.0.8
diff --git a/.github/workflows/wrangler.yml b/.github/workflows/wrangler.yml
deleted file mode 100644
index 57f590a..0000000
--- a/.github/workflows/wrangler.yml
+++ /dev/null
@@ -1,40 +0,0 @@
----
-name: "๐ค Wrangler"
-
-on:
- # schedule:
- # - cron: "0 03 * * 1/3"
- # push:
- # branches: [main]
- # paths:
- # - "lib/**"
- # - "workers/**"
- workflow_dispatch:
- inputs:
- environment:
- description: "Choose an environment to deploy to: "
- required: true
- default: "dev"
-
-jobs:
- deploy:
- runs-on: ubuntu-latest
- concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
- timeout-minutes: 15
- environment: wrangler
- steps:
- - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- - name: "๐ค Deploy > cdn"
- uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3.14.1
- with:
- apiToken: ${{ secrets.CF_API_TOKEN }}
- workingDirectory: "workers/cdn"
- command: "publish"
- - name: "๐ค Deploy > r2-store"
- uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3.14.1
- with:
- apiToken: ${{ secrets.CF_API_TOKEN }}
- workingDirectory: "workers/r2-store"
- command: "publish"
diff --git a/.gitignore b/.gitignore
index c8968ab..030f2a7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -150,3 +150,7 @@ worker/
node_modules/
.pnpm-store/
.cargo-ok
+AGENTS.md
+CLAUDE.md
+GEMINI.md
+.github/copilot-instructions.md
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index c17dc3e..0000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "[markdown]": {
- "editor.formatOnSave": true,
- "editor.formatOnPaste": true
- },
- "editor.codeActionsOnSave": {
- "source.fixAll.markdownlint": true
- },
- "conventionalCommits.scopes": [
- "maintenance",
- "workspace",
- "community",
- "general",
- "misc"
- ],
- "shellformat.useEditorConfig": true
-}
diff --git a/lib/sh/i.sh b/lib/sh/i.sh
deleted file mode 100755
index 285a610..0000000
--- a/lib/sh/i.sh
+++ /dev/null
@@ -1,547 +0,0 @@
-#!/usr/bin/env sh
-# -*- mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
-# vim: ft=sh sw=2 ts=2 et
-trap 'rm -rf "$WORKDIR"' EXIT INT
-WORKDIR="$(mktemp -d)"
-
-col_pname="[33m"
-col_error="[31m"
-col_info="[32m"
-col_rst="[0m"
-zsh_current=$(zsh --version &2 <&2
- exit 1
-}
-
-_os_type() {
- OS="$(command -v uname)"
- case $("${OS}" | tr '[:upper:]' '[:lower:]') in
- android*)
- OS='android'
- ;;
- darwin*)
- OS='darwin'
- ;;
- linux*)
- OS='linux'
- ;;
- freebsd*)
- OS='freebsd'
- ;;
- netbsd*)
- OS='netbsd'
- ;;
- openbsd*)
- OS='openbsd'
- ;;
- sunos*)
- OS='solaris'
- ;;
- msys* | cygwin* | mingw*)
- OS='windows'
- ;;
- nt | win*)
- OS='windows'
- ;;
- *)
- echo 'OS not supported'
- ;;
- esac
-}
-
-_cpu_type() {
- case "$(uname -m)" in
- x86_64 | x86-64 | x64 | amd64)
- ARCH='amd64'
- ;;
- i?86 | x86)
- ARCH='386'
- ;;
- armv8* | aarch64 | arm64)
- ARCH='arm64'
- ;;
- armv7*)
- ARCH='armv7'
- ;;
- armv6*)
- ARCH='armv6'
- ;;
- arm*)
- ARCH='arm'
- ;;
- mips64le*)
- ARCH='mips64le'
- ;;
- mips64*)
- ARCH='mips64'
- ;;
- mipsle*)
- ARCH='mipsle'
- ;;
- mips*)
- ARCH='mips'
- ;;
- ppc64le*)
- ARCH='ppc64le'
- ;;
- ppc64*)
- ARCH='ppc64'
- ;;
- ppcle*)
- ARCH='ppcle'
- ;;
- ppc*)
- ARCH='ppc'
- ;;
- s390*)
- ARCH='s390x'
- ;;
- *)
- echo 'OS architecture not supported'
- ;;
- esac
-}
-
-# Synopsis:
-#
-# annex: (available: recommended)
-# -a recommended
-# branch: (available: main or any other existing branch)
-# -b main
-# configuration directory: (default: ~/.config/zi, can be overridden to prefered location)
-# -c ${HOME}/.config/zi
-# ZI home directory (default: ~/.zi, can be overriden prefered location)
-# -d ${HOME}/.zi
-# zshrc header: (available loader, installer)
-# -e loader
-# clone options: (default: --progress, can be overridden to prefered git clone options)
-# -o --progress
-# make/build options: (build, make additonal. Available: zpmod)
-# -m zpmod
-# host to use: (default: host to use. Available: github.com, gitlab.com)
-# -h github.com
-# install profile: (profile to run: install, uninstall)
-# -p install
-# snippets: (group of snippets to install: not-available yet)
-# -s not-available yet
-# plugins: group of plugins to install: not-available yet)
-# -s not-available yet
-#
-# Example: ./install.sh -p install -c ~/.config/zi -d ~/.zi -e loader -o --progress -m zpmod -h github.com
-
-while getopts ":a:b:c:d:e:o:m:h:p:z:s:" opt; do
- case ${opt} in
- a)
- ANNEX="${ANNEX}${OPTARG}"
- ;;
- b)
- BRANCH="${BRANCH}${OPTARG}"
- ;;
- c)
- CONFIG_DIR="${CONFIG_DIR}${OPTARG}"
- ;;
- d)
- ZI_HOME="${ZI_HOME}${OPTARG}"
- ;;
- e)
- ZHEADER="${ZHEADER}${OPTARG}"
- ;;
- o)
- CLONE_OPTS="${CLONE_OPTS}${OPTARG}"
- ;;
- m)
- MAKE="${MAKE}${OPTARG}"
- ;;
- h)
- HOST="${HOST}${OPTARG}"
- ;;
- p)
- PROFILE="${PROFILE}${OPTARG}"
- ;;
- z)
- OMZ="${OMZ}${OPTARG}"
- ;;
- s)
- STD="${STD}${OPTARG}"
- ;;
- \?)
- err "Invalid option: ${OPTARG}" 1>&2
- ;;
- :)
- err "Invalid option: ${OPTARG} requires an argument" 1>&2
- ;;
- *)
- err "Invalid option: ${OPTARG}" 1>&2
-
- ;;
- esac
-done
-shift $((OPTIND - 1))
-
-if [ -z "${PROFILE}" ]; then
- # Available profiles: install, uninstall, main.
- PROFILE="main"
-fi
-if [ -z "${HOST}" ]; then
- # Default host
- HOST="github.com"
-fi
-if [ -z "${BRANCH}" ]; then
- # Default branch
- BRANCH="main"
-fi
-if [ -z "${CLONE_OPTS}" ]; then
- # Default git clone options
- CLONE_OPTS="--progress"
-fi
-if [ -z "${ZI_HOME}" ]; then
- # Installiation time ZI home directory
- ZI_HOME="${ZDOTDIR:-${HOME}}/.zi"
-fi
-if [ -z "${ZI_BIN_DIR_NAME}" ]; then
- # ZI bin directory
- ZI_BIN_DIR_NAME="bin"
-fi
-if [ -z "${CONFIG_DIR}" ]; then
- # Default configuration directory
- CONFIG_DIR="${XDG_CONFIG_HOME:-${HOME}/.config}/zi"
-fi
-if [ -z "${ZHEADER}" ]; then
- # Default header script
- ZHEADER="loader"
-fi
-
-_set_externals() {
- if ! command -v git >/dev/null 2>&1; then
- err "[1;31mโโโ[0m Something went wrong: [1;32mgit[0m not available, cannot proceed."
- fi
- if [ "${HOST}" = github.com ]; then
- if curl -fsL https://raw.githubusercontent.com/z-shell/zi-src/main/lib/zsh/init.zsh >/dev/null; then
- RAW_LOADER_URL="https://raw.githubusercontent.com/z-shell/zi-src/main/lib/zsh/init.zsh"
- if curl -fsL https://raw.githubusercontent.com/z-shell/zi/main/lib/zsh/git-process-output.zsh >/dev/null; then
- RAW_GIT_OUPUT="https://raw.githubusercontent.com/z-shell/zi/main/lib/zsh/git-process-output.zsh"
- else
- err "Git process script at GitHub is not reachable"
- fi
- else
- err "GitLab and GitHub repositories are unreachable"
- fi
- elif [ "${HOST}" = gitlab.com ]; then
- if curl -fsL https://gitlab.com/ss-o/zi-src/-/raw/main/lib/zsh/init.zsh >/dev/null; then
- RAW_LOADER_URL="https://gitlab.com/ss-o/zi-src/-/raw/main/lib/zsh/init.zsh"
- if curl -fsL https://gitlab.com/ss-o/zi/-/raw/main/lib/zsh/git-process-output.zsh >/dev/null; then
- RAW_GIT_OUPUT="https://gitlab.com/ss-o/zi/-/raw/main/lib/zsh/git-process-output.zsh"
- else
- err "Git process script at GitLab is not reachable"
- fi
- fi
- fi
- # Get the download-progress bar tool
- if command -v curl >/dev/null 2>&1; then
- command mkdir -p "${WORKDIR}"
- cd "${WORKDIR}" || return
- command curl -fsSLO "${RAW_GIT_OUPUT}" && command chmod a+x "${WORKDIR}"/git-process-output.zsh
- elif command -v wget >/dev/null 2>&1; then
- command mkdir -p "${WORKDIR}"
- cd "${WORKDIR}" || return
- command wget -q "${RAW_GIT_OUPUT}" && command chmod a+x "${WORKDIR}"/git-process-output.zsh
- else
- say "[1;31mโโโ[0m Something went wrong:"
- err "[1;32mcurl[0m or [1;32mwget[0m not available or failed to create temp directory, cannot proceed."
- fi
-}
-
-_check_zshrc() {
- THE_ZDOTDIR="${ZDOTDIR:-${HOME}}"
- say "[34mโโโ[0m[1;36m Updating ${THE_ZDOTDIR}/.zshrc"
- if grep -E '(zi|init|zinit)\.zsh' "${THE_ZDOTDIR}/.zshrc" >/dev/null 2>&1; then
- say "[34mโโโ[34m File .zshrc have conflicting commands, backuping..."
- say "[34mโโโ[34m creating backup at ${CONFIG_DIR}/zshrc..."
- date=$(date +%H%M%S) && command mv -f "${THE_ZDOTDIR}/.zshrc" "${CONFIG_DIR}/zshrc.${date}"
- fi
-}
-
-_set_zshrc_header() {
- # current zshrc headers: (loader, installer)
- _check_zshrc
- if [ "${ZHEADER}" = loader ]; then
- if command -v curl >/dev/null 2>&1; then
- command curl -fsSL "${RAW_LOADER_URL}" -o "${CONFIG_DIR}/init.zsh"
- elif command -v wget >/dev/null 2>&1; then
- command wget -qO "${CONFIG_DIR}/init.zsh" "${RAW_LOADER_URL}"
- else
- err "[1;31mโโโ[0m Something went wrong:[1;32m curl and wget[0m not available, cannot proceed."
- fi
- command chmod a+x "${CONFIG_DIR}/init.zsh"
- command sed -i "s/branch=\"main\"/branch=\"${BRANCH}\"/g" "${CONFIG_DIR}/init.zsh"
- command cat <<-EOF >>"${THE_ZDOTDIR}/.zshrc"
-if [[ -r "${XDG_CONFIG_HOME:-${HOME}/.config}/zi/init.zsh" ]]; then
- source "${XDG_CONFIG_HOME:-${HOME}/.config}/zi/init.zsh" && zzinit
-fi
-EOF
- say "[34mโโโ[0m[1;36m Loader added successfully.[0m"
- elif [ "${ZHEADER}" = installer ]; then
- command cat <<-EOF >>"${THE_ZDOTDIR}/.zshrc"
-if [[ ! -f ${ZI_HOME}/${ZI_BIN_DIR_NAME}/zi.zsh ]]; then
- print -P "%F{33}โโโ %F{160}Installing (%F{33}z-shell/zi%F{160})โฆ%f"
- command mkdir -p "${ZI_HOME}" && command chmod g-rwX "${ZI_HOME}"
- command git clone ${CLONE_OPTS} --branch "${BRANCH}" https://${HOST}/z-shell/zi "${ZI_HOME}/${ZI_BIN_DIR_NAME}" && \\
- print -P "%F{33}โโโ %F{34}Installation successful.%f%b" || \\
- print -P "%F{160}โโโ The clone has failed.%f%b"
-fi
-source "${ZI_HOME}/${ZI_BIN_DIR_NAME}/zi.zsh"
-autoload -Uz _zi
-(( \${+_comps} )) && _comps[zi]=_zi
-EOF
- else
- true
- fi
-}
-
-_setup_directories() {
- _set_externals "$@"
- if ! test -d "${ZI_HOME}"; then
- command mkdir "${ZI_HOME}"
- command chmod g-w "${ZI_HOME}"
- command chmod o-w "${ZI_HOME}"
- fi
- if ! test -d "${ZI_HOME}/${ZI_BIN_DIR_NAME}"; then
- command mkdir "${ZI_HOME}/${ZI_BIN_DIR_NAME}"
- command chmod g-w "${ZI_HOME}/${ZI_BIN_DIR_NAME}"
- command chmod o-w "${ZI_HOME}/${ZI_BIN_DIR_NAME}"
- fi
- if ! test -d "${CONFIG_DIR}"; then
- command mkdir "${CONFIG_DIR}"
- command chmod g-w "${CONFIG_DIR}"
- command chmod o-w "${CONFIG_DIR}"
- fi
- _set_zshrc_header "$@"
-}
-
-_setup_profile() {
- _setup_directories "$@"
- if [ "${PROFILE}" = install ]; then
- if test -d "${ZI_HOME}/${ZI_BIN_DIR_NAME}/.git"; then
- cd "${ZI_HOME}/${ZI_BIN_DIR_NAME}" || return
- say "[34mโโโ[0m Updating [1;36m(z-shell/zi)[1;33m plugin manager[0m at [1;35m${ZI_HOME}/${ZI_BIN_DIR_NAME}[0m"
- command git clean -d -f -f
- command git reset --hard HEAD
- command git pull -q origin HEAD
- command git submodule update --init --recursive
- command git submodule update --recursive --remote
- say "[34mโโโ[0m [1;32mSuccessfully installed [1;36m(z-shell/zi)[0m at [1;35m${ZI_HOME}/${ZI_BIN_DIR_NAME}[0m"
- else
- cd "${ZI_HOME}" || return
- say "[34mโโโ[0m Installing [1;36m(z-shell/zi)[1;33m plugin manager[0m at [1;35m${ZI_HOME}/${ZI_BIN_DIR_NAME}[0m"
- { git clone "${CLONE_OPTS}" --branch "${BRANCH}" https://"${HOST}"/z-shell/zi.git "${ZI_BIN_DIR_NAME}" \
- 2>&1 | { "${WORKDIR}/out/git-process-output.zsh" || cat; }; } 2>/dev/null
- if [ -d "${ZI_BIN_DIR_NAME}" ]; then
- say "[34mโโโ[0m Successfully installed at [1;32m${ZI_HOME}/${ZI_BIN_DIR_NAME}[0m".
- else
- err "[1;31mโโโ[0m Something went wrong, couldn't install ZI at [1;33m${ZI_HOME}/${ZI_BIN_DIR_NAME}[0m"
- fi
- fi
- elif [ "${PROFILE}" = uninstall ]; then
- clear
- say "โโโ Remove โฎ ZI โฏ? [y/N]"
- read -r confirmation
- if [ "${confirmation}" != y ] && [ "${confirmation}" != Y ]; then
- echo "Uninstall process cancelled"
- exit 0
- fi
- clear
- say "Removing โฎ ZI โฏ home directory"
- sleep 2
- if [ -d "${HOME}/.zi" ]; then
- rm -rvf "${HOME}/.zi"
- elif [ -d "${ZDOTDIR}/.zi" ]; then
- rm -rvf "${ZDOTDIR}/.zi"
- elif [ -d "${XDG_DATA_HOME}/.zi" ]; then
- rm -rvf "${XDG_DATA_HOME}/.zi"
- fi
- clear
- echo "โโโ Clean โฎ ZI โฏ cache? [y/N]"
- read -r confirmation
- if [ "${confirmation}" != y ] && [ "${confirmation}" != Y ]; then
- echo "Cleaning โฎ ZI โฏ cache"
- sleep 2
- if [ -d "${HOME}/.cache/zi" ]; then
- rm -rvf "${HOME}/.cache/zi"
- elif [ -d "${ZDOTDIR}/.cache/zi" ]; then
- rm -rvf "${ZDOTDIR}/.cache/zi"
- elif [ -d "${XDG_DATA_HOME}/.cache/zi" ]; then
- rm -rvf "${XDG_DATA_HOME}/.cache/zi"
- fi
- fi
- clear
- echo "โโโ Remove โฎ ZI โฏ config directory? [y/N]"
- read -r confirmation
- if [ "${confirmation}" != y ] && [ "${confirmation}" != Y ]; then
- echo "Removing โฎ ZI โฏ config directory"
- sleep 2
- if [ -d "${XDG_CONFIG_HOME}/zi" ]; then
- rm -rvf "${XDG_CONFIG_HOME}/zi"
- else
- if [ -d "${HOME}/.config/zi" ]; then
- rm -rvf "${HOME}/.config/zi"
- elif [ -d "${XDG_DATA_HOME}/zi" ]; then
- rm -rvf "${XDG_DATA_HOME}/zi"
- fi
- fi
- fi
- clear
- echo "โโโ Reload shell? [y/N]"
- read -r confirmation
- if [ "${confirmation}" != y ] && [ "${confirmation}" != Y ]; then
- say "[34mโโโ[0m Uninstall successful"
- command cat <<-EOF
-[34mโโโ[0m[1;36m โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โฎ ZI โฏ[0m
-[34mโโโ[0m[38;5;226m Wiki: https://wiki.zshell.dev[0m
-[34mโโโ[0m[38;5;226m Issues: https://github.com/z-shell/zi/issues[0m
-[34mโโโ[0m[38;5;226m Discussions: https://discussions.zshell.dev[0m"
-EOF
- rm -rf "${WORKDIR}"
- exit 0
- else
- rm -rf "${WORKDIR}"
- exec "${SHELL}" -l
- fi
- elif [ "${PROFILE}" = main ]; then
- true
- else
- err "Invalid profile: ${PROFILE}" 1>&2
- fi
-}
-
-_make_build() {
- if [ "${MAKE}" = zpmod ]; then
- ZI_HOME="${ZI_HOME:-${ZDOTDIR:-${HOME}}/.zi}"
- MOD_HOME="${MOD_HOME:-zmodules}/zpmod"
- if ! test -d "${ZI_HOME}/${MOD_HOME}"; then
- mkdir -p "${ZI_HOME}/${MOD_HOME}"
- chmod g-rwX "${ZI_HOME}/${MOD_HOME}"
- fi
- say "${col_pname}== Downloading ZPMOD module to ${ZI_HOME}/${MOD_HOME}"
- if test -d "${ZI_HOME}/${MOD_HOME}/.git"; then
- cd "${ZI_HOME}/${MOD_HOME}" || return
- git pull -q origin main
- else
- cd "${ZI_HOME}" || return
- git clone "${CLONE_OPTS}" https://"${HOST}"/z-shell/zpmod.git "${MOD_HOME}"
- fi
- say "${col_pname}== Done"
- if command -v zsh >/dev/null; then
- say "${col_info}-- Checkig version --${col_rst}"
- if expr "${zsh_current}" \< "${zsh_required}" >/dev/null; then
- say "${col_error}-- Zsh version 5.8.1 and above required --${col_rst}"
-
- else
- say "${col_info}-- Zsh version ${zsh_current} --${col_rst}"
- cd "${ZI_HOME}/${MOD_HOME}" || return
- say "${col_pname}== Building module ZPMOD, running: a make clean, then ./configure and then make ==${col_rst}"
- say "${col_pname}== The module sources are located at: ${ZI_HOME}/${MOD_HOME} ==${col_rst}"
- if test -f Makefile; then
- if [ "$1" = "--clean" ]; then
- say "${col_info}-- make distclean --${col_rst}"
- make -s distclean
- true
- else
- say "${col_info}-- make clean (pass --clean to invoke \`make distclean') --${col_rst}"
- make -s clean
- fi
- fi
- say "${col_info}-- Configuring --${col_rst}"
- if CPPFLAGS=-I/usr/local/include CFLAGS="-g -Wall -O3" LDFLAGS=-L/usr/local/lib ./configure --disable-gdbm --without-tcsetpgrp; then
- say "${col_info}-- Running make --${col_rst}"
- if make -s; then
- command cat <<-EOF
-[38;5;219mโโโ[0m [38;5;220mModule [38;5;177mhas been built correctly.
-[38;5;219mโโโ[0m [38;5;220mSee 'zpmod -h' for more information.
-[38;5;219mโโโ[0m [38;5;220mRun 'zpmod source-study' to see profile data,
-[38;5;219mโโโ[0m [38;5;177mGuaranteed, automatic compilation of any sourced script.
-EOF
- zpmod_file="${WORKDIR}/zpmod"
- command cat <<-EOF >>"${zpmod_file}"
-module_path+=( "${ZI_HOME}/${MOD_HOME}/Src" )
-zmodload zi/zpmod
-EOF
- say "[34mโโโ[0m[1;36m Enabling zpmod[0m"
- command cat "${zpmod_file}" >>"${THE_ZDOTDIR}/.zshrc"
- zsh -ic "@zi-scheduler burst"
- else
- say "${col_error}Module did not build.${col_rst}. You can copy the error messages and submit"
- err "error-report at: https://${HOST}/z-shell/zpmod/issues"
- fi
- fi
- fi
- else
- err "${col_error} Zsh is not installed. Please install zsh and try again.${col_rst}"
- fi
- else
- true
- fi
-}
-
-_set_annexes() {
- if [ "${ANNEX}" = recommended ]; then
- file="${WORKDIR}/annex_recommended"
- command cat <<-EOF >>"${file}"
-zi light-mode for \\
- z-shell/z-a-meta-plugins \\
- @annexes # <- https://wiki.zshell.dev/ecosystem/category/-annexes
-# examples here -> https://wiki.zshell.dev/community/gallery/collection
-zicompinit # <- https://wiki.zshell.dev/docs/guides/commands
-EOF
- say "[34mโโโ[0m[1;36m Installing annexes[0m"
- command cat "${file}" >>"${THE_ZDOTDIR}/.zshrc"
- zsh -ic "@zi-scheduler burst"
- else
- true
- fi
-}
-
-_finish_install() {
- git_refs="$(
- command cd "${ZI_HOME}/${ZI_BIN_DIR_NAME}" || true
- command git log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit | head -3
- )"
- say "[34mโโโ[0m[38;5;226m Latest changes:[0m"
- say "${git_refs}"
-}
-
-_system() {
- _os_type
- _cpu_type
- _setup_profile "$@"
- _make_build "$@"
- _set_annexes "$@"
- _finish_install "$@"
-}
-
-MAIN() {
- _system "$@"
- say "[34mโโโ[0m[1;36m System: ${OS} - ${ARCH}"
- command cat <<-EOF
-[34mโโโ[0m[1;36m โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ Successfully installed โฎ ZI โฏ โ โ โ โ โ โ โ โ โ [0m
-[34mโโโ[0m[38;5;226m Wiki: https://wiki.zshell.dev[0m
-[34mโโโ[0m[38;5;226m Issues: https://github.com/z-shell/zi/issues[0m
-[34mโโโ[0m[38;5;226m Discussions: https://discussions.zshell.dev[0m
-[34mโโโ[0m[1;36m โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ [0m
-EOF
- exit 0
-}
-
-while true; do
- MAIN "${@}"
-done
diff --git a/lib/sh/install_alpha.sh b/lib/sh/install_alpha.sh
deleted file mode 100755
index a62d423..0000000
--- a/lib/sh/install_alpha.sh
+++ /dev/null
@@ -1,512 +0,0 @@
-#!/usr/bin/env sh
-# -*- mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
-# vim: ft=sh sw=2 ts=2 et
-
-# shellcheck disable=all
-
-# Temporary work directory
-trap 'rm -rf "$WORKDIR"' EXIT INT
-
-# Variables
-WORKDIR="$(mktemp -d)"
-ZI_REPO="https://github.com/z-shell/zi"
-MOD_REPO="https://github.com/z-shell/zpmod"
-GIT_BAR="${WORKDIR}/git-progress-bar.zsh"
-GIT_BAR_URL="https://raw.githubusercontent.com/z-shell/zi/main/lib/zsh/git-process-output.zsh"
-LOADER_URL="https://raw.githubusercontent.com/z-shell/zi-src/main/lib/zsh/init.zsh"
-
-# Messages
-say() {
- while [ -n "$1" ]; do
- case "$1" in
- -normal) col="\033[00m" ;;
- -black) col="\033[30;01m" ;;
- -red) col="\033[31;01m" ;;
- -green) col="\033[32;01m" ;;
- -yellow) col="\033[33;01m" ;;
- -blue) col="\033[34;01m" ;;
- -magenta) col="\033[35;01m" ;;
- -cyan) col="\033[36;01m" ;;
- -white) col="\033[37;01m" ;;
- -n)
- one_line=1
- shift
- continue
- ;;
- *)
- printf '%s' "$1"
- shift
- continue
- ;;
- esac
- shift
- printf "%s${col}"
- printf '%s' "$1"
- printf "\033[00m"
- shift
- done
- [ -z "${one_line}" ] && printf "\n"
-}
-
-ask() {
- question="$1"
- printf "\033[34;1mโโโ \033[00mยป "
- say -yellow "$question" -n
- printf " \033[00m[y/N]: "
- read -r answer
- case $answer in
- [yY]*)
- true
- ;;
- *)
- false
- ;;
- esac
-}
-
-err() {
- say -red "$1" >&2
- exit 1
-}
-
-say_ok() {
- printf "\033[34;1mโโโ\033[32;01m โ \033[00mยป "
- say -green "$1"
- printf "\033[00m"
-}
-
-say_err() {
- printf "\033[34;01mโโโ\033[31;01m โ \033[00mยป "
- say -red "$*" >&2
- printf "\033[00m"
- exit 1
-}
-
-say_info() {
- printf "\033[34;1mโโโ\033[36;01m โก\033[00mยป "
- say -cyan "$1"
- printf "\033[00m"
-}
-
-while getopts ":i:a:b:" opt; do
- case ${opt} in
- i)
- ZOPT="${ZOPT}${OPTARG}"
- ;;
- a)
- AOPT="${AOPT}${OPTARG}"
- ;;
- b)
- BOPT="${OPTARG}"
- ;;
- \?)
- say_err "Invalid option: ${OPTARG}"
- ;;
- :)
- say_err "Invalid option: ${OPTARG} requires an argument"
- ;;
- *)
- say_err "Invalid option: ${OPTARG}"
- ;;
- esac
-done
-shift $((OPTIND - 1))
-
-# Default options
-[ -z "$BOPT" ] && BOPT="main"
-
-# Functions
-is_cmd() { command -v "$1" >/dev/null 2>&1; }
-
-check_cmd() {
- if ! is_cmd "$1"; then
- say_err "$1 not found. Please install it and try again."
- fi
-}
-
-download() {
- # Set download command
- if is_cmd curl; then
- command curl -fsSL "$1" -o "$2" && command chmod a+x "$2"
- elif is_cmd wget; then
- command wget -qO "$2" "$1" && command chmod a+x "$2"
- else
- say_err "curl or wget is required. Please install it and try again."
- fi
-}
-
-git_clone() {
- command git clone --progress --depth 1 --branch "$BOPT" "$1" "$2" 2>&1 | { "$GIT_BAR" || cat; } 2>/dev/null
-}
-
-prepare_installer() {
- # Check for required commands
- check_cmd git
- check_cmd zsh
-
- # Establish Zi home directory
- if [ -z "$ZI_HOME" ]; then
- if [ -d "${HOME}" ]; then
- ZSH_HOME_DIR="$HOME"
- ZI_HOME="${HOME}/.zi"
- elif [ -d "${ZDOTDIR}" ]; then
- ZSH_HOME_DIR="$ZDOTDIR"
- ZI_HOME="${ZDOTDIR}/.zi"
- elif [ -d "${XDG_DATA_HOME}" ]; then
- ZSH_HOME_DIR="$XDG_DATA_HOME"
- ZI_HOME="${XDG_DATA_HOME}/.zi"
- fi
- fi
-
- if [ ! -d "$ZI_HOME" ]; then
- command mkdir -p "$ZI_HOME"
- fi
-
- if [ ! -w "$ZI_HOME" ]; then
- command chown -R "$(whoami)"
- command chmod -R go-w "$ZI_HOME"
- fi
-
- # Establish Zi bin directory
- if [ -z "$ZI_BIN_DIR" ]; then
- ZI_BIN_DIR="${ZI_HOME}/bin"
- fi
-
- if [ ! -d "$ZI_BIN_DIR" ]; then
- command mkdir -p "$ZI_BIN_DIR"
- fi
-
- if [ ! -w "$ZI_BIN_DIR" ]; then
- command chown -R "$(whoami)"
- command chmod -R go-w "$ZI_BIN_DIR"
- fi
-
- if [ -z "$ZSH_CACHE_DIR" ]; then
- ZSH_CACHE_DIR="${ZSH_HOME_DIR}/.cache/zi"
- fi
-
- if [ ! -d "$ZSH_CACHE_DIR" ]; then
- command mkdir -p "$ZSH_CACHE_DIR"
- fi
-
- if [ ! -w "$ZSH_CACHE_DIR" ]; then
- command chown -R "$(whoami)"
- command chmod -R go-w "$ZSH_CACHE_DIR"
- fi
-
- if [ -z "$ZSH_LOG_DIR" ]; then
- ZSH_LOG_DIR="${ZSH_HOME_DIR}/.cache/zi/logs"
- fi
-
- if [ -z "$ZSH_LOG_FILE" ]; then
- ZSH_LOG_FILE="${ZSH_LOG_DIR}/$(date +%Y-%m-%d).log"
- fi
-
- if [ ! -f "$GIT_BAR" ]; then
- download "$GIT_BAR_URL" "$GIT_BAR"
- fi
-}
-
-check_zshrc() {
- # Check if Zi is already installed
- if grep -E '(zi|init|zinit)\.zsh' "${ZSH_HOME_DIR}/.zshrc" >/dev/null 2>&1; then
- say_info "Zi already set in .zshrc, backing up to .zshrc.bak"
- command mv "${ZSH_HOME_DIR}/.zshrc" "${ZSH_HOME_DIR}/.zshrc.bak"
- elif [ -f "${ZSH_HOME_DIR}/.zshrc" ]; then
- say_info "Backing up to current .zshrc to .zshrc.bak"
- command mv "${ZSH_HOME_DIR}/.zshrc" "${ZSH_HOME_DIR}/.zshrc.bak"
- fi
-}
-
-set_repository() {
- prepare_installer "$@"
-
- if [ -d "${ZI_BIN_DIR}/.git" ]; then
- builtin cd "${ZI_BIN_DIR}" && say_info "Found Zi at $ZI_BIN_DIR, updating..."
- command git clean --quiet -d -f -f
- command git reset --quiet --hard HEAD
- command git pull --quiet origin HEAD
- say_ok "Update Successful!"
- return 0
- elif [ -d "$ZI_BIN_DIR" ]; then
- git_clone "$ZI_REPO" "$ZI_BIN_DIR"
- if [ -f "${ZI_BIN_DIR}/zi.zsh" ]; then
- command cat <<-EOF
-[34mโโโ[0m[1;36m โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ Successfully installed Zi โ โ โ โ โ โ โ โ โ โ โ โ โ [0m
-EOF
- return 0
- else
- say_err "Something went wrong, couldn't proceed with installation."
- fi
- fi
-}
-
-set_loader() {
- check_zshrc
- # Establish Zi config directory
- if [ -z "$ZI_CONFIG_DIR" ]; then
- ZI_CONFIG_DIR="${XDG_CONFIG_HOME:-${HOME}/.config}/zi"
- fi
-
- if [ ! -d "$ZI_CONFIG_DIR" ]; then
- command mkdir -p "$ZI_CONFIG_DIR"
- fi
-
- if [ ! -w "$ZI_CONFIG_DIR" ]; then
- command chmod go-w "$ZI_CONFIG_DIR"
- fi
-
- download "$LOADER_URL" "${ZI_CONFIG_DIR}/init.zsh"
- command sed -i "s/branch=\"main\"/branch=\"${BOPT}\"/g" "${ZI_CONFIG_DIR}/init.zsh"
- command cat <<-EOF >>"$ZSH_HOME_DIR/.zshrc"
-# Zi Loader ========================================================================================================= #
-# https://wiki.zshell.dev/docs/getting_started/installation
-if [[ -r "${XDG_CONFIG_HOME:-${HOME}/.config}/zi/init.zsh" ]]; then
- source "${XDG_CONFIG_HOME:-${HOME}/.config}/zi/init.zsh" && zzinit
-fi
-
-EOF
- return 0
-}
-
-set_installer() {
- check_zshrc
- command cat <<-EOF >>"$ZSH_HOME_DIR/.zshrc"
-# Zi source directory =============================================================================================== #
-# https://wiki.zshell.dev/docs/guides/customization#customizing-paths
-typeset -A ZI
-ZI[BIN_DIR]="$ZI_BIN_DIR"
-
-# Auto install Zi =================================================================================================== #
-if [[ ! -f \${ZI[BIN_DIR]}/zi.zsh ]]; then
- print -P "%F{33}โโโ %F{160}Installing (%F{33}z-shell/zi%F{160})โฆ%f"
- command mkdir -p "\$ZI[BIN_DIR]" && \\
- command git clone -q --branch "${BOPT}" $ZI_REPO "\${ZI[BIN_DIR]}" && \\
- print -P "%F{33}โโโ %F{34}Installation successfulโฆ%f%b" || print -P "%F{160}โโโ The clone has failed.%f%b"
-fi
-
-# Enable Zi ========================================================================================================= #
-# https://wiki.zshell.dev/docs/getting_started/installation#manual-setup
-source "\${ZI[BIN_DIR]}/zi.zsh"
-autoload -Uz _zi
-(( \${+_comps} )) && _comps[zi]=_zi
-
-EOF
- return 0
-}
-
-set_omz_lib() {
- command cat <<-EOF >>"$ZSH_HOME_DIR/.zshrc"
-# Oh-My-Zsh lib ===================================================================================================== #
-# https://wiki.zshell.dev/docs/getting_started/migration#omz-library
-zi is-snippet wait lucid for \\
- OMZL::{git,theme-and-appearance,prompt_info_functions,vcs_info}.zsh \\
- atinit'COMPLETION_WAITING_DOTS=true' \\
- OMZL::completion.zsh \\
- atinit'typeset -gx HISTSIZE=290000 SAVEHIST=290000 HISTFILE=${ZSH_CACHE_DIR}/.history' \\
- OMZL::history.zsh
-
-EOF
-}
-
-set_omz_plugins() {
- command cat <<-EOF >>"$ZSH_HOME_DIR/.zshrc"
-# Oh-My-Zsh plugins ================================================================================================= #
-# https://wiki.zshell.dev/docs/getting_started/migration#omz-plugins
-zi is-snippet wait lucid for \\
- atload"unalias grv" \\
- OMZP::git \\
- if'[[ -d ~/.ssh ]]' \\
- OMZP::ssh-agent \\
- if'[[ -d ~/.gnupg ]]' \\
- OMZP::gpg-agent
-
-EOF
-}
-
-set_omz_themes() {
- command cat <<-EOF >>"$ZSH_HOME_DIR/.zshrc"
-# Oh-My-Zsh theme =================================================================================================== #
-# https://wiki.zshell.dev/community/gallery/collection/themes
-# https://wiki.zshell.dev/docs/getting_started/migration#omz-themes
-zi wait'!' lucid for \\
- atinit'setopt prompt_subst' \\
- OMZT::robbyrussell
-
-EOF
-}
-
-set_plugins() {
- command cat <<-EOF >>"$ZSH_HOME_DIR/.zshrc"
-# Popular plugins =================================================================================================== #
-# https://wiki.zshell.dev/ecosystem
-# https://wiki.zshell.dev/community/gallery/collection/plugins
-zi wait lucid for \\
- atinit'ZI[COMPINIT_OPTS]=-C; zicompinit; zicdreplay' \\
- z-shell/F-Sy-H \\
- atload'!_zsh_autosuggest_start' \\
- zsh-users/zsh-autosuggestions \\
- blockf atpull' zi creinstall -q .' \\
- zsh-users/zsh-completions \\
- atinit'zstyle ":history-search-multi-word" page-size "7"' \\
- z-shell/H-S-MW
-EOF
-}
-
-set_themes() {
- command cat <<-EOF >>"$ZSH_HOME_DIR/.zshrc"
-# Popular themes ==================================================================================================== #
-# https://wiki.zshell.dev/community/gallery/collection/themes
-
-EOF
-}
-
-set_annexes() {
- command cat <<-EOF >>"$ZSH_HOME_DIR/.zshrc"
-# Meta-plugins & annexes =========================================================================================== #
-# https://wiki.zshell.dev/ecosystem/category/-annexes
-zi for \\
- z-shell/z-a-meta-plugins \\
- @annexes
-
-EOF
-}
-
-set_zpmod() {
- check_cmd make
-
- # Establish zpmod directory
- if [ -z "$MOD_HOME" ]; then
- MOD_HOME="${ZI_HOME}/zmodules/zpmod"
- fi
-
- if [ ! -d "$MOD_HOME" ]; then
- command mkdir -p "$MOD_HOME"
- fi
-
- if [ ! -w "$MOD_HOME" ]; then
- command chmod go-w "$MOD_HOME"
- fi
-
- if [ -d "${MOD_HOME}/.git" ]; then
- say_info "Updating ZPMOD at $MOD_HOME"
- builtin cd "$MOD_HOME" && command git pull -q --ff-only origin main
- else
- say_info "Downloading ZPMOD to $MOD_HOME"
- command git clone -q "$MOD_REPO" "$MOD_HOME"
- fi
-
- say_info "Checkig version for zsh..."
- ZSH_CURRENT=$(zsh --version /dev/null; then
- say_err "Zsh version 5.8.1 and above required."
- else
- say_info "Zsh version ${ZSH_CURRENT} is compatible."
- builtin cd "$MOD_HOME" || err "Failed to change directory to $MOD_HOME."
- say_info "Building module ZPMOD, running: a make clean, then ./configure and then make."
- say_info "The module source are located at: $MOD_HOME"
- if test -f Makefile; then
- if [ "$1" = "--clean" ]; then
- say_info "Running: make distclean..."
- make distclean
- true
- else
- say_info "Running: make clean (pass --clean to invoke \`make distclean')..."
- make clean
- fi
- fi
- say_info "Configuring..."
- if CPPFLAGS=-I/usr/local/include CFLAGS="-g -Wall -O3" LDFLAGS=-L/usr/local/lib ./configure --disable-gdbm --without-tcsetpgrp; then
- say_info "Building..."
- if make -s; then
- command cat <<-EOF
-[38;5;219mโโโ[0m [38;5;220mModule [38;5;177mhas been built correctly.
-[38;5;219mโโโ[0m [38;5;220mTo [38;5;160mload the module, add following [38;5;220m2 lines to [38;5;172m.zshrc, at top:
-[0m [38;5;51m module_path+=( "${MOD_HOME}/Src" )
-[0m [38;5;51m zmodload zi/zpmod
-[38;5;219mโโโ[0m [38;5;220mSee 'zpmod -h' for more information.
-[38;5;219mโโโ[0m [38;5;220mRun 'zpmod source-study' to see profile data,
-[38;5;219mโโโ[0m [38;5;177mGuaranteed, automatic compilation of any sourced script.
-EOF
- else
- say_err "Module failed build. Please report error at: ${MOD_REPO}/issues"
- fi
- fi
- fi
-}
-
-interactive_zshrc() {
- if [ "$ZOPT" != skip ] && [ "$AOPT" = interactive ]; then
- say_info "Creating .zshrc interactively..."
- if ask "Install Zi Loader?"; then
- set_loader
- else
- set_installer
- fi
-
- if ask "Install annexes?"; then
- set_annexes
- fi
-
- if ask "Add recommended Oh-My-Zsh library?"; then
- set_omz_lib
- fi
-
- if ask "Add recommended Oh-My-Zsh plugins?"; then
- set_omz_plugins
- fi
-
- if ask "Add recommended Oh-My-Zsh theme?"; then
- set_omz_themes
- fi
-
- if ask "Add recommended plugins?"; then
- set_plugins
- fi
-
- zsh -ilc "@zi-scheduler burst"
- command cat <<-EOF
-[34mโโโ[0m[1;36m โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ Successfully created .zshrc โ โ โ โ โ โ โ โ โ โ โ โ [0m
-EOF
- return 0
- fi
-}
-
-default_zshrc() {
- if [ "$ZOPT" != skip ] && [ "$AOPT" = default ]; then
- say_info "Creating .zshrc file..."
- set_loader
- set_annexes
- set_omz_lib
- set_omz_plugins
- set_omz_themes
- set_plugins
-
- zsh -ilc "@zi-scheduler burst"
- command cat <<-EOF
-[34mโโโ[0m[1;36m โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ Successfully created .zshrc โ โ โ โ โ โ โ โ โ โ โ โ [0m
-EOF
- return 0
- fi
-}
-
-MAIN() {
- set_repository "$@"
- default_zshrc
-
- command cat <<-EOF
-
-[34mโโโ[0m[38;5;226m Wiki: https://wiki.zshell.dev[0m
-[34mโโโ[0m[38;5;226m Issues: https://github.com/z-shell/zi/issues[0m
-[34mโโโ[0m[38;5;226m Discussions: https://discussions.zshell.dev[0m
-
-[34mโโโ[0m[1;36m โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ [0m
-
-EOF
- exit $?
-}
-
-while true; do
- MAIN "${@}"
-done
From b003a258fb101f683bcb7131766676a4d336d6ac Mon Sep 17 00:00:00 2001
From: Salvydas Lukosius
Date: Fri, 15 May 2026 23:59:14 +0100
Subject: [PATCH 2/7] ci: update workflows and trunk configuration
- Bump actions/checkout to v6.0.2 and shellcheck to 2.0.0
- Add lib/zsh/** and tests/** to push/PR path triggers
- Add permissions: contents: read and timeout-minutes: 10
- Use github.ref in concurrency group
- Replace ~/.zi hard-coded paths with XDG_DATA_HOME equivalents
- Add unit-fixture step calling tests/installers.sh
- Remove wrangler deploy job; update trunk linter config
---
.github/workflows/check-linux.yml | 36 ++++++++++++++++---------
.github/workflows/check-macos.yml | 38 ++++++++++++++++++---------
.github/workflows/checksum.yml | 16 ++++++++---
.github/workflows/deploy-gh-pages.yml | 22 ++++++++++++++--
.github/workflows/rclone-action.yml | 9 +++++--
.github/workflows/win-install.yml | 25 ++++++++++++------
.trunk/trunk.yaml | 31 +++++++++++++++-------
7 files changed, 127 insertions(+), 50 deletions(-)
diff --git a/.github/workflows/check-linux.yml b/.github/workflows/check-linux.yml
index 3af9a27..705dfd7 100644
--- a/.github/workflows/check-linux.yml
+++ b/.github/workflows/check-linux.yml
@@ -5,24 +5,34 @@ on:
branches: [main]
paths:
- "lib/sh/**"
+ - "lib/zsh/**"
+ - "tests/**"
+ - ".github/workflows/check-linux.yml"
pull_request:
branches: [main]
paths:
- "lib/sh/**"
+ - "lib/zsh/**"
+ - "tests/**"
+ - ".github/workflows/check-linux.yml"
workflow_dispatch:
+permissions:
+ contents: read
+
concurrency:
- group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
+ group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
shellcheck:
runs-on: ubuntu-latest
+ timeout-minutes: 10
steps:
- name: โคต๏ธ Check out code from GitHub
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: โ๏ธ ShellCheck
- uses: ludeeus/action-shellcheck@00b27aa7cb85167568cb48a3838b75f4265f2bca
+ uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # 2.0.0
with:
scandir: "./lib/sh"
@@ -32,24 +42,26 @@ jobs:
needs: [shellcheck]
steps:
- name: โคต๏ธ Check out code from GitHub
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: โ๏ธ Prepare dependencies
run: |
sudo apt-get update
sudo apt-get install -y zsh
+ - name: "โ๏ธ Check: unit fixtures"
+ run: sh ./tests/installers.sh
- name: "โ๏ธ Check: install.sh -- -i skip"
- run: sh -x ./lib/sh/install.sh -- -i skip; command rm -rf ~/.zi
- - name: "โ๏ธ Check: install.sh -- -i annex"
- run: sh -x ./lib/sh/install.sh -- -a annex; command rm -rf ~/.zi
- - name: "โ๏ธ Check: install.sh -- -i loader"
- run: sh -x ./lib/sh/install.sh -- -a loader; command rm -rf ~/.zi
- - name: "โ๏ธ Check: install.sh -- -i zunit"
- run: sh -x ./lib/sh/install.sh -- -a zunit; command rm -rf ~/.zi
+ run: sh -x ./lib/sh/install.sh -- -i skip; command rm -rf "${XDG_DATA_HOME:-$HOME/.local/share}/zi" ~/.zi
+ - name: "โ๏ธ Check: install.sh -- -a annex"
+ run: sh -x ./lib/sh/install.sh -- -a annex; command rm -rf "${XDG_DATA_HOME:-$HOME/.local/share}/zi" ~/.zi
+ - name: "โ๏ธ Check: install.sh -- -a loader"
+ run: sh -x ./lib/sh/install.sh -- -a loader; command rm -rf "${XDG_DATA_HOME:-$HOME/.local/share}/zi" ~/.zi
+ - name: "โ๏ธ Check: install.sh -- -a zunit"
+ run: sh -x ./lib/sh/install.sh -- -a zunit; command rm -rf "${XDG_DATA_HOME:-$HOME/.local/share}/zi" ~/.zi
- name: "โ๏ธ Check: install_zpmod.sh"
run: sh -x ./lib/sh/install_zpmod.sh
- name: โ๏ธ Load zpmod module
run: |
- module_path+=( "$HOME/.zi/zmodules/zpmod/Src" )
+ module_path+=( "${XDG_DATA_HOME:-$HOME/.local/share}/zi/zmodules/zpmod/Src" )
zmodload zi/zpmod
zpmod source-study -l
shell: zsh {0}
diff --git a/.github/workflows/check-macos.yml b/.github/workflows/check-macos.yml
index 0acf6d1..1d1d8e0 100644
--- a/.github/workflows/check-macos.yml
+++ b/.github/workflows/check-macos.yml
@@ -6,50 +6,62 @@ on:
branches: [main]
paths:
- "lib/sh/**"
+ - "lib/zsh/**"
+ - "tests/**"
+ - ".github/workflows/check-macos.yml"
pull_request:
branches: [main]
paths:
- "lib/sh/**"
+ - "lib/zsh/**"
+ - "tests/**"
+ - ".github/workflows/check-macos.yml"
workflow_dispatch:
+permissions:
+ contents: read
+
concurrency:
- group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
+ group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
shellcheck:
runs-on: ubuntu-latest
+ timeout-minutes: 10
steps:
- name: โคต๏ธ Check out code from GitHub
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: โ๏ธ ShellCheck
- uses: ludeeus/action-shellcheck@00b27aa7cb85167568cb48a3838b75f4265f2bca
+ uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # 2.0.0
with:
scandir: "./lib/sh"
build:
- runs-on: ubuntu-latest
+ runs-on: macos-latest
timeout-minutes: 30
needs: [shellcheck]
steps:
- name: โคต๏ธ Check out code from GitHub
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: โ๏ธ Prepare dependencies
run: |
brew install zsh
+ - name: "โ๏ธ Check: unit fixtures"
+ run: sh ./tests/installers.sh
- name: "โ๏ธ Check: install.sh -- -i skip"
- run: sh -x ./lib/sh/install.sh -- -i skip; command rm -rf ~/.zi
- - name: "โ๏ธ Check: install.sh -- -i annex"
- run: sh -x ./lib/sh/install.sh -- -a annex; command rm -rf ~/.zi
- - name: "โ๏ธ Check: install.sh -- -i loader"
- run: sh -x ./lib/sh/install.sh -- -a loader; command rm -rf ~/.zi
- - name: "โ๏ธ Check: install.sh -- -i zunit"
- run: sh -x ./lib/sh/install.sh -- -a zunit; command rm -rf ~/.zi
+ run: sh -x ./lib/sh/install.sh -- -i skip; command rm -rf "${XDG_DATA_HOME:-$HOME/.local/share}/zi" ~/.zi
+ - name: "โ๏ธ Check: install.sh -- -a annex"
+ run: sh -x ./lib/sh/install.sh -- -a annex; command rm -rf "${XDG_DATA_HOME:-$HOME/.local/share}/zi" ~/.zi
+ - name: "โ๏ธ Check: install.sh -- -a loader"
+ run: sh -x ./lib/sh/install.sh -- -a loader; command rm -rf "${XDG_DATA_HOME:-$HOME/.local/share}/zi" ~/.zi
+ - name: "โ๏ธ Check: install.sh -- -a zunit"
+ run: sh -x ./lib/sh/install.sh -- -a zunit; command rm -rf "${XDG_DATA_HOME:-$HOME/.local/share}/zi" ~/.zi
- name: "โ๏ธ Check: install_zpmod.sh"
run: sh -x ./lib/sh/install_zpmod.sh
- name: โ๏ธ Load zpmod module
run: |
- module_path+=( "$HOME/.zi/zmodules/zpmod/Src" )
+ module_path+=( "${XDG_DATA_HOME:-$HOME/.local/share}/zi/zmodules/zpmod/Src" )
zmodload zi/zpmod
zpmod source-study -l
shell: zsh {0}
diff --git a/.github/workflows/checksum.yml b/.github/workflows/checksum.yml
index 66080e7..2a84471 100644
--- a/.github/workflows/checksum.yml
+++ b/.github/workflows/checksum.yml
@@ -3,20 +3,30 @@ name: "๐ Checksum"
on:
push:
paths:
- - "lib/**"
+ - "lib/sh/install_zpmod.sh"
+ - "lib/sh/install.sh"
+ - "lib/sh/sync-init.sh"
+ - "lib/zsh/init.zsh"
+ - ".github/workflows/checksum.yml"
workflow_dispatch: {}
+permissions:
+ contents: write
+
jobs:
checksum:
+ if: github.repository == 'z-shell/zi-src'
runs-on: ubuntu-latest
+ timeout-minutes: 10
steps:
- - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: "๐ Generate checksum"
- uses: jmgilman/actions-generate-checksum@521a903edf511407d8bd5535d257402fd9bb5db0
+ uses: jmgilman/actions-generate-checksum@3ea6dc9bf8eecf28e2ecc982fab683484a1a8561 # v1.0.1
with:
patterns: |
lib/sh/install_zpmod.sh
lib/sh/install.sh
+ lib/sh/sync-init.sh
lib/zsh/init.zsh
- run: mv checksum.txt lib/
- name: "๐ Commit"
diff --git a/.github/workflows/deploy-gh-pages.yml b/.github/workflows/deploy-gh-pages.yml
index 688a65f..83b21fd 100644
--- a/.github/workflows/deploy-gh-pages.yml
+++ b/.github/workflows/deploy-gh-pages.yml
@@ -8,17 +8,35 @@ on:
tags: ["v*.*.*"]
paths:
- "lib/**"
+ - ".github/workflows/deploy-gh-pages.yml"
+
+permissions:
+ contents: write
jobs:
deploy:
+ if: github.repository == 'z-shell/zi-src'
environment:
name: github-pages
runs-on: ubuntu-latest
+ timeout-minutes: 15
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
steps:
- name: โคต๏ธ Check out code from GitHub
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ - name: "๐ท Prepare deployment metadata"
+ id: prepare_deploy
+ run: |
+ commit_message="$(jq -r '.head_commit.message // empty' "$GITHUB_EVENT_PATH")"
+ if [ -z "$commit_message" ]; then
+ commit_message="Deploy ${GITHUB_REF_NAME}"
+ fi
+ {
+ echo "commit_message<> "$GITHUB_OUTPUT"
- name: "๐ท Prepare tag"
id: prepare_tag
if: startsWith(github.ref, 'refs/tags/')
@@ -34,6 +52,6 @@ jobs:
publish_dir: ./lib
user_name: ${{ secrets.ACTIONS_USER }}
user_email: ${{ secrets.ACTIONS_MAIL }}
- commit_message: ${{ github.event.head_commit.message }}
+ commit_message: ${{ steps.prepare_deploy.outputs.commit_message }}
tag_name: ${{ steps.prepare_tag.outputs.deploy_tag_name }}
tag_message: "Deployment ${{ steps.prepare_tag.outputs.tag_name }}"
diff --git a/.github/workflows/rclone-action.yml b/.github/workflows/rclone-action.yml
index e4f62b6..719d600 100644
--- a/.github/workflows/rclone-action.yml
+++ b/.github/workflows/rclone-action.yml
@@ -5,8 +5,12 @@ on:
branches: [main]
paths:
- "lib/**"
+ - ".github/workflows/rclone-action.yml"
workflow_dispatch: {}
+permissions:
+ contents: read
+
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
@@ -15,14 +19,15 @@ jobs:
sync:
if: github.repository == 'z-shell/zi-src'
runs-on: ubuntu-latest
+ timeout-minutes: 15
env:
local_path: "lib"
remote_path: "r2:r2-store/src"
steps:
- name: "โคต๏ธ Check out code from GitHub"
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: "โซ Run rclone/r2-store"
- uses: z-shell/.github/actions/rclone@v1
+ uses: z-shell/.github/actions/rclone@91068ee88e8788deff439d6ee36b77329edeb98a # v1.0.8
with:
config: ${{ secrets.R2_STORE }}
args: "copy --check-first ${{ env.local_path }} ${{ env.remote_path }}"
diff --git a/.github/workflows/win-install.yml b/.github/workflows/win-install.yml
index c9c32f1..c1b5cc5 100644
--- a/.github/workflows/win-install.yml
+++ b/.github/workflows/win-install.yml
@@ -5,20 +5,28 @@ on:
pull_request:
paths:
- "lib/sh/**"
+ - "lib/zsh/**"
+ - "tests/**"
- ".github/workflows/win-install.yml"
push:
paths:
- "lib/sh/**"
+ - "lib/zsh/**"
+ - "tests/**"
- ".github/workflows/win-install.yml"
workflow_dispatch: {}
+permissions:
+ contents: read
+
jobs:
shellcheck:
runs-on: ubuntu-latest
+ timeout-minutes: 10
steps:
- - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: โ๏ธ ShellCheck
- uses: ludeeus/action-shellcheck@00b27aa7cb85167568cb48a3838b75f4265f2bca
+ uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # 2.0.0
with:
scandir: "./lib/sh"
run-install:
@@ -33,21 +41,22 @@ jobs:
run: |
git config --global core.autocrlf input
git config --global --add safe.directory /cygdrive/d/a/zi-src/zi-src
- - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: ๐ช Dependencies (Windows)
- uses: egor-tensin/setup-cygwin@d2c752bab416d4b0662591bd366fc2686297c82d # v4
+ uses: egor-tensin/setup-cygwin@d2c752bab416d4b0662591bd366fc2686297c82d # v4.0.1
with:
platform: x64
packages: curl git zsh
- name: ๐ช Run Install
run: |
+ sh ./tests/installers.sh
sh -x ./lib/sh/install.sh -- -i skip
- command rm -rf /home/runneradmin/.zi
+ command rm -rf "${XDG_DATA_HOME:-$HOME/.local/share}/zi" /home/runneradmin/.zi
sh -x ./lib/sh/install.sh -- -a annex
- command rm -rf /home/runneradmin/.zi
+ command rm -rf "${XDG_DATA_HOME:-$HOME/.local/share}/zi" /home/runneradmin/.zi
sh -x ./lib/sh/install.sh -- -a loader
- command rm -rf /home/runneradmin/.zi
+ command rm -rf "${XDG_DATA_HOME:-$HOME/.local/share}/zi" /home/runneradmin/.zi
sh -x ./lib/sh/install.sh -- -a zunit
- command rm -rf /home/runneradmin/.zi
+ command rm -rf "${XDG_DATA_HOME:-$HOME/.local/share}/zi" /home/runneradmin/.zi
sh -x ./lib/sh/install.sh -- -a zpmod
shell: C:\tools\cygwin\bin\bash.exe --login -o igncr '{0}'
diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml
index edc1935..6bb320d 100644
--- a/.trunk/trunk.yaml
+++ b/.trunk/trunk.yaml
@@ -1,10 +1,10 @@
version: 0.1
cli:
- version: 1.22.11
+ version: 1.25.0
plugins:
sources:
- id: trunk
- ref: v1.6.7
+ ref: v1.10.0
uri: https://github.com/trunk-io/plugins
repo:
repo:
@@ -12,6 +12,17 @@ repo:
owner: z-shell
name: zi-src
lint:
+ definitions:
+ - name: shfmt
+ commands:
+ - name: format
+ output: shfmt
+ run: shfmt -w -s -ln=bash -i 2 ${target}
+ success_codes: [0, 1]
+ cache_results: true
+ formatter: true
+ batch: true
+ in_place: true
disabled:
- yamllint
- trufflehog
@@ -20,13 +31,13 @@ lint:
- trivy
enabled:
- git-diff-check@SYSTEM
- - actionlint@1.7.7
- - gitleaks@8.24.0
- - markdownlint@0.44.0
- - prettier@3.5.3
- - shellcheck@0.10.0
+ - actionlint@1.7.12
+ - gitleaks@8.30.1
+ - markdownlint@0.48.0
+ - prettier@3.8.3
+ - shellcheck@0.11.0
- shfmt@3.6.0
- - taplo@0.9.3
+ - taplo@0.10.0
actions:
enabled:
- trunk-announce
@@ -36,6 +47,6 @@ actions:
- trunk-cache-prune
runtimes:
enabled:
- - python@3.10.8
+ - python@3.14.4
- go@1.21.0
- - node@18.20.5
+ - node@22.16.0
From a810dc8ff74c0543f4f3c8b097bec2a476f74306 Mon Sep 17 00:00:00 2001
From: Salvydas Lukosius
Date: Fri, 15 May 2026 23:59:26 +0100
Subject: [PATCH 3/7] feat: add sync-init.sh and tests/installers.sh
sync-init.sh verifies (and optionally replaces) the local lib/zsh/init.zsh
against the canonical GitHub raw main copy. Supports --write, --local,
--remote, --checksum-url and --no-checksum flags.
tests/installers.sh provides a POSIX sh test suite covering:
- script syntax validation (sh -n / zsh -n)
- checksum integrity checks
- loader install with XDG path and branch-override assertions
- standalone zpmod delegation test
- sync-init fixture round-trip test
---
lib/sh/sync-init.sh | 252 ++++++++++++++++++++++++++++++++++++++++++++
tests/installers.sh | 251 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 503 insertions(+)
create mode 100755 lib/sh/sync-init.sh
create mode 100755 tests/installers.sh
diff --git a/lib/sh/sync-init.sh b/lib/sh/sync-init.sh
new file mode 100755
index 0000000..5cc30ac
--- /dev/null
+++ b/lib/sh/sync-init.sh
@@ -0,0 +1,252 @@
+#!/usr/bin/env sh
+# -*- mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
+# vim: ft=sh sw=2 ts=2 et
+#
+# sync-init.sh โ verify and optionally sync local lib/zsh/init.zsh with remote.
+#
+# Usage:
+# sh lib/sh/sync-init.sh [OPTIONS]
+#
+# Options:
+# --write Replace local file with remote copy (requires valid checksum)
+# --local PATH Local file to compare (default: lib/zsh/init.zsh)
+# --remote URL|PATH Remote URL or local path (default: GitHub raw main)
+# --checksum-url URL|PATH Checksum.txt URL or path (default: GitHub raw main)
+# --no-checksum Skip checksum validation of remote content
+# --help Print this help and exit
+#
+# Exit codes:
+# 0 Files match (or --write sync succeeded)
+# 1 Files differ, fetch error, or checksum mismatch
+# 2 Usage error
+
+set -eu
+
+WORKDIR="$(mktemp -d)" || exit 1
+trap 'rm -rf "${WORKDIR:?}"' EXIT INT TERM
+
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
+
+DEFAULT_LOCAL="${REPO_ROOT}/lib/zsh/init.zsh"
+DEFAULT_REMOTE="https://raw.githubusercontent.com/z-shell/zi-src/main/lib/zsh/init.zsh"
+DEFAULT_CHECKSUM_URL="https://raw.githubusercontent.com/z-shell/zi-src/main/lib/checksum.txt"
+CHECKSUM_KEY="lib/zsh/init.zsh"
+
+OPT_LOCAL="${DEFAULT_LOCAL}"
+OPT_REMOTE="${DEFAULT_REMOTE}"
+OPT_CHECKSUM_URL="${DEFAULT_CHECKSUM_URL}"
+OPT_WRITE=0
+OPT_NO_CHECKSUM=0
+
+# โโ Helpers โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+
+print_help() {
+ cat </dev/null 2>&1; then
+ command curl -fsSL "${_src}"
+ elif command -v wget >/dev/null 2>&1; then
+ command wget -qO- "${_src}"
+ else
+ printf '%s\n' "[1;31mโโโ[0m No curl or wget available." >&2
+ return 1
+ fi
+ ;;
+ *)
+ if [ -r "${_src}" ]; then
+ command cat "${_src}"
+ else
+ printf '%s\n' "[1;31mโโโ[0m Cannot read local path: ${_src}" >&2
+ return 1
+ fi
+ ;;
+ esac
+}
+
+# Compute SHA-256 hex digest of a file.
+_sha256() {
+ _file="$1"
+ if command -v sha256sum >/dev/null 2>&1; then
+ sha256sum "${_file}" | command awk '{print $1}'
+ elif command -v shasum >/dev/null 2>&1; then
+ shasum -a 256 "${_file}" | command awk '{print $1}'
+ else
+ printf '%s\n' "[1;31mโโโ[0m No sha256sum or shasum available." >&2
+ return 1
+ fi
+}
+
+# โโ Argument Parsing โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+
+while [ "$#" -gt 0 ]; do
+ case "$1" in
+ --write)
+ OPT_WRITE=1
+ shift
+ ;;
+ --local)
+ [ "$#" -ge 2 ] || {
+ printf '%s\n' "Error: --local requires an argument." >&2
+ exit 2
+ }
+ OPT_LOCAL="$2"
+ shift 2
+ ;;
+ --remote)
+ [ "$#" -ge 2 ] || {
+ printf '%s\n' "Error: --remote requires an argument." >&2
+ exit 2
+ }
+ OPT_REMOTE="$2"
+ shift 2
+ ;;
+ --checksum-url)
+ [ "$#" -ge 2 ] || {
+ printf '%s\n' "Error: --checksum-url requires an argument." >&2
+ exit 2
+ }
+ OPT_CHECKSUM_URL="$2"
+ shift 2
+ ;;
+ --no-checksum)
+ OPT_NO_CHECKSUM=1
+ shift
+ ;;
+ --help | -h)
+ print_help
+ exit 0
+ ;;
+ *)
+ printf '%s\n' "Error: unknown option: $1" >&2
+ exit 2
+ ;;
+ esac
+done
+
+# โโ Validate Inputs โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+
+if [ ! -f "${OPT_LOCAL}" ] && [ "${OPT_WRITE}" -eq 0 ]; then
+ printf '%s\n' "[1;31mโโโ[0m Local file not found: ${OPT_LOCAL}" >&2
+ printf '%s\n' "[1;33mโโโ[0m Use --write to create it from remote." >&2
+ exit 1
+fi
+
+# โโ Fetch Remote โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+
+REMOTE_FILE="${WORKDIR}/remote-init.zsh"
+printf '%s\n' "โโโ Fetching remote: ${OPT_REMOTE}"
+# shellcheck disable=SC2310
+if ! _fetch "${OPT_REMOTE}" >"${REMOTE_FILE}"; then
+ printf '%s\n' "[1;31mโโโ[0m Failed to fetch remote file." >&2
+ exit 1
+fi
+
+# โโ Verify Remote Against Checksum โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+
+if [ "${OPT_NO_CHECKSUM}" -eq 0 ]; then
+ CHECKSUM_FILE="${WORKDIR}/checksum.txt"
+ printf '%s\n' "โโโ Fetching checksum: ${OPT_CHECKSUM_URL}"
+ # shellcheck disable=SC2310
+ if ! _fetch "${OPT_CHECKSUM_URL}" >"${CHECKSUM_FILE}"; then
+ printf '%s\n' "[1;31mโโโ[0m Failed to fetch checksum file." >&2
+ exit 1
+ fi
+
+ EXPECTED_HASH="$(grep "${CHECKSUM_KEY}" "${CHECKSUM_FILE}" | command awk '{print $1}')"
+ if [ -z "${EXPECTED_HASH}" ]; then
+ printf '%s\n' "[1;31mโโโ[0m No checksum entry for '${CHECKSUM_KEY}' in checksum.txt." >&2
+ exit 1
+ fi
+
+ REMOTE_HASH="$(_sha256 "${REMOTE_FILE}")"
+ if [ "${REMOTE_HASH}" != "${EXPECTED_HASH}" ]; then
+ printf '%s\n' "[1;31mโโโ[0m Remote checksum mismatch!" >&2
+ printf '%s\n' " expected : ${EXPECTED_HASH}" >&2
+ printf '%s\n' " got : ${REMOTE_HASH}" >&2
+ exit 1
+ fi
+ printf '%s\n' "โโโ Remote checksum verified: ${REMOTE_HASH}"
+else
+ REMOTE_HASH="$(_sha256 "${REMOTE_FILE}")"
+ printf '%s\n' "โโโ Remote hash (checksum validation skipped): ${REMOTE_HASH}"
+fi
+
+# โโ Compare โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+
+if [ -f "${OPT_LOCAL}" ]; then
+ LOCAL_HASH="$(_sha256 "${OPT_LOCAL}")"
+else
+ LOCAL_HASH="(file not present)"
+fi
+
+if [ "${LOCAL_HASH}" = "${REMOTE_HASH}" ]; then
+ printf '%s\n' "[1;32mโโโ[0m Local file matches remote. No sync needed."
+ printf '%s\n' " hash : ${LOCAL_HASH}"
+ printf '%s\n' " path : ${OPT_LOCAL}"
+ exit 0
+fi
+
+printf '%s\n' "[1;33mโโโ[0m Local and remote differ."
+printf '%s\n' " local : ${LOCAL_HASH}"
+printf '%s\n' " remote : ${REMOTE_HASH}"
+printf '%s\n' " source : ${OPT_REMOTE}"
+
+if command -v diff >/dev/null 2>&1 && [ -f "${OPT_LOCAL}" ]; then
+ printf '\n%s\n' "--- diff (local vs remote) ---"
+ diff -u "${OPT_LOCAL}" "${REMOTE_FILE}" || true
+ printf '%s\n' "--- end diff ---"
+fi
+
+# โโ Sync โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+
+if [ "${OPT_WRITE}" -eq 0 ]; then
+ printf '\n%s\n' "โโโ Run with --write to replace the local file."
+ exit 1
+fi
+
+LOCAL_DIR="$(dirname "${OPT_LOCAL}")"
+TMP_TARGET="${LOCAL_DIR}/.sync-init.zsh.tmp.$$"
+
+command cp "${REMOTE_FILE}" "${TMP_TARGET}"
+
+if [ -f "${OPT_LOCAL}" ]; then
+ ORIG_MODE="$(command stat -c '%a' "${OPT_LOCAL}" 2>/dev/null ||
+ command stat -f '%A' "${OPT_LOCAL}" 2>/dev/null ||
+ printf '755')"
+ command chmod "${ORIG_MODE}" "${TMP_TARGET}"
+else
+ command chmod 755 "${TMP_TARGET}"
+fi
+
+command mv "${TMP_TARGET}" "${OPT_LOCAL}"
+
+NEW_HASH="$(_sha256 "${OPT_LOCAL}")"
+printf '%s\n' "[1;32mโโโ[0m Sync complete."
+printf '%s\n' " before : ${LOCAL_HASH}"
+printf '%s\n' " after : ${NEW_HASH}"
+printf '%s\n' " path : ${OPT_LOCAL}"
diff --git a/tests/installers.sh b/tests/installers.sh
new file mode 100755
index 0000000..5e58b13
--- /dev/null
+++ b/tests/installers.sh
@@ -0,0 +1,251 @@
+#!/usr/bin/env sh
+# -*- mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
+# vim: ft=sh sw=2 ts=2 et
+
+set -eu
+
+ROOT="$(
+ unset CDPATH
+ cd -- "$(dirname "$0")/.." && pwd
+)"
+TMP_ROOT="$(mktemp -d)" || exit 1
+trap 'rm -rf "${TMP_ROOT:?}"' EXIT INT TERM
+
+fail() {
+ printf '%s\n' "not ok - $*" >&2
+ exit 1
+}
+
+pass() {
+ printf '%s\n' "ok - $*"
+}
+
+contains() {
+ file="$1"
+ pattern="$2"
+ if ! grep -F "${pattern}" "${file}" >/dev/null 2>&1; then
+ printf '%s\n' "--- ${file} ---" >&2
+ if [ -f "${file}" ]; then
+ sed -n '1,120p' "${file}" >&2
+ else
+ printf '%s\n' "(missing)" >&2
+ fi
+ printf '%s\n' "--- end ${file} ---" >&2
+ fail "${file} does not contain: ${pattern}"
+ fi
+}
+
+sha256_file() {
+ file="$1"
+ if command -v sha256sum >/dev/null 2>&1; then
+ sha256sum "${file}" | awk '{print $1}'
+ elif command -v shasum >/dev/null 2>&1; then
+ shasum -a 256 "${file}" | awk '{print $1}'
+ else
+ fail "sha256sum or shasum is required"
+ fi
+}
+
+check_syntax() {
+ sh -n "${ROOT}/lib/sh/install.sh"
+ sh -n "${ROOT}/lib/sh/install_zpmod.sh"
+ sh -n "${ROOT}/lib/sh/sync-init.sh"
+ command -v zsh >/dev/null 2>&1 || fail "zsh is required for init.zsh syntax checks"
+ zsh -n "${ROOT}/lib/zsh/init.zsh"
+ pass "script syntax"
+}
+
+check_checksums() {
+ while read -r expected path; do
+ [ -n "${expected}" ] || continue
+ actual="$(sha256_file "${ROOT}/${path}")"
+ [ "${actual}" = "${expected}" ] || fail "checksum mismatch for ${path}"
+ done <"${ROOT}/lib/checksum.txt"
+ pass "checksums"
+}
+
+write_fake_tools() {
+ FAKE_BIN="${TMP_ROOT}/bin"
+ command mkdir -p "${FAKE_BIN}"
+
+ cat >"${FAKE_BIN}/curl" <<'EOF'
+#!/usr/bin/env sh
+set -eu
+
+out=""
+remote_name=0
+url=""
+
+while [ "$#" -gt 0 ]; do
+ case "$1" in
+ -o)
+ shift
+ out="${1:-}"
+ [ -n "${out}" ] || exit 64
+ shift
+ ;;
+ -*O*)
+ remote_name=1
+ shift
+ ;;
+ -*)
+ shift
+ ;;
+ *)
+ url="$1"
+ shift
+ ;;
+ esac
+done
+
+[ -n "${url}" ] || { printf '%s\n' "curl test double: missing URL" >&2; exit 64; }
+if [ -z "${out}" ] && [ "${remote_name}" -eq 1 ]; then
+ out="${url##*/}"
+fi
+
+case "${url}" in
+ */lib/zsh/init.zsh)
+ if [ -n "${out}" ]; then
+ cp "${ZI_SRC_TEST_ROOT}/lib/zsh/init.zsh" "${out}"
+ else
+ cat "${ZI_SRC_TEST_ROOT}/lib/zsh/init.zsh"
+ fi
+ ;;
+ */git-process-output.zsh)
+ [ -n "${out}" ] || out="git-process-output.zsh"
+ cat > "${out}" <<'SCRIPT'
+#!/usr/bin/env sh
+cat
+SCRIPT
+ chmod a+x "${out}"
+ ;;
+ */lib/sh/install_zpmod.sh)
+ [ -n "${out}" ] || { printf '%s\n' "curl test double: missing output path" >&2; exit 64; }
+ cat > "${out}" <<'SCRIPT'
+#!/usr/bin/env sh
+set -eu
+printf '%s\n' "zpmod fallback executed" > "${ZI_SRC_TEST_MARKER:?}"
+SCRIPT
+ chmod a+x "${out}"
+ ;;
+ *)
+ printf '%s\n' "curl test double: unexpected URL ${url}" >&2
+ exit 65
+ ;;
+esac
+EOF
+
+ cat >"${FAKE_BIN}/git" <<'EOF'
+#!/usr/bin/env sh
+set -eu
+
+cmd="${1:-}"
+[ "$#" -gt 0 ] && shift
+
+case "${cmd}" in
+ clone)
+ dest=""
+ for arg do
+ dest="${arg}"
+ done
+ [ -n "${dest}" ] || { printf '%s\n' "git test double: missing clone destination" >&2; exit 64; }
+ mkdir -p "${dest}/.git" "${dest}/lib"
+ printf '%s\n' '# fake zi.zsh' > "${dest}/zi.zsh"
+ printf '%s\n' '# fake _zi completion' > "${dest}/lib/_zi"
+ ;;
+ clean | reset | pull)
+ ;;
+ log)
+ printf '%s\n' 'abcdef0 - fake zi commit (now) '
+ ;;
+ *)
+ printf '%s\n' "git test double: unexpected command ${cmd}" >&2
+ exit 65
+ ;;
+esac
+EOF
+
+ command chmod a+x "${FAKE_BIN}/curl" "${FAKE_BIN}/git"
+}
+
+test_loader_install() {
+ home="${TMP_ROOT}/loader-home"
+ config="${TMP_ROOT}/loader-config"
+ data="${TMP_ROOT}/loader-data"
+ command mkdir -p "${home}" "${config}" "${data}"
+
+ HOME="${home}" \
+ ZDOTDIR="${home}" \
+ XDG_CONFIG_HOME="${config}" \
+ XDG_DATA_HOME="${data}" \
+ ZI_SRC_TEST_ROOT="${ROOT}" \
+ PATH="${FAKE_BIN}:${PATH}" \
+ sh "${ROOT}/lib/sh/install.sh" -a loader -b feature/test >/dev/null
+
+ # shellcheck disable=SC2016
+ contains "${config}/zi/init.zsh" ': ${ZI[STREAM]:="feature/test"}'
+ # shellcheck disable=SC2016
+ contains "${home}/.zshrc" 'source "${XDG_CONFIG_HOME:-${HOME}/.config}/zi/init.zsh" && zzinit'
+ [ -f "${data}/zi/bin/zi.zsh" ] || fail "loader install did not clone Zi into XDG data home"
+ pass "loader install uses XDG paths and branch override"
+}
+
+test_standalone_zpmod_delegation() {
+ standalone_dir="${TMP_ROOT}/standalone"
+ home="${TMP_ROOT}/zpmod-home"
+ data="${TMP_ROOT}/zpmod-data"
+ marker="${TMP_ROOT}/zpmod-marker"
+ command mkdir -p "${standalone_dir}" "${home}" "${data}"
+ command cp "${ROOT}/lib/sh/install.sh" "${standalone_dir}/install.sh"
+
+ HOME="${home}" \
+ ZDOTDIR="${home}" \
+ XDG_DATA_HOME="${data}" \
+ ZI_SRC_TEST_ROOT="${ROOT}" \
+ ZI_SRC_TEST_MARKER="${marker}" \
+ PATH="${FAKE_BIN}:${PATH}" \
+ sh "${standalone_dir}/install.sh" -a zpmod -i skip >/dev/null
+
+ contains "${marker}" 'zpmod fallback executed'
+ pass "standalone install.sh fetches zpmod helper"
+}
+
+test_sync_init() {
+ local_file="${TMP_ROOT}/local-init.zsh"
+ remote_file="${TMP_ROOT}/remote-init.zsh"
+ checksum_file="${TMP_ROOT}/checksum.txt"
+
+ printf '%s\n' '# remote init fixture' >"${remote_file}"
+ command cp "${remote_file}" "${local_file}"
+ remote_hash="$(sha256_file "${remote_file}")"
+ printf '%s %s\n' "${remote_hash}" 'lib/zsh/init.zsh' >"${checksum_file}"
+
+ sh "${ROOT}/lib/sh/sync-init.sh" \
+ --local "${local_file}" \
+ --remote "${remote_file}" \
+ --checksum-url "${checksum_file}" >/dev/null
+
+ printf '%s\n' '# stale init fixture' >"${local_file}"
+ if sh "${ROOT}/lib/sh/sync-init.sh" \
+ --local "${local_file}" \
+ --remote "${remote_file}" \
+ --checksum-url "${checksum_file}" >/dev/null 2>&1; then
+ fail "sync-init mismatch check unexpectedly succeeded"
+ fi
+
+ sh "${ROOT}/lib/sh/sync-init.sh" \
+ --write \
+ --local "${local_file}" \
+ --remote "${remote_file}" \
+ --checksum-url "${checksum_file}" >/dev/null
+
+ cmp -s "${local_file}" "${remote_file}" || fail "sync-init --write did not replace local file"
+ pass "sync-init fixtures"
+}
+
+check_syntax
+check_checksums
+write_fake_tools
+test_loader_install
+test_standalone_zpmod_delegation
+test_sync_init
From bf6a68a0c7e06fadc0e7f259113ca28a3ac8c370 Mon Sep 17 00:00:00 2001
From: Salvydas Lukosius
Date: Fri, 15 May 2026 23:59:39 +0100
Subject: [PATCH 4/7] refactor: migrate installer scripts to XDG paths and
harden POSIX
install.sh:
- Add set -eu; use WORKDIR=$(mktemp -d) with safe trap cleanup
- Replace ~/.zi with XDG_DATA_HOME-aware path
- Fix sed command for ZI[STREAM] substitution
- Correct cd fallback from return to exit 1
- Guard branch pull with BOPT; add exit 1 on failed clone
- Fix .zshrc loader snippet variable quoting
install_zpmod.sh:
- Add set -eu, file header and WORKDIR trap
- Add pure-POSIX _zi_ver_ge() replacing expr string comparison
- Honour XDG_DATA_HOME for ZI_HOME default
- Replace exit 255 with exit 1 throughout
lib/zsh/init.zsh:
- Update default branch to use ZI[STREAM] parameter
- Align loader paths with XDG layout
---
lib/sh/install.sh | 140 +++++++++++--------------------
lib/sh/install_zpmod.sh | 68 +++++++++------
lib/zsh/init.zsh | 178 +++++++++++++++++++++++++---------------
3 files changed, 204 insertions(+), 182 deletions(-)
diff --git a/lib/sh/install.sh b/lib/sh/install.sh
index 0f7bbbc..57959c7 100755
--- a/lib/sh/install.sh
+++ b/lib/sh/install.sh
@@ -2,8 +2,10 @@
# -*- mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
# vim: ft=sh sw=2 ts=2 et
-trap 'rm -rf "$WORKDIR"' EXIT INT
-WORKDIR="$(mktemp -d)"
+set -eu
+
+WORKDIR="$(mktemp -d)" || exit 1
+trap 'rm -rf "${WORKDIR:?}"' EXIT INT TERM
ZOPT=""
AOPT=""
BOPT="main"
@@ -43,21 +45,21 @@ if [ "${AOPT}" = loader ]; then
command wget -qO "${ZI_CONFIG_DIR}/init.zsh" https://raw.githubusercontent.com/z-shell/zi-src/main/lib/zsh/init.zsh
fi
command chmod go-w "${ZI_CONFIG_DIR}" && command chmod a+x "${ZI_CONFIG_DIR}/init.zsh"
- command sed -i "s/branch=\"main\"/branch=\"${BOPT}\"/g" "${ZI_CONFIG_DIR}/init.zsh"
+ # shellcheck disable=SC2016
+ command sed -i 's|: ${ZI\[STREAM\]:="main"}|: ${ZI[STREAM]:="'"${BOPT}"'"}|' "${ZI_CONFIG_DIR}/init.zsh"
fi
-if [ -z "${ZI_HOME}" ]; then
- ZI_HOME="${ZDOTDIR:-${HOME}}/.zi"
+if [ -z "${ZI_HOME-}" ]; then
+ ZI_HOME="${XDG_DATA_HOME:-${HOME}/.local/share}/zi"
fi
-if [ -z "${ZI_BIN_DIR_NAME}" ]; then
+if [ -z "${ZI_BIN_DIR_NAME-}" ]; then
ZI_BIN_DIR_NAME="bin"
fi
if ! test -d "${ZI_HOME}"; then
command mkdir "${ZI_HOME}"
command chmod go-w "${ZI_HOME}"
- command chmod go-w "${ZI_HOME}/${ZI_BIN_DIR_NAME}"
fi
if ! command -v git >/dev/null 2>&1; then
@@ -68,31 +70,32 @@ fi
# Get the download-progress bar tool
if command -v curl >/dev/null 2>&1; then
command mkdir -p /tmp/zi
- cd /tmp/zi || return
+ cd /tmp/zi || exit 1
command curl -fsSLO https://raw.githubusercontent.com/z-shell/zi/main/lib/zsh/git-process-output.zsh &&
command chmod a+x /tmp/zi/git-process-output.zsh
elif command -v wget >/dev/null 2>&1; then
command mkdir -p /tmp/zi
- cd /tmp/zi || return
+ cd /tmp/zi || exit 1
command wget -q https://raw.githubusercontent.com/z-shell/zi/main/lib/zsh/git-process-output.zsh &&
command chmod a+x /tmp/zi/git-process-output.zsh
fi
if test -d "${ZI_HOME}/${ZI_BIN_DIR_NAME}/.git"; then
- cd "${ZI_HOME}/${ZI_BIN_DIR_NAME}" || return
+ cd "${ZI_HOME}/${ZI_BIN_DIR_NAME}" || exit 1
printf '%s\n' "[1;34mโโโ[0m Updating [1;36m(z-shell/zi)[1;33m plugin manager[0m at [1;35m${ZI_HOME}/${ZI_BIN_DIR_NAME}[0m"
command git clean -d -f -f
command git reset --hard HEAD
- command git pull -q origin HEAD
+ command git pull -q origin "${BOPT}"
else
- cd "${ZI_HOME}" || return
+ cd "${ZI_HOME}" || exit 1
printf '%s\n' "[1;34mโโโ[0m Installing [1;36m(z-shell/zi)[1;33m plugin manager[0m at [1;35m${ZI_HOME}/${ZI_BIN_DIR_NAME}[0m"
{ git clone --progress --depth=1 --branch "${BOPT}" https://github.com/z-shell/zi.git "${ZI_BIN_DIR_NAME}" \
2>&1 | { /tmp/zi/git-process-output.zsh || cat; }; } 2>/dev/null
- if [ -d "${ZI_BIN_DIR_NAME}" ]; then
+ if [ -d "${ZI_HOME}/${ZI_BIN_DIR_NAME}" ]; then
printf '%s\n' "[1;34mโโโ[0m Successfully installed at [1;32m${ZI_HOME}/${ZI_BIN_DIR_NAME}[0m".
else
printf '%s\n' "[1;31mโโโ[0m Something went wrong, couldn't install ZI at [1;33m${ZI_HOME}/${ZI_BIN_DIR_NAME}[0m"
+ exit 1
fi
fi
@@ -106,7 +109,7 @@ MAIN_PROFILE() {
printf '%s\n' "[34mโโโ[34m Seems that .zshrc already has content or setup skipped - no changes will be made."
ZOPT='skip'
fi
- if [ "${ZOPT}" != skip ]; then
+ if [ "${ZOPT}" != skip ] && [ "${AOPT}" != loader ]; then
printf '%s\n' "[34mโโโ[0m Updating ${THE_ZDOTDIR}/.zshrc"
ZI_HOME="$(echo "${ZI_HOME}" | sed "s|${HOME}|\$HOME|")"
command cat <<-EOF >>"${THE_ZDOTDIR}/.zshrc"
@@ -126,10 +129,9 @@ EOF
printf '%s\n' "[34mโโโ[0m[1;36m Minimal configuration[0m"
fi
if [ "${AOPT}" = loader ] && [ "${ZOPT}" != skip ]; then
- command rm -rf "${THE_ZDOTDIR}/.zshrc"
command cat <<-EOF >>"${THE_ZDOTDIR}/.zshrc"
-if [[ -r "${XDG_CONFIG_HOME:-${HOME}/.config}/zi/init.zsh" ]]; then
- source "${XDG_CONFIG_HOME:-${HOME}/.config}/zi/init.zsh" && zzinit
+if [[ -r "\${XDG_CONFIG_HOME:-\${HOME}/.config}/zi/init.zsh" ]]; then
+ source "\${XDG_CONFIG_HOME:-\${HOME}/.config}/zi/init.zsh" && zzinit
fi
EOF
printf '%s\n' "[34mโโโ[0m[1;36m Loader added[0m"
@@ -164,86 +166,38 @@ EOF
fi
}
-SETUP_ZPMOD() {
- if ! test -d "${ZI_HOME}/${MOD_HOME}"; then
- command mkdir -p "${ZI_HOME}/${MOD_HOME}"
- command chmod go-w "${ZI_HOME}/${MOD_HOME}"
- fi
+ZPMOD_PROFILE() {
+ _zpmod_sh=""
+ case "$0" in
+ */*)
+ _script_dir="$(cd "$(dirname "$0")" 2>/dev/null && pwd)" || _script_dir=""
+ ;;
+ *)
+ _script_dir=""
+ ;;
+ esac
- printf '%s\n' "${col_pname}== Downloading ZPMOD module to ${ZI_HOME}/${MOD_HOME}"
- if test -d "${ZI_HOME}/${MOD_HOME}/.git"; then
- cd "${ZI_HOME}/${MOD_HOME}" || return
- git pull -q origin main
+ if [ -n "${_script_dir}" ] && [ -f "${_script_dir}/install_zpmod.sh" ]; then
+ _zpmod_sh="${_script_dir}/install_zpmod.sh"
else
- cd "${ZI_HOME}" || return
- git clone -q https://github.com/z-shell/zpmod.git "${MOD_HOME}"
- fi
- printf '%s\n' "${col_pname}== Done"
-}
-
-BUILD_ZPMOD() {
- if command -v zsh >/dev/null; then
- printf '%s\n' "${col_info2}-- Checkig version --${col_rst}"
- ZSH_CURRENT=$(zsh --version /dev/null; then
- printf '%s\n' "${col_error}-- Zsh version 5.8.1 and above required --${col_rst}"
- exit 1
+ _zpmod_sh="${WORKDIR}/install_zpmod.sh"
+ _zpmod_url="https://raw.githubusercontent.com/z-shell/zi-src/main/lib/sh/install_zpmod.sh"
+ if command -v curl >/dev/null 2>&1; then
+ command curl -fsSL "${_zpmod_url}" -o "${_zpmod_sh}"
+ elif command -v wget >/dev/null 2>&1; then
+ command wget -qO "${_zpmod_sh}" "${_zpmod_url}"
else
- printf '%s\n' "${col_info2}-- Zsh version ${ZSH_CURRENT} --${col_rst}"
- cd "${ZI_HOME}/${MOD_HOME}" || return
- printf '%s\n' "${col_pname}== Building module ZPMOD, running: a make clean, then ./configure and then make ==${col_rst}"
- printf '%s\n' "${col_pname}== The module sources are located at: ${ZI_HOME}/${MOD_HOME} ==${col_rst}"
- if test -f Makefile; then
- if [ "$1" = "--clean" ]; then
- printf '%s\n' "${col_info2}-- make distclean --${col_rst}"
- make -s distclean
- true
- else
- printf '%s\n' "${col_info2}-- make clean (pass --clean to invoke \`make distclean') --${col_rst}"
- make -s clean
- fi
- fi
- printf '%s\n' "${col_info2}-- Configuring --${col_rst}"
- if CPPFLAGS=-I/usr/local/include CFLAGS="-g -Wall -O3" LDFLAGS=-L/usr/local/lib ./configure --disable-gdbm --without-tcsetpgrp; then
- printf '%s\n' "${col_info2}-- Running make --${col_rst}"
- if make -s; then
- command cat <<-EOF
-[38;5;219mโโโ[0m [38;5;220mModule [38;5;177mhas been built correctly.
-[38;5;219mโโโ[0m [38;5;220mTo [38;5;160mload the module, add following [38;5;220m2 lines to [38;5;172m.zshrc, at top:
-[0m [38;5;51m module_path+=( "${ZI_HOME}/${MOD_HOME}/Src" )
-[0m [38;5;51m zmodload zi/zpmod
-[38;5;219mโโโ[0m [38;5;220mSee 'zpmod -h' for more information.
-[38;5;219mโโโ[0m [38;5;220mRun 'zpmod source-study' to see profile data,
-[38;5;219mโโโ[0m [38;5;177mGuaranteed, automatic compilation of any sourced script.
-EOF
- else
- printf '%s\n' "${col_error}Module didn't build.${col_rst}. You can copy the error messages and submit"
- printf '%s\n' "error-report at: https://github.com/z-shell/zpmod/issues"
- fi
- fi
+ printf '%s\n' "-- ERROR -- curl or wget is required to download install_zpmod.sh" >&2
+ exit 1
fi
- else
- printf '%s\n' "${col_error} Zsh is not installed. Please install zsh and try again.${col_rst}"
+ if [ ! -s "${_zpmod_sh}" ]; then
+ printf '%s\n' "-- ERROR -- failed to download install_zpmod.sh" >&2
+ exit 1
+ fi
+ command chmod a+x "${_zpmod_sh}"
fi
-}
-ZPMOD_PROFILE() {
- col_pname="[33m"
- col_error="[31m"
- col_info="[32m"
- col_info2="[32m"
- col_rst="[0m"
-
- ZI_HOME="${ZI_HOME:-${ZDOTDIR:-${HOME}}/.zi}"
- MOD_HOME="${MOD_HOME:-zmodules}/zpmod"
-
- printf '%s\n' "${col_info}Re-run this script to update (from Github) and rebuild the module.${col_rst}"
- printf '%s\n' "${col_info2}Press any key to continue, or Ctrl-C to exit.${col_rst}"
- read -r
-
- SETUP_ZPMOD
- BUILD_ZPMOD "$@"
+ exec sh "${_zpmod_sh}" "$@"
}
CLOSE_PROFILE() {
@@ -273,6 +227,4 @@ EOF
exit 0
}
-while true; do
- MAIN "${@}"
-done
+MAIN "${@}"
diff --git a/lib/sh/install_zpmod.sh b/lib/sh/install_zpmod.sh
index d694f88..c49b99c 100755
--- a/lib/sh/install_zpmod.sh
+++ b/lib/sh/install_zpmod.sh
@@ -1,34 +1,56 @@
#!/usr/bin/env sh
+# -*- mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
+# vim: ft=sh sw=2 ts=2 et
+
+set -eu
+
+WORKDIR="$(mktemp -d)" || exit 1
+trap 'rm -rf "${WORKDIR:?}"' EXIT INT TERM
+
+# Returns 0 if version $1 >= version $2 (dot-separated integers)
+_zi_ver_ge() {
+ _vga="$1" _vgb="$2"
+ while [ -n "${_vga}${_vgb}" ]; do
+ _af="${_vga%%.*}" _bf="${_vgb%%.*}"
+ case "${_vga}" in *.*) _vga="${_vga#*.}" ;; *) _vga="" ;; esac
+ case "${_vgb}" in *.*) _vgb="${_vgb#*.}" ;; *) _vgb="" ;; esac
+ _af="${_af:-0}" _bf="${_bf:-0}"
+ if [ "${_af}" -gt "${_bf}" ]; then return 0; fi
+ if [ "${_af}" -lt "${_bf}" ]; then return 1; fi
+ done
+ return 0
+}
setup_environment() {
- if [ -z "${ZI_HOME}" ]; then
- if [ -d "${HOME}"/.zi ]; then
+ if [ -z "${ZI_HOME-}" ]; then
+ _xdg_zi="${XDG_DATA_HOME:-${HOME}/.local/share}/zi"
+ if [ -d "${_xdg_zi}" ]; then
+ ZI_HOME="${_xdg_zi}"
+ elif [ -d "${HOME}/.zi" ]; then
ZI_HOME="${HOME}/.zi"
- elif [ -d "${ZDOTDIR}"/.zi ]; then
+ elif [ -n "${ZDOTDIR-}" ] && [ -d "${ZDOTDIR}/.zi" ]; then
ZI_HOME="${ZDOTDIR}/.zi"
- elif [ -d "${XDG_DATA_HOME}"/.zi ]; then
- ZI_HOME="${XDG_DATA_HOME}/.zi"
else
- ZI_HOME="${HOME}/.zi"
+ ZI_HOME="${_xdg_zi}"
fi
fi
- if [ -z "${MOD_HOME}" ]; then
+ if [ -z "${MOD_HOME-}" ]; then
MOD_HOME="${ZI_HOME}/zmodules/zpmod"
fi
if ! test -d "${MOD_HOME}"; then
mkdir -p "${MOD_HOME}"
- chmod g-rwX "${MOD_HOME}"
+ chmod go-w "${MOD_HOME}"
fi
if [ ! -d "${MOD_HOME}" ]; then
printf '%s\n' "${col_error}== Error: Failed to setup module directory ==${col_rst}"
- exit 255
+ exit 1
fi
}
setup_zpmod_repository() {
printf '%s\n' "${col_pname}== Downloading ZPMOD module to ${MOD_HOME}"
if test -d "${MOD_HOME}/.git"; then
- cd "${MOD_HOME}" || exit 255
+ cd "${MOD_HOME}" || exit 1
git pull -q origin main
else
git clone --depth 10 -q https://github.com/z-shell/zpmod.git "${MOD_HOME}"
@@ -39,18 +61,19 @@ build_zpmod_module() {
if command -v zsh >/dev/null; then
printf '%s\n' "${col_info2}-- Checking version --${col_rst}"
ZSH_CURRENT=$(zsh --version /dev/null; then
- printf '%s\n' "${col_error}-- Zsh version 5.8.1 and above required --${col_rst}"
+ ZSH_REQUIRED="5.8.1"
+ # shellcheck disable=SC2310
+ if ! _zi_ver_ge "${ZSH_CURRENT}" "${ZSH_REQUIRED}"; then
+ printf '%s\n' "${col_error}-- Zsh version ${ZSH_REQUIRED} and above required --${col_rst}"
exit 1
else
(
printf '%s\n' "${col_info2}-- Zsh version ${ZSH_CURRENT} --${col_rst}"
- cd "${MOD_HOME}" || exit 255
+ cd "${MOD_HOME}" || exit 1
printf '%s\n' "${col_pname}== Building module ZPMOD, running: a make clean, then ./configure and then make ==${col_rst}"
printf '%s\n' "${col_pname}== The module sources are located at: ${MOD_HOME} ==${col_rst}"
if test -f Makefile; then
- if [ "$1" = "--clean" ]; then
+ if [ "${1-}" = "--clean" ]; then
printf '%s\n' "${col_info2}-- make distclean --${col_rst}"
make distclean
true
@@ -62,9 +85,10 @@ build_zpmod_module() {
INSTALL_PATH="/usr/local"
export PATH="${INSTALL_PATH}"/bin:"${PATH}"
- export LD_LIBRARY_PATH="${INSTALL_PATH}"/lib:"${LD_LIBRARY_PATH}"
- export CFLAGS=-I"${INSTALL_PATH}"/include
- export CPPFLAGS="-I${INSTALL_PATH}/include" LDFLAGS="-L${INSTALL_PATH}/lib"
+ export LD_LIBRARY_PATH="${INSTALL_PATH}/lib:${LD_LIBRARY_PATH-}"
+ export CFLAGS="-I${INSTALL_PATH}/include"
+ export CPPFLAGS="-I${INSTALL_PATH}/include"
+ export LDFLAGS="-L${INSTALL_PATH}/lib"
CFLAGS="-g -Wall -O3" ./configure --disable-gdbm --without-tcsetpgrp --quiet
printf '%s\n' "${col_info2}-- Running make --${col_rst}"
@@ -84,13 +108,13 @@ EOF
else
printf '%s\n' "${col_error}Module didn't build.${col_rst}. You can copy the error messages and submit"
printf '%s\n' "error-report at: https://github.com/z-shell/zpmod/issues"
- exit 255
+ exit 1
fi
)
fi
else
printf '%s\n' "${col_error} Zsh is not installed. Please install zsh and try again.${col_rst}"
- exit 255
+ exit 1
fi
}
@@ -106,6 +130,4 @@ MAIN() {
exit 0
}
-while true; do
- MAIN "${@}"
-done
+MAIN "${@}"
diff --git a/lib/zsh/init.zsh b/lib/zsh/init.zsh
index 49b86a6..01add00 100755
--- a/lib/zsh/init.zsh
+++ b/lib/zsh/init.zsh
@@ -1,88 +1,136 @@
#!/usr/bin/env zsh
-# ZI Loader (Values set: default)
+# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
+# vim: ft=zsh sw=2 ts=2 et
#
-# https://z.digitalclouds.dev/community/zsh_plugin_standard
-0="${ZERO:-${${0:#$ZSH_ARGZERO}:-${(%):-%N}}}"
-0="${${(M)0:#/*}:-$PWD/$0}"
-
-# https://z.digitalclouds.dev/docs/guides/customization
-local repo="https://github.com/z-shell/zi.git"
-local branch="main"
-local verbose_mode="${verbose_mode:-false}"
-typeset -A ZI
-# Where ZI should create all working directories, e.g.: "~/.zi"
-ZI[HOME_DIR]="${ZI[HOME_DIR]:-${HOME}/.zi}"
-# Where ZI code resides, e.g.: "~/.zi/bin"
-ZI[BIN_DIR]="$ZI[HOME_DIR]/bin"
-# Zsh modules directory
-ZI[ZMODULES_DIR]="$ZI[HOME_DIR]/zmodules"
-# Where ZI cache is, e.g.: "~/.cache/zi"
-ZI[CACHE_DIR]="${ZI[CACHE_DIR]:-$HOME/.cache/zi}"
-# Path to .zcompdump file, with the file included (i.e. its name can be different)
-ZI[ZCOMPDUMP_PATH]="$ZI[CACHE_DIR]/.zcompdump"
-# If set to 1, then mutes some of the ZI warnings, specifically the plugin already registered warning
-ZI[MUTE_WARNINGS]="${ZI[MUTE_WARNINGS]:-0}"
-
-# Clone ZI repository if it doesn't exist
-zzsetup() {
- [[ $verbose_mode == true ]] && builtin print "(ZI): Checking if ZI (zi.zsh) is available."
+# Zi Loader โ bootstrap and source the Zi plugin manager.
+#
+# Sourced early in .zshrc. Defines zzinit() which clones Zi on first run,
+# sources zi.zsh, registers completions, and loads zpmod if built.
+# All helper functions are cleaned up after zzinit() returns.
+
+# โโ Zi Configuration โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+
+typeset -ghA ZI
+
+# https://wiki.zshell.dev/docs/guides/customization
+: ${ZI[REPOSITORY]:="https://github.com/z-shell/zi.git"}
+: ${ZI[STREAM]:="main"}
+: ${ZI[HOME_DIR]:="${XDG_DATA_HOME:-$HOME/.local/share}/zi"}
+: ${ZI[BIN_DIR]:="${ZI[HOME_DIR]}/bin"}
+: ${ZI[CACHE_DIR]:="${XDG_CACHE_HOME:-$HOME/.cache}/zi"}
+: ${ZI[CONFIG_DIR]:="${XDG_CONFIG_HOME:-$HOME/.config}/zi"}
+
+# https://wiki.zshell.dev/community/zsh_plugin_standard#global-parameter-with-prefix
+: ${ZPFX:=${ZI[HOME_DIR]}/polaris}
+: ${ZI[ZMODULES_DIR]:=${ZI[HOME_DIR]}/zmodules}
+: ${ZI[ZCOMPDUMP_PATH]:=${ZI[CACHE_DIR]}/.zcompdump}
+: ${ZI[MUTE_WARNINGS]:=0}
+
+# History defaults
+: ${HISTFILE:=${XDG_STATE_HOME:-$HOME/.local/state}/zsh/history}
+[[ -e "$HISTFILE" ]] || { command mkdir -p "${HISTFILE:h}"; command touch "$HISTFILE"; }
+[[ -w "$HISTFILE" ]] && typeset -gx SAVEHIST=440000 HISTSIZE=441000
+
+# โโ Bootstrap Helpers โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+
+# Fetch content from a URL to stdout.
+_zi_fetch() {
+ builtin emulate -L zsh
+ if (( $+commands[curl] )); then
+ command curl -fsSL "$1"
+ elif (( $+commands[wget] )); then
+ command wget -qO- "$1"
+ else
+ return 255
+ fi
+}
+
+# Clone Zi repository if it doesn't exist.
+_zi_setup() {
+ builtin emulate -L zsh
+ builtin autoload colors; colors
+ local -a git_refs
+ local tmp_dir show_process process_url
+
if [[ ! -f "${ZI[BIN_DIR]}/zi.zsh" ]]; then
- [[ $verbose_mode == true ]] && builtin print "(ZI): ZI (zi.zsh) is not found. Installing..."
- builtin print -P "%F{33}โโโ %F{160}Installing interactive feature-rich plugin manager (%F{33}z-shell/zi%F{160})%f%b"
- command mkdir -p "${ZI[BIN_DIR]}" && command chmod -R go-w "${ZI[HOME_DIR]}"
- command git clone -q --progress --branch "$branch" "$repo" "${ZI[BIN_DIR]}"
+ tmp_dir="${TMPDIR:-/tmp}/zi"
+ [[ -d "$tmp_dir" ]] || command mkdir -p "$tmp_dir"
+
+ show_process="${tmp_dir}/git-process.zsh"
+ process_url="https://raw.githubusercontent.com/z-shell/zi/main/lib/zsh/git-process-output.zsh"
+
+ if [[ ! -f "$show_process" ]]; then
+ if _zi_fetch "$process_url" > "${tmp_dir}/git-process.zsh"; then
+ command chmod a+x "${tmp_dir}/git-process.zsh"
+ else
+ return 1
+ fi
+ fi
+
+ (( $+commands[clear] )) && command clear
+ builtin print -P "%F{33}โโโ %F{160}Installing interactive & feature-rich plugin manager (%F{33}z-shell/zi%F{160})%f%bโฆ\n"
+ command mkdir -p "${ZI[BIN_DIR]}" && \
+ command git clone --verbose --progress --branch \
+ "${ZI[STREAM]}" "${ZI[REPOSITORY]}" "${ZI[BIN_DIR]}" \
+ |& { command "$show_process" || command cat; }
+
if [[ -f "${ZI[BIN_DIR]}/zi.zsh" ]]; then
- [[ $verbose_mode == true ]] && builtin print "(ZI): Installed and ZI (zi.zsh) is found"
- local git_refs=("$(cd "${ZI[BIN_DIR]}"; command git log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit | head -10)")
- print -P "%F{33}โโโ %F{34}Successfully installed %F{160}(%F{33}z-shell/zi%F{160})%f%b"
- print -P "%F{33}โโโ %F{226}Last changes:%f%b"
- print -P "%F{33}โโโ %F{160}%F{33}\n${git_refs}%F{160}%f%b"
+ command chmod -R go-w "${ZI[HOME_DIR]}"
+ git_refs=("${(f@)$(builtin cd -q "${ZI[BIN_DIR]}" && command git log --color --graph --abbrev-commit \
+ --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' | command head -5)}")
+ builtin print
+ builtin print -P "%F{33}โโโ %F{34}Successfully installed %F{160}(%F{33}z-shell/zi%F{160})%f%b\n"
+ builtin print -rl -- "${git_refs[@]}"
else
- print -P "%F{160}โโโ The clone has failedโฆ%f%b"
- print -P "%F{160}โโโ %F{33} Please report the issue:%f%b"
- print -P "%F{160}โโโ %F{33} https://github.com/z-shell/zi/issues/new%f%b"
+ builtin print -P "%F{160}โโโ The clone has failedโฆ%f%b"
+ builtin print -P "%F{160}โโโ %F{33} Please report the issue: %F{226}https://github.com/z-shell/zi/issues/new%f%b"
return 1
fi
- return 0
fi
+ return 0
}
-# If setup is successful or ZI is already installed, then load ZI. Otherwise, not continue and exit.
-zzsource() {
- [[ $verbose_mode == true ]] && builtin print "(ZI): If (zzsetup) function status code 0, then load ZI."
- if zzsetup; then
- [[ $verbose_mode == true ]] && builtin print "(ZI): Loading (zi.zsh)"
- source "${ZI[BIN_DIR]}/zi.zsh"
+# Source zi.zsh, bootstrapping first if needed.
+_zi_source() {
+ builtin emulate -L zsh
+ if [[ -f "${ZI[BIN_DIR]}/zi.zsh" ]]; then
+ builtin source "${ZI[BIN_DIR]}/zi.zsh"
else
- [[ $verbose_mode == true ]] && builtin print "(ZI): (zzsetup) function status code 1, not continue and exit."
- exit 1
+ _zi_setup || return 1
+ # Guard: if setup succeeded but zi.zsh is still missing, don't recurse
+ if [[ -f "${ZI[BIN_DIR]}/zi.zsh" ]]; then
+ builtin source "${ZI[BIN_DIR]}/zi.zsh"
+ else
+ return 1
+ fi
fi
}
-# Load zi module if built
-zzpmod() {
- [[ $verbose_mode == true ]] && builtin print "(ZI): Checking for ZI module."
+# Load zpmod module if built.
+_zi_pmod() {
+ builtin emulate -L zsh
if [[ -f "${ZI[ZMODULES_DIR]}/zpmod/Src/zi/zpmod.so" ]]; then
- [[ $verbose_mode == true ]] && builtin print "(ZI): Loading ZI module."
module_path+=( "${ZI[ZMODULES_DIR]}/zpmod/Src" )
- zmodload zi/zpmod &>/dev/null
- ZI[ZPMOD_ENABLED]=1
+ zmodload zi/zpmod 2>/dev/null
fi
+ return 0
}
-# Enable completion (completions should be loaded after zzsource)
-zzcomps() {
- [[ $verbose_mode == true ]] && builtin print "(ZI): Loading completionโฆ (_zi)"
- autoload -Uz _zi
- (( ${+_comps} )) && _comps[zi]=_zi
- ZI[COMPS_ENABLED]=1
+# Register Zi completion if the completion system is active.
+_zi_comps() {
+ builtin emulate -L zsh
+ if (( ${+_comps} )) && [[ -f "${ZI[BIN_DIR]}/lib/_zi" ]]; then
+ (( ${+_comps[zi]} )) || _comps[zi]="${ZI[BIN_DIR]}/lib/_zi"
+ fi
+ return 0
}
-# If ZI is installed, load ZI, enable completion and load zpmod.
+# โโ Entry Point โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+
zzinit() {
- (( ZI[SOURCED] )) && return
- [[ $verbose_mode == true ]] && builtin print "(ZI): Loading ZI (zi.zsh)"
- zzsource
- zzcomps
- zzpmod
+ {
+ _zi_source && _zi_comps && _zi_pmod
+ } always {
+ unset -f _zi_fetch _zi_setup _zi_source _zi_comps _zi_pmod zzinit 2>/dev/null
+ }
}
From e470ca3516f9180c8e3bdf0d85e6b4eea1e1e26d Mon Sep 17 00:00:00 2001
From: Salvydas Lukosius
Date: Fri, 15 May 2026 23:59:48 +0100
Subject: [PATCH 5/7] chore: update gitignore, checksums, and docs
- Exclude AI agent instruction files from git tracking
(AGENTS.md, CLAUDE.md, GEMINI.md, .github/copilot-instructions.md)
- Add .geminiignore
- Regenerate lib/checksum.txt to reflect updated scripts
- Document sync-init.sh usage in docs/README.md
- Remove deprecated git.io short URLs from README
---
.geminiignore | 0
docs/README.md | 31 +++++++++++++++++++++++++++++--
lib/checksum.txt | 7 ++++---
3 files changed, 33 insertions(+), 5 deletions(-)
create mode 100644 .geminiignore
diff --git a/.geminiignore b/.geminiignore
new file mode 100644
index 0000000..e69de29
diff --git a/docs/README.md b/docs/README.md
index cd6b128..c45d77d 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -31,13 +31,40 @@
- https://wiki.zshell.dev
- Loader:
- https://init.zshell.dev
- - https://git.io/zi-loader
- Installer:
- https://get.zshell.dev
- - https://git.io/get-zi
- R2:
- https://r2.zshell.dev
- IPFS:
- https://ipfs.zshell.dev
- jsDeliver:
- https://cdn.jsdelivr.net/gh/z-shell/zi-src@main/
+
+### Maintainer โ Verify and Sync Loader
+
+Check whether the local `lib/zsh/init.zsh` matches the canonical GitHub raw `main` copy:
+
+```sh
+sh lib/sh/sync-init.sh
+```
+
+Replace the local file if it drifts:
+
+```sh
+sh lib/sh/sync-init.sh --write
+```
+
+Run against local fixtures (no network required, useful in tests):
+
+```sh
+sh lib/sh/sync-init.sh \
+ --local /tmp/my-init.zsh \
+ --remote /tmp/remote-init.zsh \
+ --checksum-url /tmp/checksum.txt
+```
+
+Skip checksum validation:
+
+```sh
+sh lib/sh/sync-init.sh --no-checksum
+```
diff --git a/lib/checksum.txt b/lib/checksum.txt
index 7335fdd..de6d2fc 100644
--- a/lib/checksum.txt
+++ b/lib/checksum.txt
@@ -1,3 +1,4 @@
-13668e0d6edce92994b0434932873d8a8a2c2579a2cb53964de19212f02a2954 lib/sh/install_zpmod.sh
-6214cad3026f4150dfe1070592f6b24256cae5c60c596bdfebda07ffeaaf39fc lib/sh/install.sh
-23a563e80249a866c7cba3ac44eaedb1ca38f20c35690fb764a7cb75e95d38be lib/zsh/init.zsh
+5d8fdd881b84548f38c1d5ffc6d5f46a18919d8dd6c1398d69abe055dd76ef98 lib/sh/install_zpmod.sh
+9d643c40be25f71d93dd295dacc58944defe7218f961f3f3ecb4ee9c0a56d486 lib/sh/install.sh
+83d9f0dc013376b5aa03b7a11f3908058da176df3407ac6e2872857d7c9658fd lib/sh/sync-init.sh
+66dc5bb0575d44e4e1192e229204abe1ac47979a05ee3c3bb23afc2b9b493637 lib/zsh/init.zsh
From c7d9cc702db2801cc621d7ce9ed7facdfb5e7ca6 Mon Sep 17 00:00:00 2001
From: "digital-teams[bot]"
Date: Fri, 15 May 2026 23:01:09 +0000
Subject: [PATCH 6/7] Checksum e470ca3516f9180c8e3bdf0d85e6b4eea1e1e26d
---
lib/checksum.txt | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lib/checksum.txt b/lib/checksum.txt
index de6d2fc..b7048ff 100644
--- a/lib/checksum.txt
+++ b/lib/checksum.txt
@@ -1,4 +1,4 @@
-5d8fdd881b84548f38c1d5ffc6d5f46a18919d8dd6c1398d69abe055dd76ef98 lib/sh/install_zpmod.sh
-9d643c40be25f71d93dd295dacc58944defe7218f961f3f3ecb4ee9c0a56d486 lib/sh/install.sh
-83d9f0dc013376b5aa03b7a11f3908058da176df3407ac6e2872857d7c9658fd lib/sh/sync-init.sh
-66dc5bb0575d44e4e1192e229204abe1ac47979a05ee3c3bb23afc2b9b493637 lib/zsh/init.zsh
+5d8fdd881b84548f38c1d5ffc6d5f46a18919d8dd6c1398d69abe055dd76ef98 lib/sh/install_zpmod.sh
+9d643c40be25f71d93dd295dacc58944defe7218f961f3f3ecb4ee9c0a56d486 lib/sh/install.sh
+83d9f0dc013376b5aa03b7a11f3908058da176df3407ac6e2872857d7c9658fd lib/sh/sync-init.sh
+66dc5bb0575d44e4e1192e229204abe1ac47979a05ee3c3bb23afc2b9b493637 lib/zsh/init.zsh
From d2b1703e59516a1856f07a595e5a40430d324f8d Mon Sep 17 00:00:00 2001
From: Sall <59910950+ss-o@users.noreply.github.com>
Date: Sat, 16 May 2026 09:52:49 +0100
Subject: [PATCH 7/7] ci: add org project tracker scripts (#158)
* ci(check-linux): add init.zsh sync-drift detection step
* fix(install.sh): verify zi.zsh exists after clone, not just directory
* ci: add concurrency to checksum.yml; add smoke-test to win-install.yml
Co-Authored-By: Claude Sonnet 4.6
* feat: add color.zsh from molovo/color (MIT)
* feat: add revolver from molovo/revolver (MIT)
* chore: rename repo references from zi-src to src
Update all internal references to reflect the repository rename:
- .trunk/trunk.yaml repo name
- workflow repository guards (checksum, rclone-action, deploy-gh-pages)
- win-install safe.directory path
- docs/README.md VSCode and jsDelivr URLs
* ci: add org project tracker scripts (label sync + workflow rollout)
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Sall <59910950+ss-o@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Sall <59910950+ss-o@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Sall <59910950+ss-o@users.noreply.github.com>
* fix: address review feedback for revolver process check and installer URLs
Agent-Logs-Url: https://github.com/z-shell/src/sessions/3295a818-69b9-4b0d-99f8-bf27b90e3b7c
Co-authored-by: ss-o <59910950+ss-o@users.noreply.github.com>
* fix: validate revolver pid before liveness check
Agent-Logs-Url: https://github.com/z-shell/src/sessions/3295a818-69b9-4b0d-99f8-bf27b90e3b7c
Co-authored-by: ss-o <59910950+ss-o@users.noreply.github.com>
---------
Signed-off-by: Sall <59910950+ss-o@users.noreply.github.com>
---
.github/workflows/check-linux.yml | 5 +
.github/workflows/checksum.yml | 6 +-
.github/workflows/deploy-gh-pages.yml | 2 +-
.github/workflows/rclone-action.yml | 2 +-
.github/workflows/win-install.yml | 12 +-
.trunk/trunk.yaml | 2 +-
docs/README.md | 4 +-
lib/checksum.txt | 2 +-
lib/sh/install.sh | 8 +-
lib/zsh/snippets/color.zsh | 33 +++
lib/zsh/snippets/revolver | 324 ++++++++++++++++++++++++++
scripts/add-project-workflow.sh | 126 ++++++++++
scripts/repos.txt | 94 ++++++++
scripts/sync-labels.sh | 94 ++++++++
14 files changed, 702 insertions(+), 12 deletions(-)
create mode 100644 lib/zsh/snippets/color.zsh
create mode 100644 lib/zsh/snippets/revolver
create mode 100755 scripts/add-project-workflow.sh
create mode 100644 scripts/repos.txt
create mode 100755 scripts/sync-labels.sh
diff --git a/.github/workflows/check-linux.yml b/.github/workflows/check-linux.yml
index 705dfd7..f4c3382 100644
--- a/.github/workflows/check-linux.yml
+++ b/.github/workflows/check-linux.yml
@@ -65,3 +65,8 @@ jobs:
zmodload zi/zpmod
zpmod source-study -l
shell: zsh {0}
+ - name: "โ๏ธ Check: init.zsh sync drift"
+ run: >
+ sh lib/sh/sync-init.sh
+ --remote https://raw.githubusercontent.com/z-shell/src/main/lib/zsh/init.zsh
+ --checksum-url https://raw.githubusercontent.com/z-shell/src/main/lib/zsh/init.zsh.md5
diff --git a/.github/workflows/checksum.yml b/.github/workflows/checksum.yml
index 2a84471..29fdb4e 100644
--- a/.github/workflows/checksum.yml
+++ b/.github/workflows/checksum.yml
@@ -13,9 +13,13 @@ on:
permissions:
contents: write
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: false
+
jobs:
checksum:
- if: github.repository == 'z-shell/zi-src'
+ if: github.repository == 'z-shell/src'
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
diff --git a/.github/workflows/deploy-gh-pages.yml b/.github/workflows/deploy-gh-pages.yml
index 83b21fd..351dbeb 100644
--- a/.github/workflows/deploy-gh-pages.yml
+++ b/.github/workflows/deploy-gh-pages.yml
@@ -15,7 +15,7 @@ permissions:
jobs:
deploy:
- if: github.repository == 'z-shell/zi-src'
+ if: github.repository == 'z-shell/src'
environment:
name: github-pages
runs-on: ubuntu-latest
diff --git a/.github/workflows/rclone-action.yml b/.github/workflows/rclone-action.yml
index 719d600..5b0f0e0 100644
--- a/.github/workflows/rclone-action.yml
+++ b/.github/workflows/rclone-action.yml
@@ -17,7 +17,7 @@ concurrency:
jobs:
sync:
- if: github.repository == 'z-shell/zi-src'
+ if: github.repository == 'z-shell/src'
runs-on: ubuntu-latest
timeout-minutes: 15
env:
diff --git a/.github/workflows/win-install.yml b/.github/workflows/win-install.yml
index c1b5cc5..365e6bc 100644
--- a/.github/workflows/win-install.yml
+++ b/.github/workflows/win-install.yml
@@ -40,7 +40,7 @@ jobs:
- name: ๐ช Set CRLF (Windows)
run: |
git config --global core.autocrlf input
- git config --global --add safe.directory /cygdrive/d/a/zi-src/zi-src
+ git config --global --add safe.directory /cygdrive/d/a/src/src
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: ๐ช Dependencies (Windows)
uses: egor-tensin/setup-cygwin@d2c752bab416d4b0662591bd366fc2686297c82d # v4.0.1
@@ -60,3 +60,13 @@ jobs:
command rm -rf "${XDG_DATA_HOME:-$HOME/.local/share}/zi" /home/runneradmin/.zi
sh -x ./lib/sh/install.sh -- -a zpmod
shell: C:\tools\cygwin\bin\bash.exe --login -o igncr '{0}'
+ - name: ๐ช Smoke-test โ verify zi.zsh present
+ run: |
+ ZI_BIN="${XDG_DATA_HOME:-${HOME}/.local/share}/zi/bin"
+ if [ ! -f "${ZI_BIN}/zi.zsh" ]; then
+ printf '%s\n' "FAIL: zi.zsh not found at ${ZI_BIN}/zi.zsh"
+ exit 1
+ fi
+ printf '%s\n' "OK: zi.zsh found at ${ZI_BIN}/zi.zsh"
+ command rm -rf "${XDG_DATA_HOME:-${HOME}/.local/share}/zi" /home/runneradmin/.zi
+ shell: C:\tools\cygwin\bin\bash.exe --login -o igncr '{0}'
diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml
index 6bb320d..7cdfae6 100644
--- a/.trunk/trunk.yaml
+++ b/.trunk/trunk.yaml
@@ -10,7 +10,7 @@ repo:
repo:
host: github.com
owner: z-shell
- name: zi-src
+ name: src
lint:
definitions:
- name: shfmt
diff --git a/docs/README.md b/docs/README.md
index c45d77d..7b2fa8c 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -21,7 +21,7 @@
-
+
@@ -38,7 +38,7 @@
- IPFS:
- https://ipfs.zshell.dev
- jsDeliver:
- - https://cdn.jsdelivr.net/gh/z-shell/zi-src@main/
+ - https://cdn.jsdelivr.net/gh/z-shell/src@main/
### Maintainer โ Verify and Sync Loader
diff --git a/lib/checksum.txt b/lib/checksum.txt
index b7048ff..cb840e2 100644
--- a/lib/checksum.txt
+++ b/lib/checksum.txt
@@ -1,4 +1,4 @@
5d8fdd881b84548f38c1d5ffc6d5f46a18919d8dd6c1398d69abe055dd76ef98 lib/sh/install_zpmod.sh
-9d643c40be25f71d93dd295dacc58944defe7218f961f3f3ecb4ee9c0a56d486 lib/sh/install.sh
+b2363e18f5dff0d94b475150922a8646d55d1c0fa2ef47dbf5f513361d111f44 lib/sh/install.sh
83d9f0dc013376b5aa03b7a11f3908058da176df3407ac6e2872857d7c9658fd lib/sh/sync-init.sh
66dc5bb0575d44e4e1192e229204abe1ac47979a05ee3c3bb23afc2b9b493637 lib/zsh/init.zsh
diff --git a/lib/sh/install.sh b/lib/sh/install.sh
index 57959c7..74b94a1 100755
--- a/lib/sh/install.sh
+++ b/lib/sh/install.sh
@@ -40,9 +40,9 @@ if [ "${AOPT}" = loader ]; then
ZI_CONFIG_DIR="${XDG_CONFIG_HOME:-${HOME}/.config}/zi"
command mkdir -p "${ZI_CONFIG_DIR}"
if command -v curl >/dev/null 2>&1; then
- command curl -fsSL https://raw.githubusercontent.com/z-shell/zi-src/main/lib/zsh/init.zsh -o "${ZI_CONFIG_DIR}/init.zsh"
+ command curl -fsSL https://raw.githubusercontent.com/z-shell/src/main/lib/zsh/init.zsh -o "${ZI_CONFIG_DIR}/init.zsh"
elif command -v wget >/dev/null 2>&1; then
- command wget -qO "${ZI_CONFIG_DIR}/init.zsh" https://raw.githubusercontent.com/z-shell/zi-src/main/lib/zsh/init.zsh
+ command wget -qO "${ZI_CONFIG_DIR}/init.zsh" https://raw.githubusercontent.com/z-shell/src/main/lib/zsh/init.zsh
fi
command chmod go-w "${ZI_CONFIG_DIR}" && command chmod a+x "${ZI_CONFIG_DIR}/init.zsh"
# shellcheck disable=SC2016
@@ -91,7 +91,7 @@ else
printf '%s\n' "[1;34mโโโ[0m Installing [1;36m(z-shell/zi)[1;33m plugin manager[0m at [1;35m${ZI_HOME}/${ZI_BIN_DIR_NAME}[0m"
{ git clone --progress --depth=1 --branch "${BOPT}" https://github.com/z-shell/zi.git "${ZI_BIN_DIR_NAME}" \
2>&1 | { /tmp/zi/git-process-output.zsh || cat; }; } 2>/dev/null
- if [ -d "${ZI_HOME}/${ZI_BIN_DIR_NAME}" ]; then
+ if [ -d "${ZI_HOME}/${ZI_BIN_DIR_NAME}" ] && [ -f "${ZI_HOME}/${ZI_BIN_DIR_NAME}/zi.zsh" ]; then
printf '%s\n' "[1;34mโโโ[0m Successfully installed at [1;32m${ZI_HOME}/${ZI_BIN_DIR_NAME}[0m".
else
printf '%s\n' "[1;31mโโโ[0m Something went wrong, couldn't install ZI at [1;33m${ZI_HOME}/${ZI_BIN_DIR_NAME}[0m"
@@ -181,7 +181,7 @@ ZPMOD_PROFILE() {
_zpmod_sh="${_script_dir}/install_zpmod.sh"
else
_zpmod_sh="${WORKDIR}/install_zpmod.sh"
- _zpmod_url="https://raw.githubusercontent.com/z-shell/zi-src/main/lib/sh/install_zpmod.sh"
+ _zpmod_url="https://raw.githubusercontent.com/z-shell/src/main/lib/sh/install_zpmod.sh"
if command -v curl >/dev/null 2>&1; then
command curl -fsSL "${_zpmod_url}" -o "${_zpmod_sh}"
elif command -v wget >/dev/null 2>&1; then
diff --git a/lib/zsh/snippets/color.zsh b/lib/zsh/snippets/color.zsh
new file mode 100644
index 0000000..82ee3d7
--- /dev/null
+++ b/lib/zsh/snippets/color.zsh
@@ -0,0 +1,33 @@
+#!/usr/bin/env zsh
+# Source: https://github.com/molovo/color
+# License: MIT โ Copyright (c) 2015 Joe Letchford
+# Maintained by z-shell/src โ https://github.com/z-shell/src
+#
+
+function color() {
+ local color=$1 style=$2 b=0
+
+ shift
+
+ case $style in
+ bold|b) b=1; shift ;;
+ italic|i) b=2; shift ;;
+ underline|u) b=4; shift ;;
+ inverse|in) b=7; shift ;;
+ strikethrough|s) b=9; shift ;;
+ esac
+
+ case $color in
+ black|b) echo "\033[${b};30m${@}\033[0;m" ;;
+ red|r) echo "\033[${b};31m${@}\033[0;m" ;;
+ green|g) echo "\033[${b};32m${@}\033[0;m" ;;
+ yellow|y) echo "\033[${b};33m${@}\033[0;m" ;;
+ blue|bl) echo "\033[${b};34m${@}\033[0;m" ;;
+ magenta|m) echo "\033[${b};35m${@}\033[0;m" ;;
+ cyan|c) echo "\033[${b};36m${@}\033[0;m" ;;
+ white|w) echo "\033[${b};37m${@}\033[0;m" ;;
+ *) echo "\033[${b};38;5;$(( ${color} ))m${@}\033[0;m" ;;
+ esac
+}
+
+color "$@"
diff --git a/lib/zsh/snippets/revolver b/lib/zsh/snippets/revolver
new file mode 100644
index 0000000..9913839
--- /dev/null
+++ b/lib/zsh/snippets/revolver
@@ -0,0 +1,324 @@
+#!/usr/bin/env zsh
+# Source: https://github.com/molovo/revolver
+# License: MIT โ Copyright (c) 2016 Joe Letchford
+# Maintained by z-shell/src โ https://github.com/z-shell/src
+#
+
+local -A _revolver_spinners
+_revolver_spinners=(
+ 'dots' '0.08 โ โ โ น โ ธ โ ผ โ ด โ ฆ โ ง โ โ '
+ 'dots2' '0.08 โฃพ โฃฝ โฃป โขฟ โกฟ โฃ โฃฏ โฃท'
+ 'dots3' '0.08 โ โ โ โ โ โ ฆ โ ด โ ฒ โ ณ โ '
+ 'dots4' '0.08 โ โ โ โ โ โ ธ โ ฐ โ โ ฐ โ ธ โ โ โ โ '
+ 'dots5' '0.08 โ โ โ โ โ โ โ โ ฒ โ ด โ ฆ โ โ โ โ โ โ โ '
+ 'dots6' '0.08 โ โ โ โ โ โ โ โ โ ฒ โ ด โ ค โ โ โ ค โ ด โ ฒ โ โ โ โ โ โ โ โ '
+ 'dots7' '0.08 โ โ โ โ โ โ โ โ โ โ ฆ โ ค โ โ โ ค โ ฆ โ โ โ โ โ โ โ โ โ '
+ 'dots8' '0.08 โ โ โ โ โ โ โ โ โ โ ฒ โ ด โ ค โ โ โ ค โ โ โ ค โ ฆ โ โ โ โ โ โ โ โ โ โ '
+ 'dots9' '0.08 โขน โขบ โขผ โฃธ โฃ โกง โก โก'
+ 'dots10' '0.08 โข โข โข โก โก โก โก '
+ 'dots11' '0.1 โ โ โ โก โข โ โ โ '
+ 'dots12' '0.08 "โขโ " "โกโ " "โ โ " "โขโ " "โกโ " "โ
โ " "โขโ " "โกโ " "โ โ " "โขโ " "โกโ " "โ โ " "โขโ " "โกโ " "โ โ " "โ โ " "โ โ " "โ โ " "โ โ " "โ โ ฉ" "โ โข" "โ โก" "โขโ ฉ" "โกโข" "โ โก" "โขโ ฉ" "โกโข" "โ
โก" "โขโ จ" "โกโข" "โ โก" "โขโ " "โกโข" "โ โก" "โขโ " "โกโ " "โ โ " "โ โ " "โ โ " "โ โ " "โ โ " "โ โ ฉ" "โ โข" "โ โก" "โ โ ฉ" "โ โข" "โ โก" "โ โ ฉ" "โ โข" "โ โก" "โ โ จ" "โ โข" "โ โก" "โ โ " "โ โข" "โ โก"'
+ 'line' '0.13 - \\ | /'
+ 'line2' '0.1 โ - โ โ โ -'
+ 'pipe' '0.1 โค โ โด โ โ โ โฌ โ'
+ 'simpleDots' '0.4 ". " ".. " "..." " "'
+ 'simpleDotsScrolling' '0.2 ". " ".. " "..." " .." " ." " "'
+ 'star' '0.07 โถ โธ โน โบ โน โท'
+ 'star2' '0.08 + x *'
+ 'flip' "0.07 _ _ _ - \` \` ' ยด - _ _ _"
+ 'hamburger' '0.1 โฑ โฒ โด'
+ 'growVertical' '0.12 โ โ โ โ
โ โ โ โ
โ โ'
+ 'growHorizontal' '0.12 โ โ โ โ โ โ โ โ โ โ โ โ'
+ 'balloon' '0.14 " " "." "o" "O" "@" "*" " "'
+ 'balloon2' '0.12 . o O ยฐ O o .'
+ 'noise' '0.14 โ โ โ'
+ 'bounce' '0.1 โ โ โ โ '
+ 'boxBounce' '0.12 โ โ โ โ'
+ 'boxBounce2' '0.1 โ โ โ โ'
+ 'triangle' '0.05 โข โฃ โค โฅ'
+ 'arc' '0.1 โ โ โ โ โก โ'
+ 'circle' '0.12 โก โ โ '
+ 'squareCorners' '0.18 โฐ โณ โฒ โฑ'
+ 'circleQuarters' '0.12 โด โท โถ โต'
+ 'circleHalves' '0.05 โ โ โ โ'
+ 'squish' '0.1 โซ โช'
+ 'toggle' '0.25 โถ โท'
+ 'toggle2' '0.08 โซ โช'
+ 'toggle3' '0.12 โก โ '
+ 'toggle4' '0.1 โ โก โช โซ'
+ 'toggle5' '0.1 โฎ โฏ'
+ 'toggle6' '0.3 แ แ'
+ 'toggle7' '0.08 โฆพ โฆฟ'
+ 'toggle8' '0.1 โ โ'
+ 'toggle9' '0.1 โ โ'
+ 'toggle10' '0.1 ใ ใ ใ'
+ 'toggle11' '0.05 โง โง'
+ 'toggle12' '0.12 โ โ'
+ 'toggle13' '0.08 = * -'
+ 'arrow' '0.1 โ โ โ โ โ โ โ โ'
+ 'arrow2' '0.12 โนโนโนโนโน โธโนโนโนโน โนโธโนโนโน โนโนโธโนโน โนโนโนโธโน โนโนโนโนโธ'
+ 'bouncingBar' '0.08 "[ ]" "[ =]" "[ ==]" "[ ===]" "[====]" "[=== ]" "[== ]" "[= ]"'
+ 'bouncingBall' '0.08 "( โ )" "( โ )" "( โ )" "( โ )" "( โ)" "( โ )" "( โ )" "( โ )" "( โ )" "(โ )"'
+ 'pong' '0.08 "โโ โ" "โโ โ" "โ โ โ" "โ โ โ" "โ โก โ" "โ โ โ" "โ โ โ" "โ โ โ" "โ โ โ" "โ โ โ" "โ โก โ" "โ โ โ" "โ โ โ" "โ โ โ" "โ โ โ" "โ โ โ" "โ โกโ" "โ โ โ" "โ โ โ" "โ โ โ" "โ โ โ" "โ โ โ" "โ โก โ" "โ โ โ" "โ โ โ" "โ โ โ" "โ โ โ" "โ โ โ" "โ โก โ" "โโ โ"'
+ 'shark' '0.12 "โ|\\____________โ" "โ_|\\___________โ" "โ__|\\__________โ" "โ___|\\_________โ" "โ____|\\________โ" "โ_____|\\_______โ" "โ______|\\______โ" "โ_______|\\_____โ" "โ________|\\____โ" "โ_________|\\___โ" "โ__________|\\__โ" "โ___________|\\_โ" "โ____________|\\โ" "โ____________/|โ" "โ___________/|_โ" "โ__________/|__โ" "โ_________/|___โ" "โ________/|____โ" "โ_______/|_____โ" "โ______/|______โ" "โ_____/|_______โ" "โ____/|________โ" "โ___/|_________โ" "โ__/|__________โ" "โ_/|___________โ" "โ/|____________โ"'
+)
+
+###
+# Output usage information and exit
+###
+function _revolver_usage() {
+ echo "\033[0;33mUsage:\033[0;m"
+ echo " revolver [options] "
+ echo
+ echo "\033[0;33mOptions:\033[0;m"
+ echo " -h, --help Output help text and exit"
+ echo " -v, --version Output version information and exit"
+ echo " -s, --style Set the spinner style"
+ echo
+ echo "\033[0;33mCommands:\033[0;m"
+ echo " start Start the spinner"
+ echo " update Update the message"
+ echo " stop Stop the spinner"
+ echo " demo Display a demo of each style"
+}
+
+###
+# The main revolver process, which contains the loop
+###
+function _revolver_process() {
+ local dir statefile state msg pid="$1" spinner_index=0
+
+ if [[ -z $pid || $pid != <-> ]]; then
+ exit 1
+ fi
+
+ # Find the directory and load the statefile
+ dir=${REVOLVER_DIR:-"${ZDOTDIR:-$HOME}/.revolver"}
+ statefile="$dir/$pid"
+
+ # The frames that, when animated, will make up
+ # our spinning indicator
+ frames=(${(@z)_revolver_spinners[$style]})
+ interval=${(@z)frames[1]}
+ shift frames
+
+ # Create a never-ending loop
+ while [[ 1 -eq 1 ]]; do
+ # If the statefile has been removed, exit the script
+ # to prevent it from being orphaned
+ if [[ ! -f $statefile ]]; then
+ exit 1
+ fi
+
+ # Check for the existence of the parent process
+ # and exit if process doesn't exist to prevent
+ # the spinner from being orphaned
+ if ! kill -s 0 "$pid" 2>/dev/null; then
+ exit 1
+ fi
+
+ # Load the current state, and parse it to get
+ # the message to be displayed
+ state=($(cat $statefile))
+
+ msg="${(@)state:1}"
+
+ # Output the current spinner frame, and add a
+ # slight delay before the next one
+ _revolver_spin
+ sleep ${interval:-"0.1"}
+ done
+}
+
+###
+# Output the spinner itself, along with a message
+###
+function _revolver_spin() {
+ local dir statefile state pid frame
+
+ # ZSH arrays start at 1, so we need to bump the index if it's 0
+ if [[ $spinner_index -eq 0 ]]; then
+ spinner_index+=1
+ fi
+
+ # Calculate the screen width
+ lim=$(tput cols)
+
+ # Clear the line and move the cursor to the start
+ printf ' %.0s' {1..$lim}
+ echo -n "\r"
+
+ # Echo the current frame and message, and overwrite
+ # the rest of the line with white space
+ msg="\033[0;38;5;242m${msg}\033[0;m"
+ frame="${${(@z)frames}[$spinner_index]//\"}"
+ printf '%*.*b' ${#msg} $lim "$frame $msg$(printf '%0.1s' " "{1..$lim})"
+
+ # Return to the beginning of the line
+ echo -n "\r"
+
+ # Set the spinner index to the next frame
+ spinner_index=$(( $(( $spinner_index + 1 )) % $(( ${#frames} + 1 )) ))
+}
+
+###
+# Stop the current spinner process
+###
+function _revolver_stop() {
+ local dir statefile state pid
+
+ # Find the directory and load the statefile
+ dir=${REVOLVER_DIR:-"${ZDOTDIR:-$HOME}/.revolver"}
+ statefile="$dir/$PPID"
+
+ # If the statefile does not exist, raise an error.
+ # The spinner process itself performs the same check
+ # and kills itself, so it should never be orphaned
+ if [[ ! -f $statefile ]]; then
+ echo '\033[0;31mRevolver process could not be found\033[0;m'
+ exit 1
+ fi
+
+ # Get the current state, and parse it to find the PID
+ # of the spinner process
+ state=($(cat $statefile))
+ pid="$state[1]"
+
+ # Clear the line and move the cursor to the start
+ printf ' %.0s' {1..$(tput cols)}
+ echo -n "\r"
+
+ # If a PID has been found, kill the process
+ [[ ! -z $pid ]] && kill "$pid" > /dev/null
+ unset pid
+
+ # Remove the statefile
+ rm $statefile
+}
+
+###
+# Update the message being displayed
+function _revolver_update() {
+ local dir statefile state pid msg="$1"
+
+ # Find the directory and load the statefile
+ dir=${REVOLVER_DIR:-"${ZDOTDIR:-$HOME}/.revolver"}
+ statefile="$dir/$PPID"
+
+ # If the statefile does not exist, raise an error.
+ # The spinner process itself performs the same check
+ # and kills itself, so it should never be orphaned
+ if [[ ! -f $statefile ]]; then
+ echo '\033[0;31mRevolver process could not be found\033[0;m'
+ exit 1
+ fi
+
+ # Get the current state, and parse it to find the PID
+ # of the spinner process
+ state=($(cat $statefile))
+ pid="$state[1]"
+
+ # Clear the line and move the cursor to the start
+ printf ' %.0s' {1..$(tput cols)}
+ echo -n "\r"
+
+ # Echo the new message to the statefile, to be
+ # picked up by the spinner process
+ echo "$pid $msg" >! $statefile
+}
+
+###
+# Create a new spinner with the specified message
+###
+function _revolver_start() {
+ local dir statefile msg="$1"
+
+ # Find the directory and create it if it doesn't exist
+ dir=${REVOLVER_DIR:-"${ZDOTDIR:-$HOME}/.revolver"}
+ if [[ ! -d $dir ]]; then
+ mkdir -p $dir
+ fi
+
+ # Create the filename for the statefile
+ statefile="$dir/$PPID"
+
+ touch $statefile
+ if [[ ! -f $statefile ]]; then
+ echo '\033[0;31mRevolver process could not create state file\033[0;m'
+ echo "Check that the directory $dir is writable"
+ exit 1
+ fi
+
+ # Start the spinner process in the background
+ _revolver_process $PPID &!
+
+ # Save the current state to the statefile
+ echo "$! $msg" >! $statefile
+}
+
+###
+# Demonstrate each of the included spinner styles
+###
+function _revolver_demo() {
+ for style in "${(@k)_revolver_spinners[@]}"; do
+ revolver --style $style start $style
+ sleep 2
+ revolver stop
+ done
+}
+
+###
+# Handle command input
+###
+function _revolver() {
+ #ย Get the context from the first parameter
+ local help version style ctx="$1"
+
+ # Parse CLI options
+ zparseopts -D \
+ h=help -help=help \
+ v=version -version=version \
+ s:=style -style:=style
+
+ # Output usage information and exit
+ if [[ -n $help ]]; then
+ _revolver_usage
+ exit 0
+ fi
+
+ # Output version information and exit
+ if [[ -n $version ]]; then
+ echo '0.2.0'
+ exit 0
+ fi
+
+ if [[ -z $style ]]; then
+ style='dots'
+ fi
+
+ if [[ -n $style ]]; then
+ shift style
+ ctx="$1"
+ fi
+
+ if [[ -z $_revolver_spinners[$style] ]]; then
+ echo $(color red "Spinner '$style' is not recognised")
+ exit 1
+ fi
+
+ case $ctx in
+ start|update|stop|demo)
+ # Check if a valid command is passed,
+ # and if so, run it
+ _revolver_${ctx} "${(@)@:2}"
+ ;;
+ *)
+ # If the context is not recognised,
+ # throw an error and exit
+ echo "Command $ctx is not recognised"
+ exit 1
+ ;;
+ esac
+}
+
+_revolver "$@"
diff --git a/scripts/add-project-workflow.sh b/scripts/add-project-workflow.sh
new file mode 100755
index 0000000..3436536
--- /dev/null
+++ b/scripts/add-project-workflow.sh
@@ -0,0 +1,126 @@
+#!/usr/bin/env sh
+# add-project-workflow.sh โ Add project-tracker workflow to all org repos.
+#
+# Usage:
+# ./add-project-workflow.sh [owner] [repos-file]
+#
+# Defaults:
+# owner = z-shell
+# repos-file = scripts/repos.txt
+#
+# Requirements:
+# - gh CLI authenticated with repo scope
+# - SSH key configured for git push
+# - z-shell/.github already has add-to-project.yml deployed
+
+set -e
+
+OWNER="${1:-z-shell}"
+REPOS="${2:-$(dirname "$0")/repos.txt}"
+WORKFLOW_FILE=".github/workflows/project-tracker.yml"
+BRANCH="ci/add-project-tracker"
+
+if [ ! -f "$REPOS" ]; then
+ printf 'Error: repos file not found: %s\n' "$REPOS" >&2
+ exit 1
+fi
+
+# Skip repos that already have the workflow or are the .github meta-repo
+SKIP_REPOS=".github"
+
+WORKFLOW_CONTENT='# Add issues and PRs to the Z-Shell Tracker project automatically.
+name: Track in Z-Shell Tracker
+
+on:
+ issues:
+ types: [opened, reopened, transferred]
+ pull_request:
+ types: [opened, reopened]
+
+jobs:
+ track:
+ uses: z-shell/.github/.github/workflows/add-to-project.yml@main
+ secrets: inherit
+'
+
+total=0
+ok=0
+skipped=0
+failed=0
+
+add_workflow() {
+ repo="$1"
+ printf '=== %s/%s ===\n' "$OWNER" "$repo"
+
+ # Skip the .github meta-repo itself
+ for skip in $SKIP_REPOS; do
+ if [ "$repo" = "$skip" ]; then
+ printf 'Skipping meta-repo\n'
+ skipped=$((skipped + 1))
+ return 0
+ fi
+ done
+
+ tmpdir=$(mktemp -d)
+ trap 'rm -rf "$tmpdir"' EXIT INT TERM
+
+ # Clone (shallow) โ skip archived/empty repos gracefully
+ if ! git clone --depth=1 "git@github.com:$OWNER/$repo.git" "$tmpdir/$repo" 2>/dev/null; then
+ printf 'SKIP: cannot clone (archived or empty?)\n'
+ skipped=$((skipped + 1))
+ trap - EXIT INT TERM
+ rm -rf "$tmpdir"
+ return 0
+ fi
+
+ cd "$tmpdir/$repo"
+
+ # Skip if workflow already exists
+ if [ -f "$WORKFLOW_FILE" ]; then
+ printf 'SKIP: workflow already present\n'
+ skipped=$((skipped + 1))
+ cd - >/dev/null
+ trap - EXIT INT TERM
+ rm -rf "$tmpdir"
+ return 0
+ fi
+
+ # Get default branch
+ default_branch=$(git symbolic-ref --short HEAD 2>/dev/null || echo "main")
+
+ git checkout -b "$BRANCH" 2>/dev/null || git checkout "$BRANCH"
+ mkdir -p "$(dirname "$WORKFLOW_FILE")"
+ printf '%s' "$WORKFLOW_CONTENT" >"$WORKFLOW_FILE"
+
+ git add "$WORKFLOW_FILE"
+ git commit -m "ci: add project tracker workflow"
+ git push origin "$BRANCH"
+
+ # Open a PR
+ gh pr create \
+ --repo "$OWNER/$repo" \
+ --base "$default_branch" \
+ --head "$BRANCH" \
+ --title "ci: add project tracker workflow" \
+ --body 'Adds the `.github/workflows/project-tracker.yml` workflow so new issues and PRs are automatically added to the [Z-Shell Tracker](https://github.com/orgs/z-shell/projects/28) project.
+
+Uses the shared reusable workflow from `z-shell/.github` โ no per-repo secrets needed.' \
+ 2>/dev/null && printf 'PR opened\n' || printf 'PR already open or failed\n'
+
+ ok=$((ok + 1))
+ cd - >/dev/null
+ trap - EXIT INT TERM
+ rm -rf "$tmpdir"
+}
+
+while IFS= read -r repo || [ -n "$repo" ]; do
+ [ -z "$repo" ] && continue
+ total=$((total + 1))
+ add_workflow "$repo" || {
+ failed=$((failed + 1))
+ printf 'FAILED: %s/%s\n' "$OWNER" "$repo" >&2
+ }
+done <"$REPOS"
+
+printf '\nDone โ %d total, %d ok, %d skipped, %d failed\n' \
+ "$total" "$ok" "$skipped" "$failed"
diff --git a/scripts/repos.txt b/scripts/repos.txt
new file mode 100644
index 0000000..2aacb30
--- /dev/null
+++ b/scripts/repos.txt
@@ -0,0 +1,94 @@
+F-Sy-H
+z-a-bin-gem-node
+z-a-patch-dl
+z-a-readurl
+z-a-rust
+z-a-submods
+z-a-meta-plugins
+zsh-navigation-tools
+declare-zsh
+zsh-unique-id
+zsh-diff-so-fancy
+zflai
+null
+zconvey
+zui
+z-a-man
+zsh
+z-a-unscope
+z-a-default-ice
+zi-crasis
+zi-vim-syntax
+zsh-lint
+zsh-github-issues
+zzcomplete
+zbrowse
+firefox-dev
+any-node
+any-gem
+apr
+doctoc
+asciidoctor
+ecs-cli
+fzf
+fzy
+github-issues-srv
+github-issues
+ls_colors
+pyenv
+z-a-test
+z-a-linkbin
+z-a-eval
+dircolors-material
+zi-rbenv
+ztrace
+zsnapshot
+zsh-select
+zsh-morpho
+zsh-log-lines
+zservice-py3http
+zsh-editing-workbench
+pm-perf-test
+system-completions
+subversion
+remark
+community
+zsh-tig-plugin
+zsh-string-lib
+zsh-util-lib
+zsh-cmd-architect
+zredis-cmd
+zredis
+zprompts
+zi-console
+playground
+zgdbm
+redis
+VATS
+zi
+H-S-MW
+src
+zsh-bin
+docs
+zsdoc
+vramsteg-zsh
+zd
+status
+.github
+z-shell.github.io
+zpmod
+zsh-eza
+brew-completions
+0
+wiki
+zsh-zoxide
+zsh-fancy-completions
+web
+zsh-web-artwork
+merch
+nb
+.github-private
+z-a-linkman
+zsh-lsd
+.trunk
+zunit
diff --git a/scripts/sync-labels.sh b/scripts/sync-labels.sh
new file mode 100755
index 0000000..328ded5
--- /dev/null
+++ b/scripts/sync-labels.sh
@@ -0,0 +1,94 @@
+#!/usr/bin/env sh
+# sync-labels.sh โ Apply canonical Z-Shell label set to org repos.
+#
+# Usage:
+# ./sync-labels.sh [owner] [repos-file]
+#
+# Defaults:
+# owner = z-shell
+# repos-file = scripts/repos.txt (one repo name per line)
+#
+# Requirements:
+# - gh CLI authenticated with repo scope
+# - gh label create supports --force (gh >= 2.14)
+
+set -e
+
+OWNER="${1:-z-shell}"
+REPOS="${2:-$(dirname "$0")/repos.txt}"
+
+if [ ! -f "$REPOS" ]; then
+ printf 'Error: repos file not found: %s\n' "$REPOS" >&2
+ exit 1
+fi
+
+apply_labels() {
+ repo="$1"
+ printf '=== %s/%s ===\n' "$OWNER" "$repo"
+
+ # โโ Type labels โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+ gh label create "bug ๐" --repo "$OWNER/$repo" --color d73a4a \
+ --description "Something isn't working" --force
+ gh label create "feature-request ๐ก" --repo "$OWNER/$repo" --color 0075ca \
+ --description "New feature or request" --force
+ gh label create "enhancement โจ" --repo "$OWNER/$repo" --color a2eeef \
+ --description "Improvement to existing functionality" --force
+ gh label create "documentation ๐" --repo "$OWNER/$repo" --color 0052cc \
+ --description "Documentation-only changes" --force
+ gh label create "performance ๐" --repo "$OWNER/$repo" --color 006b75 \
+ --description "Performance improvements" --force
+ gh label create "security ๐ก๏ธ" --repo "$OWNER/$repo" --color ee0701 \
+ --description "Security vulnerability or hardening" --force
+ gh label create "breaking-change ๐ฅ" --repo "$OWNER/$repo" --color d93f0b \
+ --description "Breaks backward compatibility" --force
+ gh label create "dependencies ๐ฆ" --repo "$OWNER/$repo" --color 0366d6 \
+ --description "Dependency updates" --force
+ gh label create "chore ๐ง" --repo "$OWNER/$repo" --color c5def5 \
+ --description "Routine maintenance, no behavior change" --force
+ gh label create "refactor โป๏ธ" --repo "$OWNER/$repo" --color 5319e7 \
+ --description "Code refactor, no behavior change" --force
+ gh label create "ci โ๏ธ" --repo "$OWNER/$repo" --color 1d76db \
+ --description "CI/CD pipeline changes" --force
+
+ # โโ Status / workflow labels โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+ gh label create "triage ๐" --repo "$OWNER/$repo" --color fbca04 \
+ --description "Needs investigation before action" --force
+ gh label create "in-progress ๐ง" --repo "$OWNER/$repo" --color f9d0c4 \
+ --description "Currently being worked on" --force
+ gh label create "blocked โ" --repo "$OWNER/$repo" --color e4e669 \
+ --description "Blocked on external dependency/decision" --force
+ gh label create "stale ๐ค" --repo "$OWNER/$repo" --color f2f2f2 \
+ --description "No activity for an extended period" --force
+ gh label create "invalid โ ๏ธ" --repo "$OWNER/$repo" --color e4e669 \
+ --description "Off-topic, cannot reproduce, or incorrect" --force
+ gh label create "wontfix ๐ซ" --repo "$OWNER/$repo" --color ffffff \
+ --description "Will not be fixed" --force
+ gh label create "no-stale ๐" --repo "$OWNER/$repo" --color 0e8a16 \
+ --description "Exempt from stale-bot closing" --force
+
+ # โโ Community labels โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+ gh label create "help-wanted ๐" --repo "$OWNER/$repo" --color 008672 \
+ --description "Extra attention or expertise needed" --force
+ gh label create "good-first-issue ๐ฑ" --repo "$OWNER/$repo" --color 7057ff \
+ --description "Good for newcomers" --force
+ gh label create "Q&A โ๏ธ" --repo "$OWNER/$repo" --color d4c5f9 \
+ --description "Questions and answers" --force
+}
+
+# โโ Main loop โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+total=0
+ok=0
+failed=0
+
+while IFS= read -r repo || [ -n "$repo" ]; do
+ [ -z "$repo" ] && continue
+ total=$((total + 1))
+ if apply_labels "$repo"; then
+ ok=$((ok + 1))
+ else
+ failed=$((failed + 1))
+ printf 'FAILED: %s/%s\n' "$OWNER" "$repo" >&2
+ fi
+done <"$REPOS"
+
+printf '\nDone โ %d total, %d ok, %d failed\n' "$total" "$ok" "$failed"