mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-15 18:21:09 +00:00
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
118 lines
2.9 KiB
Bash
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
|
|
}
|