90 lines
3.5 KiB
Bash
90 lines
3.5 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
read_install_shell() {
|
|
local shell=$1
|
|
if [ -n "$shell" ]; then
|
|
case "$shell" in
|
|
powershell|PowerShell) printf 'powershell\n'; return 0 ;;
|
|
bash|Bash) printf 'bash\n'; return 0 ;;
|
|
*) printf 'Unknown --shell value: %s (expected powershell or bash)\n' "$shell" >&2; return 1 ;;
|
|
esac
|
|
fi
|
|
read_single_selection 'Select shell' 'PowerShell' 'powershell' 'Bash' 'bash'
|
|
}
|
|
|
|
read_install_client() {
|
|
local client=$1
|
|
if [ -n "$client" ]; then
|
|
case "$client" in
|
|
codex|Codex) printf 'codex\n'; return 0 ;;
|
|
claude|Claude) printf 'claude\n'; return 0 ;;
|
|
both|Both) printf 'both\n'; return 0 ;;
|
|
*) printf 'Unknown --client value: %s (expected codex, claude, or both)\n' "$client" >&2; return 1 ;;
|
|
esac
|
|
fi
|
|
read_single_selection 'Select client' 'Codex' 'codex' 'Claude' 'claude' 'Both' 'both'
|
|
}
|
|
|
|
clear_interactive() { [ -t 0 ] && [ "${CI:-}" != true ] && [ "${AI_CONFIG_NO_INTERACTIVE:-}" != 1 ] && printf '\033[2J\033[H' >&2; }
|
|
read_single_selection() {
|
|
local title=$1; shift; local labels=() values=() value index=0 key
|
|
while [ $# -gt 0 ]; do labels+=("$1"); values+=("$2"); shift 2; done
|
|
if [ ! -t 0 ] || [ "${CI:-}" = true ] || [ "${AI_CONFIG_NO_INTERACTIVE:-}" = 1 ]; then printf '%s\n' "$title" >&2; for ((index=0;index<${#labels[@]};index++)); do printf '%d) %s\n' "$((index+1))" "${labels[$index]}" >&2; done; while read -r -p 'Selection ' value; do [[ "$value" =~ ^[1-9][0-9]*$ ]] && [ "$value" -le "${#labels[@]}" ] && { printf '%s\n' "${values[$((value-1))]}"; return; }; done; return 1; fi
|
|
local selected=0
|
|
while :; do
|
|
clear_interactive
|
|
printf '%s\n' "$title" >&2
|
|
for ((index=0;index<${#labels[@]};index++)); do
|
|
if [ "$index" -eq "$selected" ]; then printf '> %s\n' "${labels[$index]}" >&2; else printf ' %s\n' "${labels[$index]}" >&2; fi
|
|
done
|
|
printf 'Up/Down Navigate Enter Confirm\n' >&2
|
|
IFS= read -rsn1 key || return 1
|
|
case "$key" in
|
|
$'\x1b')
|
|
read -rsn2 key || return 1
|
|
case "$key" in
|
|
'[A') selected=$(( (selected+${#labels[@]}-1)%${#labels[@]} ));;
|
|
'[B') selected=$(( (selected+1)%${#labels[@]} ));;
|
|
esac;;
|
|
'') clear_interactive; printf '%s\n' "${values[$selected]}"; return;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
# get_install_destinations <home> <client> -- prints one destination per line
|
|
get_install_destinations() {
|
|
local home_path=$1 client=$2
|
|
case "$client" in codex|both) printf '%s/.codex\n' "$home_path" ;; esac
|
|
case "$client" in claude|both) printf '%s/.claude\n' "$home_path" ;; esac
|
|
}
|
|
|
|
# get_install_targets <generated> <home> <shell> <client> -- prints "source|dest" per line
|
|
get_install_targets() {
|
|
local generated=$1 home_path=$2 shell=$3 client=$4
|
|
case "$client" in
|
|
codex|both)
|
|
printf '%s/codex-%s/skills|%s/.agents/skills\n' "$generated" "$shell" "$home_path"
|
|
printf '%s/codex-%s|%s/.codex\n' "$generated" "$shell" "$home_path"
|
|
;;
|
|
esac
|
|
case "$client" in claude|both) printf '%s/claude-%s|%s/.claude\n' "$generated" "$shell" "$home_path" ;; esac
|
|
}
|
|
|
|
# any_manifest_present <destination>... -- true (0) if at least one has a manifest
|
|
any_manifest_present() {
|
|
local destination
|
|
for destination in "$@"; do
|
|
[ -f "$(manifest_path "$destination")" ] && return 0
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# all_manifests_present <destination>... -- true (0) only if every destination has a manifest
|
|
all_manifests_present() {
|
|
local destination
|
|
for destination in "$@"; do
|
|
[ -f "$(manifest_path "$destination")" ] || return 1
|
|
done
|
|
return 0
|
|
}
|