feat(install): add arrow-key menu navigation

This commit is contained in:
thibaud-lclr 2026-04-15 10:43:00 +02:00
parent 21808ddce0
commit a19b35cbea

View file

@ -81,6 +81,101 @@ prompt() {
printf "%s" "$answer"
}
tty_prompt_available() {
[ -t 2 ] && [ -r /dev/tty ] && [ -w /dev/tty ]
}
menu_select() {
local title="$1"
shift
local options=("$@")
local count="${#options[@]}"
local index=0
local key=""
local i=0
local rows=$((count + 3))
local rendered=0
if [ "$count" -eq 0 ]; then
return 1
fi
if ! tty_prompt_available; then
ui_title "$title"
i=0
while [ "$i" -lt "$count" ]; do
printf " %d) %s\n" "$((i + 1))" "${options[$i]}" >&2
i=$((i + 1))
done
while true; do
local raw_choice
raw_choice="$(prompt "Choix" "1")"
case "$raw_choice" in
''|*[!0-9]*)
ui_warn "Choix invalide: $raw_choice"
;;
*)
if [ "$raw_choice" -ge 1 ] && [ "$raw_choice" -le "$count" ]; then
printf "%s" "${options[$((raw_choice - 1))]}"
return 0
fi
ui_warn "Choix invalide: $raw_choice"
;;
esac
done
fi
while true; do
if [ "$rendered" -eq 1 ]; then
printf "\033[%dA\033[J" "$rows" >&2 2>/dev/null || true
fi
ui_title "$title"
i=0
while [ "$i" -lt "$count" ]; do
if [ "$i" -eq "$index" ]; then
printf " %b %s%b\n" "$C_BOLD$C_CYAN" "${options[$i]}" "$C_RESET" >&2
else
printf " %s\n" "${options[$i]}" >&2
fi
i=$((i + 1))
done
printf "%bUtilise ↑/↓ puis Entrée.%b\n" "$C_DIM" "$C_RESET" >&2
rendered=1
if ! IFS= read -rsn1 key < /dev/tty; then
continue
fi
case "$key" in
"")
printf "%s" "${options[$index]}"
return 0
;;
$'\x1b')
if IFS= read -rsn2 key < /dev/tty; then
case "$key" in
"[A")
if [ "$index" -eq 0 ]; then
index=$((count - 1))
else
index=$((index - 1))
fi
;;
"[B")
if [ "$index" -eq $((count - 1)) ]; then
index=0
else
index=$((index + 1))
fi
;;
esac
fi
;;
esac
done
}
sanitize_server_name() {
local raw="$1"
local sanitized
@ -314,25 +409,15 @@ collect_server_inputs() {
choose_scope() {
local selected
while true; do
ui_title "Scope de configuration"
printf " 1) global (user)\n" >&2
printf " 2) project (projet courant)\n" >&2
selected="$(prompt "Choix" "1")"
selected="$(menu_select "Scope de configuration" "global (user)" "project (projet courant)")"
case "$selected" in
1)
"global (user)")
printf "global"
return
;;
2)
printf "project"
return
;;
*)
ui_warn "Choix invalide: $selected"
printf "project"
;;
esac
done
}
apply_claude_mcp() {
@ -453,48 +538,40 @@ print_header() {
printf "%bMCP Install Wizard%b for %b%s%b\n" "$C_BOLD$C_MAGENTA" "$C_RESET" "$C_BOLD" "$BINARY_NAME" "$C_RESET" >&2
printf "%bRelease repo:%b %s\n" "$C_DIM" "$C_RESET" "$RELEASE_REPOSITORY" >&2
ui_line
printf "Choisis une action:\n" >&2
printf " 1) Installer/mettre a jour le binaire + setup\n" >&2
printf " 2) Configurer Claude Code (apply direct)\n" >&2
printf " 3) Configurer Codex (apply direct)\n" >&2
printf " 4) Generer JSON MCP manuel\n" >&2
printf " 5) Quitter\n" >&2
printf "%bSelectionne une action dans le menu interactif.%b\n" "$C_DIM" "$C_RESET" >&2
}
main() {
while true; do
print_header
local choice
choice="$(prompt "Choix" "1")"
local action
action="$(menu_select \
"Choisis une action" \
"Installer/mettre a jour le binaire + setup" \
"Configurer Claude Code (apply direct)" \
"Configurer Codex (apply direct)" \
"Generer JSON MCP manuel" \
"Quitter")"
printf "\n" >&2
case "$choice" in
1)
case "$action" in
"Installer/mettre a jour le binaire + setup")
run_setup_wizard
return
;;
2)
"Configurer Claude Code (apply direct)")
apply_claude_mcp
return
;;
3)
"Configurer Codex (apply direct)")
apply_codex_mcp
return
;;
4)
"Generer JSON MCP manuel")
ui_info "JSON MCP genere sur stdout."
print_mcp_json
return
;;
5)
ui_warn "Annule."
return
;;
*)
ui_warn "Choix invalide: $choice"
ui_warn "Annule."
;;
esac
done
}
main "$@"