Skip to content
Draft
Show file tree
Hide file tree
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
110 changes: 110 additions & 0 deletions scripts/test-shell-dispatch.sh
Original file line number Diff line number Diff line change
@@ -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))
28 changes: 16 additions & 12 deletions shell-plugin/doctor.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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


Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.)
Expand Down
4 changes: 2 additions & 2 deletions shell-plugin/forge.setup.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion shell-plugin/lib/config.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -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}"

Expand Down
Loading