feat: Dynamic package registry
This commit is contained in:
@@ -35,22 +35,16 @@ When adding a new installer named `<name>`:
|
||||
|
||||
Create `installers/install_<name>.sh` using the template below.
|
||||
|
||||
### Step 2: Register in `routes.sh`
|
||||
### Step 2: Add metadata comments to the top of your installer script
|
||||
|
||||
Make **two** edits to `routes.sh`:
|
||||
At the top of your new installer script, right below `#!/usr/bin/env bash`, add the following three metadata headers:
|
||||
```bash
|
||||
# Tool: <name>
|
||||
# DisplayName: <displayName>
|
||||
# Description: <description>
|
||||
```
|
||||
|
||||
1. **Add to the `INSTALLERS` associative array** (line ~19-26). Insert a new entry in alphabetical order:
|
||||
```bash
|
||||
[<name>]="Short description of what it installs"
|
||||
```
|
||||
|
||||
2. **Add to the `INSTALLER_KEYS` array** (line ~28). Insert the key in alphabetical order:
|
||||
```bash
|
||||
INSTALLER_KEYS=(agy bat <name> node nvim yazi zoxide)
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Both arrays must be kept in sync and in alphabetical order.
|
||||
The central router `routes.sh` and autocomplete function in `b.sh` will dynamically parse this metadata from all `install_*.sh` scripts to register the installer and keys automatically! No manual edits to `routes.sh` or `b.sh` are required.
|
||||
|
||||
### Step 3: Verify (optional)
|
||||
|
||||
@@ -67,6 +61,9 @@ Every installer follows this exact boilerplate structure. Copy this and fill in
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
# Tool: <name>
|
||||
# DisplayName: <ToolName>
|
||||
# Description: Short description of what it installs
|
||||
#
|
||||
# <ToolName> Installer Script
|
||||
#
|
||||
|
||||
43
b.sh
43
b.sh
@@ -77,16 +77,23 @@ _b_completion() {
|
||||
|
||||
# If completing the first argument after 'b'
|
||||
if [ "$COMP_CWORD" -eq 1 ]; then
|
||||
opts="all con bye up ware"
|
||||
opts="all con bye up ware bware"
|
||||
|
||||
local routes_file="$HOME/.config/bootstrap/routes.sh"
|
||||
if [ -f "$routes_file" ]; then
|
||||
# Extract installer keys dynamically from the routes.sh file
|
||||
local installer_keys
|
||||
installer_keys=$(grep -E "^INSTALLER_KEYS=" "$routes_file" 2>/dev/null | sed -E 's/INSTALLER_KEYS=\(([^)]+)\)/\1/' 2>/dev/null)
|
||||
if [ -n "$installer_keys" ]; then
|
||||
opts="$opts $installer_keys"
|
||||
fi
|
||||
local routes_dir="$HOME/.config/bootstrap"
|
||||
local installer_keys=""
|
||||
if [ -d "$routes_dir/installers" ]; then
|
||||
for f in "$routes_dir/installers"/install_*.sh; do
|
||||
if [ -f "$f" ]; then
|
||||
local tool
|
||||
tool=$(grep -E "^# Tool:" "$f" | head -n1 | sed -E 's/^# Tool:\s*//I')
|
||||
if [ -n "$tool" ]; then
|
||||
installer_keys="$installer_keys $tool"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [ -n "$installer_keys" ]; then
|
||||
opts="$opts $installer_keys"
|
||||
fi
|
||||
|
||||
# Support comma-separated completions (e.g. b nvim,ya<TAB>)
|
||||
@@ -111,12 +118,20 @@ _b_completion() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
# If completing arguments for 'b ware <tool>'
|
||||
if [ "$COMP_CWORD" -eq 2 ] && [ "$prev" = "ware" ]; then
|
||||
local routes_file="$HOME/.config/bootstrap/routes.sh"
|
||||
# If completing arguments for 'b ware <tool>' or 'b bware <tool>'
|
||||
if [ "$COMP_CWORD" -eq 2 ] && { [ "$prev" = "ware" ] || [ "$prev" = "bware" ]; }; then
|
||||
local routes_dir="$HOME/.config/bootstrap"
|
||||
local installer_keys=""
|
||||
if [ -f "$routes_file" ]; then
|
||||
installer_keys=$(grep -E "^INSTALLER_KEYS=" "$routes_file" 2>/dev/null | sed -E 's/INSTALLER_KEYS=\(([^)]+)\)/\1/' 2>/dev/null)
|
||||
if [ -d "$routes_dir/installers" ]; then
|
||||
for f in "$routes_dir/installers"/install_*.sh; do
|
||||
if [ -f "$f" ]; then
|
||||
local tool
|
||||
tool=$(grep -E "^# Tool:" "$f" | head -n1 | sed -E 's/^# Tool:\s*//I')
|
||||
if [ -n "$tool" ]; then
|
||||
installer_keys="$installer_keys $tool"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
[ -z "$installer_keys" ] && installer_keys="agy bat node nvim pnpm rust starship yay yazi zoxide"
|
||||
|
||||
|
||||
@@ -90,6 +90,7 @@ install_bootstrap() {
|
||||
"VERSION"
|
||||
"b.sh"
|
||||
"routes.sh"
|
||||
"registry.sh"
|
||||
"lib/common.sh"
|
||||
"lib/platform.sh"
|
||||
"lib/shell_config.sh"
|
||||
|
||||
@@ -9,7 +9,4 @@ printf " %-6s - %s\n" "up" "Check for updates and update Bootstrap CLI"
|
||||
printf " %-6s - %s\n" "ware" "Edit and run an installer (e.g. b ware nvim)"
|
||||
printf " %-6s - %s\n" "bye" "Uninstall Bootstrap CLI helper"
|
||||
|
||||
# Installers second
|
||||
for key in "${INSTALLER_KEYS[@]}"; do
|
||||
printf " %-6s - %s\n" "$key" "${INSTALLERS[$key]}"
|
||||
done
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tool: agy
|
||||
# DisplayName: Antigravity
|
||||
# Description: Install Antigravity CLI
|
||||
#
|
||||
# Antigravity CLI Installer Script (Linux Only)
|
||||
#
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tool: bat
|
||||
# DisplayName: Bat
|
||||
# Description: Install Bat (alternative to cat) and configure alias
|
||||
#
|
||||
# Bat Installer Script
|
||||
#
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tool: node
|
||||
# DisplayName: Node
|
||||
# Description: Install Node.js (LTS) and NVM
|
||||
#
|
||||
# Node.js and NVM Installer Script
|
||||
#
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tool: nvim
|
||||
# DisplayName: Neovim
|
||||
# Description: Install Neovim 0.11.7 and configuration
|
||||
#
|
||||
# Neovim Installer Script
|
||||
#
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tool: pnpm
|
||||
# DisplayName: Pnpm
|
||||
# Description: Install pnpm package manager
|
||||
#
|
||||
# pnpm Installer Script
|
||||
#
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tool: rust
|
||||
# DisplayName: Rust
|
||||
# Description: Install Rustup and Rust compiler/toolchain
|
||||
#
|
||||
# Rust Installer Script (Simplified Local Rustup Init)
|
||||
#
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tool: starship
|
||||
# DisplayName: Starship
|
||||
# Description: Install Starship shell prompt
|
||||
#
|
||||
# Starship Installer Script
|
||||
#
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tool: yay
|
||||
# DisplayName: Yay
|
||||
# Description: Install Yay AUR helper
|
||||
#
|
||||
# Yay Installer Script
|
||||
#
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tool: yazi
|
||||
# DisplayName: Yazi
|
||||
# Description: Install Yazi terminal file manager and dependencies
|
||||
#
|
||||
# Yazi Installer Script
|
||||
#
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tool: zoxide
|
||||
# DisplayName: Zoxide
|
||||
# Description: Install Zoxide directory jumper
|
||||
#
|
||||
# Zoxide Installer Script
|
||||
#
|
||||
|
||||
@@ -58,6 +58,12 @@ To bypass the editor and install the tool directly using the `ware` command, app
|
||||
b ware nvim -y
|
||||
```
|
||||
|
||||
To list all available installer tools and their descriptions, run the `ware` (or `bware`) command without any arguments:
|
||||
|
||||
```bash
|
||||
b ware
|
||||
```
|
||||
|
||||
You can also edit configurations located in your `~/.config/` directory by running:
|
||||
|
||||
```bash
|
||||
|
||||
29
registry.sh
Normal file
29
registry.sh
Normal file
@@ -0,0 +1,29 @@
|
||||
# This file is auto-generated by scripts/generate_registry.sh. Do not edit manually.
|
||||
|
||||
declare -A INSTALLERS=(
|
||||
[agy]="Install Antigravity CLI"
|
||||
[bat]="Install Bat (alternative to cat) and configure alias"
|
||||
[node]="Install Node.js (LTS) and NVM"
|
||||
[nvim]="Install Neovim 0.11.7 and configuration"
|
||||
[pnpm]="Install pnpm package manager"
|
||||
[rust]="Install Rustup and Rust compiler/toolchain"
|
||||
[starship]="Install Starship shell prompt"
|
||||
[yay]="Install Yay AUR helper"
|
||||
[yazi]="Install Yazi terminal file manager and dependencies"
|
||||
[zoxide]="Install Zoxide directory jumper"
|
||||
)
|
||||
|
||||
declare -A INSTALLER_DISPLAYS=(
|
||||
[agy]="Antigravity"
|
||||
[bat]="Bat"
|
||||
[node]="Node"
|
||||
[nvim]="Neovim"
|
||||
[pnpm]="Pnpm"
|
||||
[rust]="Rust"
|
||||
[starship]="Starship"
|
||||
[yay]="Yay"
|
||||
[yazi]="Yazi"
|
||||
[zoxide]="Zoxide"
|
||||
)
|
||||
|
||||
INSTALLER_KEYS=(agy bat node nvim pnpm rust starship yay yazi zoxide)
|
||||
60
routes.sh
60
routes.sh
@@ -15,21 +15,35 @@ fi
|
||||
|
||||
require_bash
|
||||
|
||||
# Registry of installers
|
||||
declare -A INSTALLERS=(
|
||||
[agy]="Install Antigravity CLI"
|
||||
[bat]="Install Bat (alternative to cat) and configure alias"
|
||||
[node]="Install Node.js (LTS) and NVM"
|
||||
[nvim]="Install Neovim 0.11.7 and configuration"
|
||||
[pnpm]="Install pnpm package manager"
|
||||
[rust]="Install Rustup and Rust compiler/toolchain"
|
||||
[starship]="Install Starship shell prompt"
|
||||
[yay]="Install Yay AUR helper"
|
||||
[yazi]="Install Yazi terminal file manager and dependencies"
|
||||
[zoxide]="Install Zoxide directory jumper"
|
||||
)
|
||||
# Order in which installers should be displayed
|
||||
INSTALLER_KEYS=(agy bat node nvim pnpm rust starship yay yazi zoxide)
|
||||
_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd 2>/dev/null || pwd)"
|
||||
|
||||
# Source registry
|
||||
if [ -f "$_SCRIPT_DIR/registry.sh" ]; then
|
||||
. "$_SCRIPT_DIR/registry.sh"
|
||||
elif [ -f "$BOOTSTRAP_DIR/registry.sh" ]; then
|
||||
. "$BOOTSTRAP_DIR/registry.sh"
|
||||
else
|
||||
# Standalone/remote fallback: download registry
|
||||
_tmp_registry=$(mktemp)
|
||||
BOOTSTRAP_BASE_URL="${BOOTSTRAP_BASE_URL:-https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master}"
|
||||
BOOTSTRAP_FALLBACK_URL="${BOOTSTRAP_FALLBACK_URL:-https://raw.githubusercontent.com/sortedcord/bootstrap/refs/heads/master}"
|
||||
if has_command curl; then
|
||||
curl -fsSL "${BOOTSTRAP_BASE_URL}/registry.sh" -o "$_tmp_registry" 2>/dev/null || \
|
||||
curl -fsSL "${BOOTSTRAP_FALLBACK_URL}/registry.sh" -o "$_tmp_registry" 2>/dev/null
|
||||
elif has_command wget; then
|
||||
wget -qO "$_tmp_registry" "${BOOTSTRAP_BASE_URL}/registry.sh" 2>/dev/null || \
|
||||
wget -qO "$_tmp_registry" "${BOOTSTRAP_FALLBACK_URL}/registry.sh" 2>/dev/null
|
||||
fi
|
||||
if [ -s "$_tmp_registry" ]; then
|
||||
. "$_tmp_registry"
|
||||
else
|
||||
# Critical fallback
|
||||
declare -A INSTALLERS
|
||||
declare -A INSTALLER_DISPLAYS
|
||||
INSTALLER_KEYS=()
|
||||
fi
|
||||
rm -f "$_tmp_registry"
|
||||
fi
|
||||
|
||||
# Helper function to run/edit installer scripts
|
||||
run_ware() {
|
||||
@@ -47,8 +61,11 @@ run_ware() {
|
||||
fi
|
||||
done
|
||||
|
||||
# Capitalize first letter for display (e.g. nvim -> Neovim)
|
||||
local display_name="$(echo "${tool:0:1}" | tr '[:lower:]' '[:upper:]')${tool:1}"
|
||||
# Resolve display name from metadata or fallback
|
||||
local display_name="${INSTALLER_DISPLAYS[$tool]:-}"
|
||||
if [ -z "$display_name" ]; then
|
||||
display_name="$(echo "${tool:0:1}" | tr '[:lower:]' '[:upper:]')${tool:1}"
|
||||
fi
|
||||
|
||||
# Check for local installer first
|
||||
local local_installer="$BOOTSTRAP_DIR/installers/install_${tool}.sh"
|
||||
@@ -166,11 +183,14 @@ for script in "${SCRIPTS[@]}"; do
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
ware)
|
||||
ware|bware)
|
||||
tools_arg="${1:-}"
|
||||
if [ -z "$tools_arg" ]; then
|
||||
log_error "Usage: b ware <tool1,tool2,...> [-y]"
|
||||
exit 1
|
||||
echo "Available tools:"
|
||||
for key in "${INSTALLER_KEYS[@]}"; do
|
||||
printf " %-10s - %s\n" "$key" "${INSTALLERS[$key]}"
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
shift
|
||||
IFS=',' read -ra WARE_TOOLS <<< "$tools_arg"
|
||||
|
||||
56
scripts/generate_registry.sh
Executable file
56
scripts/generate_registry.sh
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
# Automatically generate registry.sh from installer headers.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
INSTALLERS_DIR="$REPO_DIR/installers"
|
||||
REGISTRY_FILE="$REPO_DIR/registry.sh"
|
||||
|
||||
echo "==> Generating registry.sh..."
|
||||
|
||||
# Temporary arrays
|
||||
declare -A tools_desc
|
||||
declare -A tools_disp
|
||||
keys=()
|
||||
|
||||
for f in "$INSTALLERS_DIR"/install_*.sh; do
|
||||
[ -f "$f" ] || continue
|
||||
tool=$(grep -E "^# Tool:" "$f" | head -n1 | sed -E 's/^# Tool:\s*//I')
|
||||
disp_name=$(grep -E "^# DisplayName:" "$f" | head -n1 | sed -E 's/^# DisplayName:\s*//I')
|
||||
desc=$(grep -E "^# Description:" "$f" | head -n1 | sed -E 's/^# Description:\s*//I')
|
||||
|
||||
if [ -n "$tool" ]; then
|
||||
tools_desc["$tool"]="$desc"
|
||||
tools_disp["$tool"]="${disp_name:-$tool}"
|
||||
keys+=("$tool")
|
||||
fi
|
||||
done
|
||||
|
||||
# Sort keys alphabetically
|
||||
sorted_keys=($(printf '%s\n' "${keys[@]}" | sort))
|
||||
|
||||
{
|
||||
echo "# This file is auto-generated by scripts/generate_registry.sh. Do not edit manually."
|
||||
echo ""
|
||||
echo "declare -A INSTALLERS=("
|
||||
for k in "${sorted_keys[@]}"; do
|
||||
# Escape any double quotes in description
|
||||
escaped_desc=$(echo "${tools_desc[$k]}" | sed 's/"/\\"/g')
|
||||
echo " [$k]=\"$escaped_desc\""
|
||||
done
|
||||
echo ")"
|
||||
echo ""
|
||||
echo "declare -A INSTALLER_DISPLAYS=("
|
||||
for k in "${sorted_keys[@]}"; do
|
||||
escaped_disp=$(echo "${tools_disp[$k]}" | sed 's/"/\\"/g')
|
||||
echo " [$k]=\"$escaped_disp\""
|
||||
done
|
||||
echo ")"
|
||||
echo ""
|
||||
# Format keys output as space-separated list in array declaration format
|
||||
echo "INSTALLER_KEYS=(${sorted_keys[*]})"
|
||||
} > "$REGISTRY_FILE"
|
||||
|
||||
echo "==> registry.sh successfully generated with ${#sorted_keys[@]} tools."
|
||||
@@ -4,6 +4,12 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Generate the registry dynamically and stage it
|
||||
if [ -f "./scripts/generate_registry.sh" ]; then
|
||||
./scripts/generate_registry.sh
|
||||
git add registry.sh
|
||||
fi
|
||||
|
||||
VERSION_FILE="VERSION"
|
||||
|
||||
if [ ! -f "$VERSION_FILE" ]; then
|
||||
|
||||
Reference in New Issue
Block a user