295 lines
7.4 KiB
Bash
295 lines
7.4 KiB
Bash
#!/bin/bash
|
||
|
||
# Cursor Rules Generator CLI
|
||
# Based on PageAI tutorial: https://pageai.pro/blog/cursor-rules-tutorial
|
||
|
||
set -e
|
||
|
||
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||
SCRIPT_DIR="$PROJECT_ROOT/scripts"
|
||
GENERATOR_SCRIPT="$SCRIPT_DIR/generate_cursor_rules.py"
|
||
|
||
# Colors for output
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Function to print colored output
|
||
print_info() {
|
||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||
}
|
||
|
||
print_success() {
|
||
echo -e "${GREEN}✅ $1${NC}"
|
||
}
|
||
|
||
print_warning() {
|
||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||
}
|
||
|
||
print_error() {
|
||
echo -e "${RED}❌ $1${NC}"
|
||
}
|
||
|
||
# Function to show usage
|
||
show_usage() {
|
||
cat << EOF
|
||
Cursor Rules Generator
|
||
|
||
Usage: $0 [OPTIONS] [DIRECTORIES...]
|
||
|
||
OPTIONS:
|
||
-h, --help Show this help message
|
||
-a, --analyze Analyze existing rules and suggest improvements
|
||
-g, --generate Generate rules for specified directories
|
||
-t, --type TYPE Rule type (python, javascript, testing, generic)
|
||
-f, --force Overwrite existing rules
|
||
-v, --verbose Verbose output
|
||
|
||
DIRECTORIES:
|
||
List of directories to analyze (e.g., src tests scripts)
|
||
|
||
EXAMPLES:
|
||
$0 --generate src tests # Generate rules for src and tests
|
||
$0 --generate --type python src # Generate Python-specific rules
|
||
$0 --analyze # Analyze existing rules
|
||
$0 --generate --force src # Force overwrite existing rules
|
||
|
||
EOF
|
||
}
|
||
|
||
# Function to check dependencies
|
||
check_dependencies() {
|
||
if ! command -v python3 &> /dev/null; then
|
||
print_error "Python 3 is required but not installed"
|
||
exit 1
|
||
fi
|
||
|
||
if [[ ! -f "$GENERATOR_SCRIPT" ]]; then
|
||
print_error "Generator script not found: $GENERATOR_SCRIPT"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# Function to analyze existing rules
|
||
analyze_rules() {
|
||
print_info "Analyzing existing Cursor rules..."
|
||
|
||
RULES_DIR="$PROJECT_ROOT/.cursor/rules"
|
||
|
||
if [[ ! -d "$RULES_DIR" ]]; then
|
||
print_warning "No .cursor/rules directory found"
|
||
return
|
||
fi
|
||
|
||
echo
|
||
echo "📊 Current Rules Analysis"
|
||
echo "========================"
|
||
|
||
# Count rules by type
|
||
total_rules=$(find "$RULES_DIR" -name "*.mdc" | wc -l)
|
||
always_apply=$(grep -r "alwaysApply: true" "$RULES_DIR" | wc -l)
|
||
domain_specific=$(find "$RULES_DIR" -name "*.mdc" -exec grep -l "globs:" {} \; | wc -l)
|
||
|
||
echo "Total rules: $total_rules"
|
||
echo "Always apply: $always_apply"
|
||
echo "Domain-specific: $domain_specific"
|
||
|
||
echo
|
||
echo "📁 Rule Categories:"
|
||
echo "-------------------"
|
||
|
||
# Categorize rules
|
||
if [[ -f "$RULES_DIR/project-structure.mdc" ]]; then
|
||
echo "✅ Project Structure (comprehensive)"
|
||
else
|
||
echo "❌ Project Structure (missing)"
|
||
fi
|
||
|
||
if [[ -f "$RULES_DIR/self_improve.mdc" ]]; then
|
||
echo "✅ Self-Improvement (enabled)"
|
||
else
|
||
echo "❌ Self-Improvement (missing)"
|
||
fi
|
||
|
||
if [[ -f "$RULES_DIR/cursor_rules.mdc" ]]; then
|
||
echo "✅ Cursor Rules (meta-rule)"
|
||
else
|
||
echo "❌ Cursor Rules (missing)"
|
||
fi
|
||
|
||
# Check for domain-specific rules
|
||
domain_rules=(
|
||
"audio-processing.mdc"
|
||
"database-registry.mdc"
|
||
"real-file-testing.mdc"
|
||
"protocol-services.mdc"
|
||
)
|
||
|
||
echo
|
||
echo "🎯 Domain-Specific Rules:"
|
||
for rule in "${domain_rules[@]}"; do
|
||
if [[ -f "$RULES_DIR/$rule" ]]; then
|
||
echo "✅ $rule"
|
||
else
|
||
echo "❌ $rule"
|
||
fi
|
||
done
|
||
|
||
# Check rule quality
|
||
echo
|
||
echo "🔍 Rule Quality Check:"
|
||
echo "---------------------"
|
||
|
||
for rule_file in "$RULES_DIR"/*.mdc; do
|
||
if [[ -f "$rule_file" ]]; then
|
||
rule_name=$(basename "$rule_file")
|
||
lines=$(wc -l < "$rule_file")
|
||
|
||
# Check for required sections
|
||
has_frontmatter=$(grep -c "^---" "$rule_file" || echo "0")
|
||
has_description=$(grep -c "description:" "$rule_file" || echo "0")
|
||
has_examples=$(grep -c "```" "$rule_file" || echo "0")
|
||
|
||
if [[ $has_frontmatter -ge 2 && $has_description -gt 0 ]]; then
|
||
echo "✅ $rule_name ($lines lines)"
|
||
else
|
||
echo "⚠️ $rule_name ($lines lines) - missing frontmatter"
|
||
fi
|
||
fi
|
||
done
|
||
}
|
||
|
||
# Function to generate rules
|
||
generate_rules() {
|
||
local directories=("$@")
|
||
local rule_type="${RULE_TYPE:-generic}"
|
||
local force_flag=""
|
||
|
||
if [[ "$FORCE" == "true" ]]; then
|
||
force_flag="--force"
|
||
fi
|
||
|
||
print_info "Generating Cursor rules..."
|
||
print_info "Rule type: $rule_type"
|
||
print_info "Directories: ${directories[*]}"
|
||
|
||
# Change to project root
|
||
cd "$PROJECT_ROOT"
|
||
|
||
# Run the Python generator
|
||
if [[ "$VERBOSE" == "true" ]]; then
|
||
python3 "$GENERATOR_SCRIPT" --verbose
|
||
else
|
||
python3 "$GENERATOR_SCRIPT"
|
||
fi
|
||
|
||
print_success "Rule generation completed!"
|
||
}
|
||
|
||
# Function to validate directories
|
||
validate_directories() {
|
||
local directories=("$@")
|
||
|
||
for dir in "${directories[@]}"; do
|
||
if [[ ! -d "$PROJECT_ROOT/$dir" ]]; then
|
||
print_error "Directory not found: $dir"
|
||
exit 1
|
||
fi
|
||
done
|
||
}
|
||
|
||
# Main script logic
|
||
main() {
|
||
# Parse command line arguments
|
||
GENERATE=false
|
||
ANALYZE=false
|
||
RULE_TYPE="generic"
|
||
FORCE=false
|
||
VERBOSE=false
|
||
DIRECTORIES=()
|
||
|
||
while [[ $# -gt 0 ]]; do
|
||
case $1 in
|
||
-h|--help)
|
||
show_usage
|
||
exit 0
|
||
;;
|
||
-a|--analyze)
|
||
ANALYZE=true
|
||
shift
|
||
;;
|
||
-g|--generate)
|
||
GENERATE=true
|
||
shift
|
||
;;
|
||
-t|--type)
|
||
RULE_TYPE="$2"
|
||
shift 2
|
||
;;
|
||
-f|--force)
|
||
FORCE=true
|
||
shift
|
||
;;
|
||
-v|--verbose)
|
||
VERBOSE=true
|
||
shift
|
||
;;
|
||
-*)
|
||
print_error "Unknown option: $1"
|
||
show_usage
|
||
exit 1
|
||
;;
|
||
*)
|
||
DIRECTORIES+=("$1")
|
||
shift
|
||
;;
|
||
esac
|
||
done
|
||
|
||
# Check dependencies
|
||
check_dependencies
|
||
|
||
# Default behavior if no action specified
|
||
if [[ "$GENERATE" == "false" && "$ANALYZE" == "false" ]]; then
|
||
if [[ ${#DIRECTORIES[@]} -gt 0 ]]; then
|
||
GENERATE=true
|
||
else
|
||
ANALYZE=true
|
||
fi
|
||
fi
|
||
|
||
# Validate rule type
|
||
case "$RULE_TYPE" in
|
||
python|javascript|testing|generic)
|
||
;;
|
||
*)
|
||
print_error "Invalid rule type: $RULE_TYPE"
|
||
print_info "Valid types: python, javascript, testing, generic"
|
||
exit 1
|
||
;;
|
||
esac
|
||
|
||
# Execute requested actions
|
||
if [[ "$ANALYZE" == "true" ]]; then
|
||
analyze_rules
|
||
fi
|
||
|
||
if [[ "$GENERATE" == "true" ]]; then
|
||
if [[ ${#DIRECTORIES[@]} -eq 0 ]]; then
|
||
print_warning "No directories specified, using defaults: src tests scripts"
|
||
DIRECTORIES=("src" "tests" "scripts")
|
||
fi
|
||
|
||
validate_directories "${DIRECTORIES[@]}"
|
||
generate_rules "${DIRECTORIES[@]}"
|
||
fi
|
||
|
||
print_success "Done!"
|
||
}
|
||
|
||
# Run main function with all arguments
|
||
main "$@"
|