Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 65 additions & 75 deletions cli/install.sh
Original file line number Diff line number Diff line change
@@ -1,38 +1,41 @@
#!/usr/bin/env bash
# install.sh — installer for hypercar-colorscripts (v0.1.1)
# install.sh — installer for hypercar-colorscripts (v0.1.4)
#
# Bug-fix release. Changes vs the previous public build:
# Changes from v0.1.3:
# * Explicit --logo-type based on our own terminal detection.
# Fastfetch's auto-detect (default when --logo-type is omitted)
# is unreliable on Darwin: on macOS Ghostty it silently picks
# `file-raw` and dumps the PNG magic bytes to the terminal as
# text, even though Ghostty implements the kitty graphics
# protocol correctly. We already know which terminal family
# we're in (that's what __HC_IMG_OK==1 means), so we pick the
# protocol ourselves:
# - Kitty / Ghostty / WezTerm -> kitty-direct
# - iTerm2 -> iterm
# This works identically on Linux and macOS.
#
# * ben10-colorscripts coexistence. Previously, installing hypercar
# after ben10 would leave both shell blocks active (double render).
# Now:
# - if a ben10-colorscripts shell block is already present, hypercar
# defers to it and skips writing its own render block (ben10's
# block already knows how to render both projects);
# - if only the ben10 binary is present (no ben10 block), hypercar's
# own render block includes ben10 in the mixing pool.
# Changes from v0.1.2:
# * Non-image branch renders PNG on-the-fly via `chafa --colors 256`
# instead of cat-ing pre-rendered truecolor ANSI files.
# Pre-rendered ANSI used \e[38;2;R;G;Bm escapes that Apple Terminal
# (256-color only) cannot render, producing garbled half-block
# pixels with overlaid info-card values.
# * `ls` -> `find` for image discovery.
#
# * fastfetch styling: writes ~/.config/fastfetch/hypercar.jsonc
# automatically (Catppuccin+ vibrant gradient palette). Arrows now
# align perfectly (`type: name`, no icons — icons re-enabled by
# changing one field in the JSONC). Existing file is backed up.
#
# * chafa fallback: image still renders when fastfetch is not installed.
#
# * kitty logo-type detection fix (kitty-direct → kitty on older
# fastfetch builds).
#
# * macOS portability: `shuf` replaced with an awk one-liner, Ghostty
# detection via TERM_PROGRAM + TERM as well as GHOSTTY_RESOURCES_DIR.
#
# * Broader marker-deletion regex on reinstall; PATH dedupe.
# Prior fixes (from v0.1.1):
# * ben10-colorscripts coexistence (defers when ben10 block present).
# * Vibrant Catppuccin+ gradient JSONC (auto-written).
# * Portable random-line picker.
# * Ghostty detection via TERM_PROGRAM + TERM.
# * Zsh-safe mixing target picker.
# * Broader marker-deletion regex; PATH dedupe.
#
# Flags:
# --system binary -> /usr/local/bin (sudo)
# --no-shell skip all .rc modifications
# --yes / -y skip confirmations
# --with-vintage include vintage cars even with --yes
# --no-mix don't mix with other colorscripts (pokemon / ben10)
# --no-mix don't mix with other colorscripts
# --no-ff-config skip writing ~/.config/fastfetch/hypercar.jsonc
# --uninstall forward to uninstall.sh

Expand Down Expand Up @@ -71,7 +74,7 @@ SRC_MANIFEST="$PROJECT_ROOT/manifest.json"
SRC_ASSETS="$PROJECT_ROOT/assets"
HELPER="$SCRIPT_DIR/_vintage_helper.py"

echo -e "${BLUE}═══ hypercar-colorscripts installer (v0.1.1) ═══${NC}"
echo -e "${BLUE}═══ hypercar-colorscripts installer (v0.1.4) ═══${NC}"

# 1. Prereqs + detect other colorscripts projects
step "1/9 Prerequisites"
Expand All @@ -94,16 +97,10 @@ if command -v ben10-colorscripts >/dev/null 2>&1; then
ok "ben10-colorscripts detected at $(command -v ben10-colorscripts)"
fi

