Initial commit
This commit is contained in:
94
skills/clap-patterns/scripts/generate-completions.sh
Executable file
94
skills/clap-patterns/scripts/generate-completions.sh
Executable file
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env bash
|
||||
# Generate shell completions for Clap CLI applications
|
||||
#
|
||||
# Usage: ./generate-completions.sh <binary-name> [output-dir]
|
||||
#
|
||||
# This script generates shell completion scripts for bash, zsh, fish, and powershell.
|
||||
# The CLI binary must support the --generate-completions flag (built with Clap).
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
BINARY="${1:-}"
|
||||
OUTPUT_DIR="${2:-completions}"
|
||||
|
||||
if [ -z "$BINARY" ]; then
|
||||
echo "Error: Binary name required"
|
||||
echo "Usage: $0 <binary-name> [output-dir]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create output directory
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
echo "Generating shell completions for: $BINARY"
|
||||
echo "Output directory: $OUTPUT_DIR"
|
||||
echo ""
|
||||
|
||||
# Check if binary exists
|
||||
if ! command -v "$BINARY" &> /dev/null; then
|
||||
echo "Warning: Binary '$BINARY' not found in PATH"
|
||||
echo "Make sure to build and install it first: cargo install --path ."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Generate completions for each shell
|
||||
for shell in bash zsh fish powershell elvish; do
|
||||
echo "Generating $shell completions..."
|
||||
|
||||
case "$shell" in
|
||||
bash)
|
||||
"$BINARY" --generate-completion "$shell" > "$OUTPUT_DIR/${BINARY}.bash" 2>/dev/null || {
|
||||
echo " ⚠️ Failed (CLI may not support --generate-completion)"
|
||||
continue
|
||||
}
|
||||
echo " ✓ Generated: $OUTPUT_DIR/${BINARY}.bash"
|
||||
;;
|
||||
zsh)
|
||||
"$BINARY" --generate-completion "$shell" > "$OUTPUT_DIR/_${BINARY}" 2>/dev/null || {
|
||||
echo " ⚠️ Failed"
|
||||
continue
|
||||
}
|
||||
echo " ✓ Generated: $OUTPUT_DIR/_${BINARY}"
|
||||
;;
|
||||
fish)
|
||||
"$BINARY" --generate-completion "$shell" > "$OUTPUT_DIR/${BINARY}.fish" 2>/dev/null || {
|
||||
echo " ⚠️ Failed"
|
||||
continue
|
||||
}
|
||||
echo " ✓ Generated: $OUTPUT_DIR/${BINARY}.fish"
|
||||
;;
|
||||
powershell)
|
||||
"$BINARY" --generate-completion "$shell" > "$OUTPUT_DIR/_${BINARY}.ps1" 2>/dev/null || {
|
||||
echo " ⚠️ Failed"
|
||||
continue
|
||||
}
|
||||
echo " ✓ Generated: $OUTPUT_DIR/_${BINARY}.ps1"
|
||||
;;
|
||||
elvish)
|
||||
"$BINARY" --generate-completion "$shell" > "$OUTPUT_DIR/${BINARY}.elv" 2>/dev/null || {
|
||||
echo " ⚠️ Failed"
|
||||
continue
|
||||
}
|
||||
echo " ✓ Generated: $OUTPUT_DIR/${BINARY}.elv"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "✓ Completion generation complete!"
|
||||
echo ""
|
||||
echo "Installation instructions:"
|
||||
echo ""
|
||||
echo "Bash:"
|
||||
echo " sudo cp $OUTPUT_DIR/${BINARY}.bash /etc/bash_completion.d/"
|
||||
echo " Or: echo 'source $PWD/$OUTPUT_DIR/${BINARY}.bash' >> ~/.bashrc"
|
||||
echo ""
|
||||
echo "Zsh:"
|
||||
echo " cp $OUTPUT_DIR/_${BINARY} /usr/local/share/zsh/site-functions/"
|
||||
echo " Or add to fpath: fpath=($PWD/$OUTPUT_DIR \$fpath)"
|
||||
echo ""
|
||||
echo "Fish:"
|
||||
echo " cp $OUTPUT_DIR/${BINARY}.fish ~/.config/fish/completions/"
|
||||
echo ""
|
||||
echo "PowerShell:"
|
||||
echo " Add to profile: . $PWD/$OUTPUT_DIR/_${BINARY}.ps1"
|
||||
159
skills/clap-patterns/scripts/test-cli.sh
Executable file
159
skills/clap-patterns/scripts/test-cli.sh
Executable file
@@ -0,0 +1,159 @@
|
||||
#!/usr/bin/env bash
|
||||
# Test a Clap CLI application with various argument combinations
|
||||
#
|
||||
# Usage: ./test-cli.sh <binary-path> [test-suite]
|
||||
#
|
||||
# Test suites: basic, subcommands, validation, env, all (default)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
BINARY="${1:-}"
|
||||
TEST_SUITE="${2:-all}"
|
||||
|
||||
if [ -z "$BINARY" ]; then
|
||||
echo "Error: Binary path required"
|
||||
echo "Usage: $0 <binary-path> [test-suite]"
|
||||
echo ""
|
||||
echo "Test suites:"
|
||||
echo " basic - Test help, version, basic flags"
|
||||
echo " subcommands - Test subcommand routing"
|
||||
echo " validation - Test input validation"
|
||||
echo " env - Test environment variables"
|
||||
echo " all - Run all tests (default)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -x "$BINARY" ]; then
|
||||
echo "Error: Binary not found or not executable: $BINARY"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PASS=0
|
||||
FAIL=0
|
||||
|
||||
run_test() {
|
||||
local name="$1"
|
||||
local expected_exit="$2"
|
||||
shift 2
|
||||
|
||||
echo -n "Testing: $name ... "
|
||||
|
||||
if "$BINARY" "$@" &>/dev/null; then
|
||||
actual_exit=0
|
||||
else
|
||||
actual_exit=$?
|
||||
fi
|
||||
|
||||
if [ "$actual_exit" -eq "$expected_exit" ]; then
|
||||
echo "✓ PASS"
|
||||
((PASS++))
|
||||
else
|
||||
echo "❌ FAIL (expected exit $expected_exit, got $actual_exit)"
|
||||
((FAIL++))
|
||||
fi
|
||||
}
|
||||
|
||||
test_basic() {
|
||||
echo ""
|
||||
echo "=== Basic Tests ==="
|
||||
|
||||
run_test "Help output" 0 --help
|
||||
run_test "Version output" 0 --version
|
||||
run_test "Short help" 0 -h
|
||||
run_test "Invalid flag" 1 --invalid-flag
|
||||
run_test "No arguments (might fail for some CLIs)" 0
|
||||
}
|
||||
|
||||
test_subcommands() {
|
||||
echo ""
|
||||
echo "=== Subcommand Tests ==="
|
||||
|
||||
run_test "Subcommand help" 0 help
|
||||
run_test "Invalid subcommand" 1 invalid-command
|
||||
|
||||
# Try common subcommands
|
||||
for cmd in init add build test deploy; do
|
||||
if "$BINARY" help 2>&1 | grep -q "$cmd"; then
|
||||
run_test "Subcommand '$cmd' help" 0 "$cmd" --help
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
test_validation() {
|
||||
echo ""
|
||||
echo "=== Validation Tests ==="
|
||||
|
||||
# Test file arguments with non-existent files
|
||||
run_test "Non-existent file" 1 --input /nonexistent/file.txt
|
||||
|
||||
# Test numeric ranges
|
||||
run_test "Invalid number" 1 --count abc
|
||||
run_test "Negative number" 1 --count -5
|
||||
|
||||
# Test conflicting flags
|
||||
if "$BINARY" --help 2>&1 | grep -q "conflicts with"; then
|
||||
echo " (Found conflicting arguments in help text)"
|
||||
fi
|
||||
}
|
||||
|
||||
test_env() {
|
||||
echo ""
|
||||
echo "=== Environment Variable Tests ==="
|
||||
|
||||
# Check if binary supports environment variables
|
||||
if "$BINARY" --help 2>&1 | grep -q "\[env:"; then
|
||||
echo "✓ Environment variable support detected"
|
||||
|
||||
# Extract env vars from help text
|
||||
ENV_VARS=$("$BINARY" --help 2>&1 | grep -o '\[env: [A-Z_]*\]' | sed 's/\[env: \(.*\)\]/\1/' || true)
|
||||
|
||||
if [ -n "$ENV_VARS" ]; then
|
||||
echo "Found environment variables:"
|
||||
echo "$ENV_VARS" | while read -r var; do
|
||||
echo " - $var"
|
||||
done
|
||||
fi
|
||||
else
|
||||
echo " No environment variable support detected"
|
||||
fi
|
||||
}
|
||||
|
||||
# Run requested test suite
|
||||
case "$TEST_SUITE" in
|
||||
basic)
|
||||
test_basic
|
||||
;;
|
||||
subcommands)
|
||||
test_subcommands
|
||||
;;
|
||||
validation)
|
||||
test_validation
|
||||
;;
|
||||
env)
|
||||
test_env
|
||||
;;
|
||||
all)
|
||||
test_basic
|
||||
test_subcommands
|
||||
test_validation
|
||||
test_env
|
||||
;;
|
||||
*)
|
||||
echo "Error: Unknown test suite: $TEST_SUITE"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
echo "=== Test Summary ==="
|
||||
echo "Passed: $PASS"
|
||||
echo "Failed: $FAIL"
|
||||
echo ""
|
||||
|
||||
if [ "$FAIL" -gt 0 ]; then
|
||||
echo "❌ Some tests failed"
|
||||
exit 1
|
||||
else
|
||||
echo "✓ All tests passed!"
|
||||
exit 0
|
||||
fi
|
||||
113
skills/clap-patterns/scripts/validate-cargo.sh
Executable file
113
skills/clap-patterns/scripts/validate-cargo.sh
Executable file
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env bash
|
||||
# Validate Cargo.toml for correct Clap configuration
|
||||
#
|
||||
# Usage: ./validate-cargo.sh [path-to-Cargo.toml]
|
||||
#
|
||||
# Checks:
|
||||
# - Clap dependency exists
|
||||
# - Clap version is 4.x or newer
|
||||
# - Required features are enabled (derive)
|
||||
# - Optional features (env, cargo) are present if needed
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
CARGO_TOML="${1:-Cargo.toml}"
|
||||
|
||||
if [ ! -f "$CARGO_TOML" ]; then
|
||||
echo "❌ Error: $CARGO_TOML not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Validating Clap configuration in: $CARGO_TOML"
|
||||
echo ""
|
||||
|
||||
# Check if clap is listed as a dependency
|
||||
if ! grep -q "clap" "$CARGO_TOML"; then
|
||||
echo "❌ Clap not found in dependencies"
|
||||
echo ""
|
||||
echo "Add to $CARGO_TOML:"
|
||||
echo ""
|
||||
echo '[dependencies]'
|
||||
echo 'clap = { version = "4.5", features = ["derive"] }'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ Clap dependency found"
|
||||
|
||||
# Extract clap version
|
||||
VERSION=$(grep -A 5 '^\[dependencies\]' "$CARGO_TOML" | grep 'clap' | head -1)
|
||||
|
||||
# Check version
|
||||
if echo "$VERSION" | grep -q '"4\.' || echo "$VERSION" | grep -q "'4\."; then
|
||||
echo "✓ Clap version 4.x detected"
|
||||
elif echo "$VERSION" | grep -q '"3\.' || echo "$VERSION" | grep -q "'3\."; then
|
||||
echo "⚠️ Warning: Clap version 3.x detected"
|
||||
echo " Consider upgrading to 4.x for latest features"
|
||||
else
|
||||
echo "⚠️ Warning: Could not determine Clap version"
|
||||
fi
|
||||
|
||||
# Check for derive feature
|
||||
if echo "$VERSION" | grep -q 'features.*derive' || echo "$VERSION" | grep -q 'derive.*features'; then
|
||||
echo "✓ 'derive' feature enabled"
|
||||
else
|
||||
echo "❌ 'derive' feature not found"
|
||||
echo " Add: features = [\"derive\"]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for optional but recommended features
|
||||
echo ""
|
||||
echo "Optional features:"
|
||||
|
||||
if echo "$VERSION" | grep -q '"env"' || echo "$VERSION" | grep -q "'env'"; then
|
||||
echo "✓ 'env' feature enabled (environment variable support)"
|
||||
else
|
||||
echo " 'env' feature not enabled"
|
||||
echo " Add for environment variable support: features = [\"derive\", \"env\"]"
|
||||
fi
|
||||
|
||||
if echo "$VERSION" | grep -q '"cargo"' || echo "$VERSION" | grep -q "'cargo'"; then
|
||||
echo "✓ 'cargo' feature enabled (automatic version from Cargo.toml)"
|
||||
else
|
||||
echo " 'cargo' feature not enabled"
|
||||
echo " Add for automatic version: features = [\"derive\", \"cargo\"]"
|
||||
fi
|
||||
|
||||
if echo "$VERSION" | grep -q '"color"' || echo "$VERSION" | grep -q "'color'"; then
|
||||
echo "✓ 'color' feature enabled (colored output)"
|
||||
else
|
||||
echo " 'color' feature not enabled"
|
||||
echo " Add for colored help: features = [\"derive\", \"color\"]"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Check for common patterns in src/
|
||||
if [ -d "src" ]; then
|
||||
echo "Checking source files for Clap usage patterns..."
|
||||
|
||||
if grep -r "use clap::Parser" src/ &>/dev/null; then
|
||||
echo "✓ Parser trait usage found"
|
||||
fi
|
||||
|
||||
if grep -r "use clap::Subcommand" src/ &>/dev/null; then
|
||||
echo "✓ Subcommand trait usage found"
|
||||
fi
|
||||
|
||||
if grep -r "use clap::ValueEnum" src/ &>/dev/null; then
|
||||
echo "✓ ValueEnum trait usage found"
|
||||
fi
|
||||
|
||||
if grep -r "#\[derive(Parser)\]" src/ &>/dev/null; then
|
||||
echo "✓ Parser derive macro usage found"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "✓ Validation complete!"
|
||||
echo ""
|
||||
echo "Recommended Cargo.toml configuration:"
|
||||
echo ""
|
||||
echo '[dependencies]'
|
||||
echo 'clap = { version = "4.5", features = ["derive", "env", "cargo"] }'
|
||||
Reference in New Issue
Block a user