Files
ccs/lib/progress-indicator.sh
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

118 lines
2.9 KiB
Bash

#!/usr/bin/env bash
# CCS Progress Indicator (bash 3.2+ compatible)
# Simple spinner for long-running operations
# NO external dependencies - ASCII-only for cross-platform compatibility
set -euo pipefail
# Show spinner while a background process is running
# Usage: show_spinner "message" $pid
show_spinner() {
local message="$1"
local pid="$2"
# TTY detection: only animate if stderr is TTY and not in CI
if [[ ! -t 2 ]] || [[ -n "${CI:-}" ]] || [[ -n "${NO_COLOR:-}" ]]; then
# Non-TTY: just print message once
echo "[i] $message..." >&2
wait "$pid" 2>/dev/null || true
return
fi
# ASCII-only frames for cross-platform compatibility
local frames=('|' '/' '-' '\\')
local frame_idx=0
local start_time=$(date +%s)
# Animate spinner while process is running
while kill -0 "$pid" 2>/dev/null; do
local frame="${frames[$frame_idx]}"
local elapsed=$(($(date +%s) - start_time))
printf "\r[%s] %s... (%ds)" "$frame" "$message" "$elapsed" >&2
frame_idx=$(( (frame_idx + 1) % 4 ))
sleep 0.1
done
# Clear spinner line
printf "\r\033[K" >&2
# Wait for process to complete and capture exit code
wait "$pid" 2>/dev/null || true
}
# Show spinner with success/fail result
# Usage: spinner_with_result "message" "command"
spinner_with_result() {
local message="$1"
shift
local command=("$@")
local start_time=$(date +%s)
# TTY detection
if [[ ! -t 2 ]] || [[ -n "${CI:-}" ]] || [[ -n "${NO_COLOR:-}" ]]; then
# Non-TTY: just print message and run command
echo "[i] $message..." >&2
if "${command[@]}"; then
echo "[OK] $message" >&2
return 0
else
echo "[X] $message" >&2
return 1
fi
fi
# Run command in background
"${command[@]}" &>/dev/null &
local pid=$!
# Show spinner
local frames=('|' '/' '-' '\\')
local frame_idx=0
while kill -0 "$pid" 2>/dev/null; do
local frame="${frames[$frame_idx]}"
local elapsed=$(($(date +%s) - start_time))
printf "\r[%s] %s... (%ds)" "$frame" "$message" "$elapsed" >&2
frame_idx=$(( (frame_idx + 1) % 4 ))
sleep 0.1
done
# Clear spinner line
printf "\r\033[K" >&2
# Check result
if wait "$pid" 2>/dev/null; then
local elapsed=$(($(date +%s) - start_time))
echo "[OK] $message (${elapsed}s)" >&2
return 0
else
echo "[X] $message" >&2
return 1
fi
}
# Simple progress counter (for multi-step operations)
# Usage: show_progress_step 3 10 "Checking configuration"
show_progress_step() {
local current="$1"
local total="$2"
local message="$3"
# TTY detection
if [[ ! -t 2 ]] || [[ -n "${CI:-}" ]]; then
echo "[${current}/${total}] $message" >&2
return
fi
# Show progress with carriage return (can be overwritten)
printf "\r[%d/%d] %s..." "$current" "$total" "$message" >&2
}
# Clear progress line
clear_progress() {
if [[ -t 2 ]] && [[ -z "${CI:-}" ]]; then
printf "\r\033[K" >&2
fi
}