# Detect which kitty logo type this fastfetch understands.
# `kitty-direct` is newer (~2024); older builds only know `kitty`.
KITTY_LOGO_TYPE="kitty-direct"
if command -v fastfetch >/dev/null 2>&1; then
if ! fastfetch --help-logo 2>/dev/null | grep -q 'kitty-direct'; then
KITTY_LOGO_TYPE="kitty"
fi
ok "fastfetch logo type: $KITTY_LOGO_TYPE"
ok "fastfetch present"
else
warn "fastfetch not installed — image will still render via chafa; info card skipped"
warn "fastfetch not installed — image renders via chafa; info card skipped"
fi

# 2. Build
Expand All @@ -124,8 +121,8 @@ step "4/9 Default rendering mode"
DEFAULT_MODE="auto"
if [[ $ASSUME_YES -eq 0 ]]; then
echo "How to render at terminal startup:"
echo " 1) auto — real image in Kitty/Ghostty/WezTerm/iTerm2, ANSI text elsewhere"
echo " 2) ansi — always pre-rendered text"
echo " 1) auto — real image in Kitty/Ghostty/WezTerm/iTerm2, chafa-ANSI elsewhere"
echo " 2) ansi — always chafa-ANSI (works everywhere, 256-color safe)"
read -rp "Choice [1]: " m
case "${m:-1}" in 2) DEFAULT_MODE="ansi" ;; *) DEFAULT_MODE="auto" ;; esac
fi
Expand All @@ -152,7 +149,7 @@ fi

# 6. Mixing
step "6/9 Colorscripts mixing"
POKEMON_MIX="false" # config field name kept for backward-compat; controls all mixing now
POKEMON_MIX="false"
if [[ $NO_MIX -eq 0 ]] && [[ $HAS_POKEMON -eq 1 || $HAS_BEN10 -eq 1 ]]; then
MIXERS=""
[[ $HAS_POKEMON -eq 1 ]] && MIXERS="${MIXERS:+$MIXERS + }pokemon"
Expand Down Expand Up @@ -211,7 +208,7 @@ else
fi
ok "Binary: $BIN_DIR/$BINARY"

# 8. fastfetch styling config (vibrant Catppuccin+ gradient)
# 8. fastfetch styling config (vibrant gradient)
step "8/9 fastfetch styling config"
if [[ $NO_FF_CONFIG -eq 1 ]]; then
warn "Skipped (--no-ff-config)"
Expand Down Expand Up @@ -300,10 +297,7 @@ if [[ -n "$SECONDARY_RC" ]]; then
fi
fi

# Detect if ben10-colorscripts already owns the shell integration in ANY
# of the rc files we're about to touch. If so, we defer to it and skip
# writing hypercar's own render block (ben10's block already handles both
# projects via its coexistence logic).
# Defer to ben10-colorscripts if its block already owns the shell rc.
BEN10_OWNS_SHELL=0
for RC in "${RC_FILES[@]}"; do
if [[ -f "$RC" ]] && grep -qE '# >>> ben10-colorscripts.*>>>' "$RC" 2>/dev/null; then
Expand All @@ -316,8 +310,7 @@ if [[ $BEN10_OWNS_SHELL -eq 1 ]]; then
warn "ben10-colorscripts shell block detected"
echo " ben10's block already handles rendering hypercar alongside itself."
echo " Skipping hypercar shell-block write to avoid double-render."
echo " (If you want hypercar to own the block, first run ben10-colorscripts's"
echo " uninstall.sh to remove ben10's block, then re-run this installer.)"
echo " (Run ben10's uninstall.sh first if you want hypercar to own the block.)"
echo
echo -e "${GREEN}═══ Done ═══${NC}"
[[ $INCLUDE_VINTAGE -eq 1 ]] && echo "Installed: $TOTAL_COUNT cars (modern + vintage)" || echo "Installed: $MODERN_COUNT cars"
Expand All @@ -340,9 +333,6 @@ for RC in "${RC_FILES[@]}"; do
BACKUP="$RC.hypercar-backup-$(date +%Y%m%d-%H%M%S)"
cp "$RC" "$BACKUP"

