Files
ccs/lib/prompt.sh
T
Kai (Tam Nhu) TranandGitHub f40e9647ec feat(cli): comprehensive UX improvements for v3.5.0 (#7)
Implements 6-phase CLI UX improvement plan with comprehensive error handling, 
interactive features, and cross-platform consistency.

### Added
- Shell auto-completion (bash, zsh, PowerShell, Fish)
- Error codes (E101-E901) with documentation URLs
- Fuzzy matching "Did you mean?" suggestions (Levenshtein distance)
- Progress indicators (doctor [n/9] counter, GLMT proxy spinner)
- Interactive confirmation prompts with --yes/-y automation flag
- JSON output format (--json) for auth commands
- Impact display (session count, paths) before destructive operations
- Comprehensive test suite (15 tests, 100% pass rate)
- Complete error documentation in docs/errors/
- Cross-platform `--shell-completion` command

### Changed
- Error boxes: Unicode (╔═╗) → ASCII (===) for compatibility
- JSON output uses CCS version instead of schema version
- Help text includes EXAMPLES section across platforms
- Test suite properly counts test cases (not assertions)

### Fixed
- --yes flag bug (returned false instead of true)
- Help text consistency (added Uninstall section to bash)
- Test pass rate calculation (excludes skipped tests)
- Help section comparison (locale-specific sort)

### Testing
- 13/13 tests passing (2 legitimately skipped)
- Cross-platform verified (Node.js, bash, PowerShell)
- All error codes documented and tested
2025-11-15 01:26:50 -05:00

100 lines
2.1 KiB
Bash

#!/usr/bin/env bash
# CCS Interactive Prompt Utilities (bash 3.2+ compatible)
# NO external dependencies
set -euo pipefail
# Interactive confirmation prompt
# Usage: confirm_action "message" "yes"|"no"
# Returns: 0 (true) or 1 (false)
confirm_action() {
local message="$1"
local default="${2:-no}" # Default to NO for safety
# Check for --yes flag (automation) - always returns true (0)
if [[ "${CCS_YES:-}" == "1" ]]; then
return 0
fi
# Check for --no-input flag (CI)
if [[ "${CCS_NO_INPUT:-}" == "1" ]]; then
echo "[X] Interactive input required but --no-input specified" >&2
exit 1
fi
# Non-TTY: use default
if [[ ! -t 0 ]]; then
[[ "$default" == "yes" ]] && return 0 || return 1
fi
# Interactive prompt
local prompt
if [[ "$default" == "yes" ]]; then
prompt="$message [Y/n]: "
else
prompt="$message [y/N]: "
fi
while true; do
read -r -p "$prompt" response >&2
response=$(echo "$response" | tr '[:upper:]' '[:lower:]')
case "$response" in
""|" ")
# Empty answer: use default
[[ "$default" == "yes" ]] && return 0 || return 1
;;
y|yes)
return 0
;;
n|no)
return 1
;;
*)
echo "[!] Please answer y or n" >&2
;;
esac
done
}
# Interactive text input
# Usage: prompt_input "message" "default_value"
# Outputs: user input to stdout
prompt_input() {
local message="$1"
local default="${2:-}"
# Non-TTY: use default or error
if [[ ! -t 0 ]]; then
if [[ -n "$default" ]]; then
echo "$default"
return 0
else
echo "[X] Interactive input required but stdin is not a TTY" >&2
exit 1
fi
fi
# Interactive prompt
local prompt
if [[ -n "$default" ]]; then
prompt="$message [$default]: "
else
prompt="$message: "
fi
read -r -p "$prompt" response >&2
# Return user input or default
if [[ -z "$response" ]]; then
echo "$default"
else
echo "$response"
fi
}
# Check if running in non-interactive mode
is_non_interactive() {
[[ ! -t 0 ]] || [[ "${CCS_YES:-}" == "1" ]] || [[ "${CCS_NO_INPUT:-}" == "1" ]]
}