From d7defcbe87a35d5ea009a744c30fd8c28e1c5750 Mon Sep 17 00:00:00 2001 From: KooshaPari Date: Tue, 4 Aug 2026 19:09:08 -0700 Subject: [PATCH] fix(shell): default zsh dispatch to forgecode Provenance: f17756c7aa59ee5246d540f531ed2f4b1f08756f Co-Authored-By: ForgeCode --- scripts/test-shell-dispatch.sh | 110 +++++++++++++++++++++++++++++++++ shell-plugin/doctor.zsh | 28 +++++---- shell-plugin/forge.setup.zsh | 4 +- shell-plugin/lib/config.zsh | 2 +- 4 files changed, 129 insertions(+), 15 deletions(-) create mode 100644 scripts/test-shell-dispatch.sh diff --git a/scripts/test-shell-dispatch.sh b/scripts/test-shell-dispatch.sh new file mode 100644 index 0000000000..9d4414bf19 --- /dev/null +++ b/scripts/test-shell-dispatch.sh @@ -0,0 +1,110 @@ +#!/usr/bin/env zsh + +# Regression tests for the executable selected by the Forgecode zsh integration. + +set -euo pipefail + +SCRIPT_DIR="${0:A:h}" +REPO_ROOT="${SCRIPT_DIR:h}" + +PASS=0 +FAIL=0 + +function assert_eq() { + local test_name="$1" + local actual="$2" + local expected="$3" + + if [[ "$actual" == "$expected" ]]; then + print -r -- "[PASS] ${test_name}" + PASS=$((PASS + 1)) + else + print -r -- "[FAIL] ${test_name}" + print -r -- " expected: ${expected}" + print -r -- " actual: ${actual}" + FAIL=$((FAIL + 1)) + fi +} + +function assert_contains() { + local test_name="$1" + local actual="$2" + local expected="$3" + + if [[ "$actual" == *"${expected}"* ]]; then + print -r -- "[PASS] ${test_name}" + PASS=$((PASS + 1)) + else + print -r -- "[FAIL] ${test_name}" + print -r -- " expected to contain: ${expected}" + FAIL=$((FAIL + 1)) + fi +} + +function setup_output() { + local forge_bin="${1:-}" + + FORGE_BIN="$forge_bin" zsh -dfc ' + forge() { + print -u2 -r -- "forge:$*" + case "$1:$2" in + zsh:plugin) print -r -- "typeset -g _FORGE_PLUGIN_LOADED=1" ;; + zsh:theme) print -r -- "typeset -g _FORGE_THEME_LOADED=1" ;; + esac + } + forgecode() { + print -u2 -r -- "forgecode:$*" + case "$1:$2" in + zsh:plugin) print -r -- "typeset -g _FORGE_PLUGIN_LOADED=1" ;; + zsh:theme) print -r -- "typeset -g _FORGE_THEME_LOADED=1" ;; + esac + } + source "$1" + print -r -- "loaded:${_FORGE_PLUGIN_LOADED:-0}:${_FORGE_THEME_LOADED:-0}" + ' _ "${REPO_ROOT}/shell-plugin/forge.setup.zsh" 2>&1 +} + +function doctor_output() { + local forge_bin="${1:-}" + + FORGE_BIN="$forge_bin" ZDOTDIR="${REPO_ROOT}/.test-zdotdir" zsh -dfc ' + forge() { + if [[ "$1" == "--version" ]]; then + print -r -- "forge 1.0.0" + fi + } + forgecode() { + if [[ "$1" == "--version" ]]; then + print -r -- "forgecode 9.9.9" + fi + } + source "$1" + ' _ "${REPO_ROOT}/shell-plugin/doctor.zsh" 2>&1 || true +} + +assert_eq "plugin config defaults to forgecode" \ + "$(zsh -dfc 'source "$1"; print -r -- "$_FORGE_BIN"' _ "${REPO_ROOT}/shell-plugin/lib/config.zsh")" \ + "forgecode" + +assert_eq "plugin config preserves FORGE_BIN override" \ + "$(FORGE_BIN="/opt/custom-forge" zsh -dfc 'source "$1"; print -r -- "$_FORGE_BIN"' _ "${REPO_ROOT}/shell-plugin/lib/config.zsh")" \ + "/opt/custom-forge" + +assert_eq "setup loads plugin and theme through forgecode by default" \ + "$(setup_output)" \ + $'forgecode:zsh plugin\nforgecode:zsh theme\nloaded:1:1' + +assert_eq "setup preserves FORGE_BIN override" \ + "$(setup_output "forge")" \ + $'forge:zsh plugin\nforge:zsh theme\nloaded:1:1' + +default_doctor_output="$(doctor_output)" +assert_contains "doctor checks forgecode by default" "$default_doctor_output" "forgecode: 9.9.9" +assert_contains "doctor suggests forgecode plugin setup by default" "$default_doctor_output" '"forgecode" zsh plugin' + +override_doctor_output="$(doctor_output "forge")" +assert_contains "doctor preserves FORGE_BIN override" "$override_doctor_output" "forge: 1.0.0" +assert_contains "doctor preserves FORGE_BIN override in hints" "$override_doctor_output" '"forge" zsh plugin' + +print -r -- "${PASS}/$((PASS + FAIL)) checks passed" +((FAIL == 0)) diff --git a/shell-plugin/doctor.zsh b/shell-plugin/doctor.zsh index ebb0330938..bcf94ab89e 100755 --- a/shell-plugin/doctor.zsh +++ b/shell-plugin/doctor.zsh @@ -126,21 +126,25 @@ fi # 2. Check if forge is installed and in PATH print_section "Forge Installation" +# Respect an explicitly configured executable while defaulting to the +# Forgecode distribution instead of a legacy forge binary. +local forge_bin="${FORGE_BIN:-forgecode}" + # Check if forge is in PATH -if command -v forge &> /dev/null; then - local forge_path=$(command -v forge) +if command -v "$forge_bin" &> /dev/null; then + local forge_path=$(command -v "$forge_bin") # Get forge version and extract just the version number - local forge_version=$(forge --version 2>&1 | head -n1 | awk '{print $2}') + local forge_version=$("$forge_bin" --version 2>&1 | head -n1 | awk '{print $2}') if [[ -n "$forge_version" ]]; then - print_result pass "forge: ${forge_version}" + print_result pass "${forge_bin}: ${forge_version}" print_result info "${forge_path}" else - print_result pass "forge: installed" + print_result pass "${forge_bin}: installed" print_result info "${forge_path}" fi else - print_result fail "Forge binary not found in PATH" "Installation: curl -fsSL https://forgecode.dev/cli | sh" + print_result fail "Forge binary not found: ${forge_bin}" "Installation: curl -fsSL https://forgecode.dev/cli | sh" fi # 3. Check shell plugin @@ -152,8 +156,8 @@ if [[ -n "$_FORGE_PLUGIN_LOADED" ]]; then else print_result fail "Forge plugin not loaded" print_result instruction "Add to your ~/.zshrc:" - print_result code "eval \"\$(forge zsh plugin)\"" - print_result instruction "Or run: forge zsh setup" + print_result code "eval \"\$(\"${forge_bin}\" zsh plugin)\"" + print_result instruction "Or run: ${forge_bin} zsh setup" fi @@ -198,11 +202,11 @@ elif (( $+functions[p10k] )); then elif [[ -n "$ZSH_THEME" ]]; then print_result warn "Using theme: ${ZSH_THEME}" print_result instruction "To use Forge theme, add to ~/.zshrc:" - print_result code "eval \"\$(forge zsh theme)\"" + print_result code "eval \"\$(\"${forge_bin}\" zsh theme)\"" else print_result warn "No theme loaded" print_result instruction "To use Forge theme, add to ~/.zshrc:" - print_result code "eval \"\$(forge zsh theme)\"" + print_result code "eval \"\$(\"${forge_bin}\" zsh theme)\"" fi # Helper function to compare versions @@ -412,7 +416,7 @@ if [[ "$platform" == "Darwin" ]]; then print_result info "• VS Code: Settings → terminal.integrated.macOptionIsMeta → true" print_result info "• iTerm2: Preferences → Profiles → Keys → Option Key → Esc+" print_result info "• Terminal.app: Preferences → Profiles → Keyboard → Use Option as Meta" - print_result info "Run 'forge zsh keyboard' for detailed keyboard shortcuts" + print_result info "Run '${forge_bin} zsh keyboard' for detailed keyboard shortcuts" fi elif [[ "$platform" == "Linux" ]]; then @@ -502,7 +506,7 @@ elif [[ "$platform" == "Linux" ]]; then print_result info "• GNOME Terminal: Usually works by default" print_result info "• Konsole: Usually works by default" print_result info "• xterm: Add 'XTerm*metaSendsEscape: true' to ~/.Xresources" - print_result info "Run 'forge zsh keyboard' for detailed keyboard shortcuts" + print_result info "Run '${forge_bin} zsh keyboard' for detailed keyboard shortcuts" fi else # Other platforms (BSD, etc.) diff --git a/shell-plugin/forge.setup.zsh b/shell-plugin/forge.setup.zsh index 76e2039905..c3de1e4b9a 100644 --- a/shell-plugin/forge.setup.zsh +++ b/shell-plugin/forge.setup.zsh @@ -11,10 +11,10 @@ fi # Load forge shell plugin (commands, completions, keybindings) if not already loaded if [[ -z "$_FORGE_PLUGIN_LOADED" ]]; then - eval "$(forge zsh plugin)" + eval "$("${FORGE_BIN:-forgecode}" zsh plugin)" fi # Load forge shell theme (prompt with AI context) if not already loaded if [[ -z "$_FORGE_THEME_LOADED" ]]; then - eval "$(forge zsh theme)" + eval "$("${FORGE_BIN:-forgecode}" zsh theme)" fi diff --git a/shell-plugin/lib/config.zsh b/shell-plugin/lib/config.zsh index adbbe487e0..3a326b8d89 100644 --- a/shell-plugin/lib/config.zsh +++ b/shell-plugin/lib/config.zsh @@ -3,7 +3,7 @@ # Configuration variables for forge plugin # Using typeset to keep variables local to plugin scope and prevent public exposure -typeset -h _FORGE_BIN="${FORGE_BIN:-forge}" +typeset -h _FORGE_BIN="${FORGE_BIN:-forgecode}" typeset -h _FORGE_CONVERSATION_PATTERN=":" typeset -h _FORGE_MAX_COMMIT_DIFF="${FORGE_MAX_COMMIT_DIFF:-100000}"