# Broad marker cleanup — catches every past variant of our own block
# (only ours; ben10's block is left untouched — but if we got here,
# ben10's block isn't present anyway).
sed -i.tmp '/# >>> hypercar-colorscripts.*>>>/,/# <<< hypercar-colorscripts.*<<</d' "$RC"
rm -f "$RC.tmp"

Expand All @@ -352,7 +342,6 @@ for RC in "${RC_FILES[@]}"; do
ok "Commented existing pokemon line"
fi

# Dedupe stray un-marked `export PATH="$HOME/.local/bin:$PATH"` lines
TMP="$(mktemp)"
awk '
/^export PATH="\$HOME\/\.local\/bin:\$PATH"[[:space:]]*$/ {
Expand All @@ -379,8 +368,6 @@ for RC in "${RC_FILES[@]}"; do

BEFORE=$(fsize "$RC")

# Write render block via single-quoted heredoc, then sed-substitute
# the @@HC_KITTY_TYPE@@ placeholder with the detected logo type.
cat >> "$RC" <<'HC_BLOCK_END'

# >>> hypercar-colorscripts >>>
Expand All @@ -399,18 +386,12 @@ if [ -f "$__HC_CONF" ]; then
unset __HC_TMP
fi

# Use the hypercar fastfetch styling config if present; deleting it never
# breaks this block (fastfetch just falls back to its default output).
__HC_FF_ARGS=()
[ -f "$__HC_FF_CFG" ] && __HC_FF_ARGS=(-c "$__HC_FF_CFG")

# Portable random-line picker (macOS has no `shuf` by default).
__hc_pick() { awk 'BEGIN{srand()} {a[NR]=$0} END{if(NR)print a[int(rand()*NR)+1]}'; }

# Mixing target selection. We use explicit slot arithmetic instead of
# shell word-splitting on a pool string, because zsh (unlike bash) does
# not word-split unquoted variables by default — which would make the
# picker collapse to always picking "car".
# Mixing target selection (explicit slots — zsh-safe, no word splitting).
__HC_TARGET="car"
if [ "$__HC_MIX" = "true" ]; then
__HC_HAS_POKEMON=0
Expand All @@ -419,8 +400,6 @@ if [ "$__HC_MIX" = "true" ]; then
command -v ben10-colorscripts >/dev/null 2>&1 && __HC_HAS_BEN10=1
__HC_TOTAL=$(( 1 + __HC_HAS_POKEMON + __HC_HAS_BEN10 ))
__HC_ROLL=$(( RANDOM % __HC_TOTAL ))
# Slot 0 is always car; the installed siblings fill slots 1..N-1
# in the order pokemon, then ben10.
if [ "$__HC_ROLL" -eq 0 ]; then
__HC_TARGET="car"
elif [ "$__HC_ROLL" -eq 1 ] && [ "$__HC_HAS_POKEMON" -eq 1 ]; then
Expand All @@ -432,6 +411,8 @@ if [ "$__HC_MIX" = "true" ]; then
fi
fi

# Image-capable terminal detection. These four terminal families implement
# an inline image protocol; everything else falls through to chafa-ANSI.
__HC_IMG_OK=0
case "${TERM:-}" in xterm-kitty*|xterm-ghostty*) __HC_IMG_OK=1 ;; esac
[ -n "${KITTY_WINDOW_ID:-}" ] && __HC_IMG_OK=1
Expand All @@ -456,48 +437,57 @@ elif [ "$__HC_TARGET" = "ben10" ]; then
ben10-colorscripts --random 2>/dev/null || ben10-colorscripts
fi
elif [ "$__HC_IMG_OK" -eq 1 ]; then
# Car branch — image path (Kitty/Ghostty/WezTerm/iTerm2)
__HC_IMG=$(ls "$__HC_DATA/assets/images/"*.png 2>/dev/null | __hc_pick)
# Car branch — image path. Explicitly pick fastfetch's --logo-type
# based on our own terminal detection. Fastfetch's --logo-type auto
# is unreliable on Darwin: on macOS Ghostty it silently picks
# `file-raw` (dumping PNG magic bytes to the terminal) even though
# Ghostty implements the kitty graphics protocol correctly.
#
# kitty-direct → Kitty, Ghostty, WezTerm (all implement kitty graphics)
# iterm → iTerm2 (its own inline image protocol)
__HC_LOGO_TYPE="kitty-direct"
[ "${TERM_PROGRAM:-}" = "iTerm.app" ] && __HC_LOGO_TYPE="iterm"

__HC_IMG=$(find "$__HC_DATA/assets/images" -type f -name "*.png" 2>/dev/null | __hc_pick)
if [ -n "$__HC_IMG" ]; then
if command -v fastfetch >/dev/null 2>&1; then
fastfetch "${__HC_FF_ARGS[@]}" --logo-type @@HC_KITTY_TYPE@@ --logo-height 14 --logo-width 28 --logo "$__HC_IMG"
fastfetch "${__HC_FF_ARGS[@]}" --logo-type "$__HC_LOGO_TYPE" --logo-height 14 --logo-width 28 --logo "$__HC_IMG"
elif command -v chafa >/dev/null 2>&1; then
chafa --size 60x20 "$__HC_IMG"
chafa --size 60x20 --colors 256 "$__HC_IMG"
fi
fi
unset __HC_LOGO_TYPE
else
# Car branch — ANSI fallback
__HC_ANSI=$(ls "$__HC_DATA/assets/ansi/"*.txt 2>/dev/null | __hc_pick)
if [ -n "$__HC_ANSI" ]; then
# Car branch — non-image terminals (Apple Terminal, plain xterm, tmux
# without truecolor, etc.). Render on-the-fly with `chafa --colors 256`
# so we never emit truecolor escapes that these terminals can't display.
__HC_IMG=$(find "$__HC_DATA/assets/images" -type f -name "*.png" 2>/dev/null | __hc_pick)
if [ -n "$__HC_IMG" ] && command -v chafa >/dev/null 2>&1; then
if command -v fastfetch >/dev/null 2>&1; then
cat "$__HC_ANSI" | fastfetch "${__HC_FF_ARGS[@]}" --logo-type file-raw --logo-height 25 --logo-width 80 --logo -
chafa --size 40x18 --format symbols --colors 256 "$__HC_IMG" | \
fastfetch "${__HC_FF_ARGS[@]}" --logo-type file-raw --logo-width 40 --logo -
else
cat "$__HC_ANSI"
chafa --size 40x18 --format symbols --colors 256 "$__HC_IMG"
fi
fi
fi
unset -f __hc_pick 2>/dev/null
unset __HC_DATA __HC_CONF __HC_FF_CFG __HC_FF_ARGS __HC_MODE __HC_MIX \
__HC_TARGET __HC_HAS_POKEMON __HC_HAS_BEN10 __HC_TOTAL __HC_ROLL \
__HC_IMG_OK __HC_IMG __HC_ANSI
__HC_IMG_OK __HC_IMG
# <<< hypercar-colorscripts <<<
HC_BLOCK_END

# Substitute the kitty logo type placeholder
sed -i.tmp "s|@@HC_KITTY_TYPE@@|${KITTY_LOGO_TYPE}|g" "$RC"
rm -f "$RC.tmp"

AFTER=$(fsize "$RC")
[[ $AFTER -gt $BEFORE ]] || fail "$RC didn't grow"
grep -q '# >>> hypercar-colorscripts >>>' "$RC" || fail "$RC missing marker"
grep -q '@@HC_KITTY_TYPE@@' "$RC" && fail "placeholder substitution failed in $RC"
ok "Block appended ($((AFTER - BEFORE)) bytes)"
done

echo
echo -e "${GREEN}═══ Done ═══${NC}"
[[ $INCLUDE_VINTAGE -eq 1 ]] && echo "Installed: $TOTAL_COUNT cars (modern + vintage)" || echo "Installed: $MODERN_COUNT cars"
echo "Mode: $DEFAULT_MODE Mixing: $POKEMON_MIX fastfetch logo-type: $KITTY_LOGO_TYPE"
echo "Mode: $DEFAULT_MODE Mixing: $POKEMON_MIX"
[[ $NO_FF_CONFIG -eq 0 ]] && echo "fastfetch styling: $FF_CONFIG_FILE"
[[ $HAS_BEN10 -eq 1 ]] && echo "ben10-colorscripts: detected, included in mixing"
echo
Expand Down
Loading