Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 09:04:14 +08:00
commit 70c36b5eff
248 changed files with 47482 additions and 0 deletions

View File

@@ -0,0 +1,334 @@
#!/bin/bash
#
# generate-click-cli.sh - Generate Click CLI project structure
#
# Usage: generate-click-cli.sh <project-name> [cli-type]
# cli-type: basic, nested, or advanced (default: basic)
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Function to print colored output
print_info() { echo -e "${CYAN}${NC} $1"; }
print_success() { echo -e "${GREEN}${NC} $1"; }
print_error() { echo -e "${RED}${NC} $1" >&2; }
print_warning() { echo -e "${YELLOW}${NC} $1"; }
# Validate arguments
if [ $# -lt 1 ]; then
print_error "Usage: $0 <project-name> [cli-type]"
echo " cli-type: basic, nested, or advanced (default: basic)"
exit 1
fi
PROJECT_NAME="$1"
CLI_TYPE="${2:-basic}"
# Validate CLI type
if [[ ! "$CLI_TYPE" =~ ^(basic|nested|advanced)$ ]]; then
print_error "Invalid CLI type: $CLI_TYPE"
echo " Valid types: basic, nested, advanced"
exit 1
fi
# Validate project name
if [[ ! "$PROJECT_NAME" =~ ^[a-z0-9_-]+$ ]]; then
print_error "Invalid project name: $PROJECT_NAME"
echo " Must contain only lowercase letters, numbers, hyphens, and underscores"
exit 1
fi
# Create project directory
if [ -d "$PROJECT_NAME" ]; then
print_error "Directory already exists: $PROJECT_NAME"
exit 1
fi
print_info "Creating Click CLI project: $PROJECT_NAME (type: $CLI_TYPE)"
# Create directory structure
mkdir -p "$PROJECT_NAME"/{src,tests,docs}
# Determine which template to use
SKILL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
TEMPLATE_FILE=""
case "$CLI_TYPE" in
basic)
TEMPLATE_FILE="$SKILL_DIR/templates/basic-cli.py"
;;
nested)
TEMPLATE_FILE="$SKILL_DIR/templates/nested-commands.py"
;;
advanced)
# For advanced, use nested as base with validators
TEMPLATE_FILE="$SKILL_DIR/templates/nested-commands.py"
;;
esac
# Copy template
if [ ! -f "$TEMPLATE_FILE" ]; then
print_error "Template file not found: $TEMPLATE_FILE"
exit 1
fi
cp "$TEMPLATE_FILE" "$PROJECT_NAME/src/cli.py"
print_success "Created src/cli.py from template"
# Copy validators if advanced type
if [ "$CLI_TYPE" = "advanced" ]; then
VALIDATORS_FILE="$SKILL_DIR/templates/validators.py"
if [ -f "$VALIDATORS_FILE" ]; then
cp "$VALIDATORS_FILE" "$PROJECT_NAME/src/validators.py"
print_success "Created src/validators.py"
fi
fi
# Create __init__.py
cat > "$PROJECT_NAME/src/__init__.py" <<'EOF'
"""
CLI application package
"""
from .cli import cli
__version__ = "1.0.0"
__all__ = ["cli"]
EOF
print_success "Created src/__init__.py"
# Create requirements.txt
cat > "$PROJECT_NAME/requirements.txt" <<'EOF'
click>=8.0.0
rich>=13.0.0
EOF
print_success "Created requirements.txt"
# Create setup.py
cat > "$PROJECT_NAME/setup.py" <<EOF
from setuptools import setup, find_packages
setup(
name="${PROJECT_NAME}",
version="1.0.0",
packages=find_packages(),
install_requires=[
"click>=8.0.0",
"rich>=13.0.0",
],
entry_points={
"console_scripts": [
"${PROJECT_NAME}=src.cli:cli",
],
},
python_requires=">=3.8",
)
EOF
print_success "Created setup.py"
# Create pyproject.toml
cat > "$PROJECT_NAME/pyproject.toml" <<EOF
[build-system]
requires = ["setuptools>=45", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "${PROJECT_NAME}"
version = "1.0.0"
description = "A Click-based CLI tool"
requires-python = ">=3.8"
dependencies = [
"click>=8.0.0",
"rich>=13.0.0",
]
[project.scripts]
${PROJECT_NAME} = "src.cli:cli"
EOF
print_success "Created pyproject.toml"
# Create README.md
cat > "$PROJECT_NAME/README.md" <<EOF
# ${PROJECT_NAME}
A CLI tool built with Click framework.
## Installation
\`\`\`bash
pip install -e .
\`\`\`
## Usage
\`\`\`bash
# Show help
${PROJECT_NAME} --help
# Run command
${PROJECT_NAME} <command>
\`\`\`
## Development
\`\`\`bash
# Install in development mode
pip install -e .
# Run tests
pytest tests/
# Format code
black src/ tests/
# Lint code
pylint src/ tests/
\`\`\`
## Project Structure
\`\`\`
${PROJECT_NAME}/
├── src/
│ ├── __init__.py
│ └── cli.py # Main CLI implementation
├── tests/
│ └── test_cli.py # Unit tests
├── docs/
│ └── usage.md # Usage documentation
├── requirements.txt # Dependencies
├── setup.py # Setup configuration
└── README.md # This file
\`\`\`
## License
MIT
EOF
print_success "Created README.md"
# Create basic test file
cat > "$PROJECT_NAME/tests/test_cli.py" <<'EOF'
import pytest
from click.testing import CliRunner
from src.cli import cli
def test_cli_help():
"""Test CLI help output"""
runner = CliRunner()
result = runner.invoke(cli, ['--help'])
assert result.exit_code == 0
assert 'Usage:' in result.output
def test_cli_version():
"""Test CLI version output"""
runner = CliRunner()
result = runner.invoke(cli, ['--version'])
assert result.exit_code == 0
assert '1.0.0' in result.output
EOF
print_success "Created tests/test_cli.py"
# Create .gitignore
cat > "$PROJECT_NAME/.gitignore" <<'EOF'
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# Virtual environments
venv/
ENV/
env/
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# Testing
.pytest_cache/
.coverage
htmlcov/
# Environment
.env
.env.local
EOF
print_success "Created .gitignore"
# Create usage documentation
cat > "$PROJECT_NAME/docs/usage.md" <<EOF
# ${PROJECT_NAME} Usage Guide
## Installation
Install the CLI tool:
\`\`\`bash
pip install -e .
\`\`\`
## Commands
### Help
Show available commands:
\`\`\`bash
${PROJECT_NAME} --help
\`\`\`
### Version
Show version information:
\`\`\`bash
${PROJECT_NAME} --version
\`\`\`
## Examples
Add specific examples for your CLI commands here.
EOF
print_success "Created docs/usage.md"
# Print summary
echo ""
print_success "Click CLI project created successfully!"
echo ""
print_info "Next steps:"
echo " 1. cd $PROJECT_NAME"
echo " 2. python -m venv venv"
echo " 3. source venv/bin/activate"
echo " 4. pip install -e ."
echo " 5. $PROJECT_NAME --help"
echo ""
print_info "Project type: $CLI_TYPE"
print_info "Location: $(pwd)/$PROJECT_NAME"

View File

@@ -0,0 +1,108 @@
#!/bin/bash
#
# setup-click-project.sh - Setup Click project dependencies and environment
#
# Usage: setup-click-project.sh [project-directory]
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Function to print colored output
print_info() { echo -e "${CYAN}${NC} $1"; }
print_success() { echo -e "${GREEN}${NC} $1"; }
print_error() { echo -e "${RED}${NC} $1" >&2; }
print_warning() { echo -e "${YELLOW}${NC} $1"; }
PROJECT_DIR="${1:-.}"
print_info "Setting up Click project in: $PROJECT_DIR"
# Check if Python is installed
if ! command -v python3 &> /dev/null; then
print_error "Python 3 is not installed"
exit 1
fi
PYTHON_VERSION=$(python3 --version | cut -d' ' -f2)
print_success "Python $PYTHON_VERSION detected"
# Navigate to project directory
cd "$PROJECT_DIR"
# Check if virtual environment exists
if [ ! -d "venv" ]; then
print_info "Creating virtual environment..."
python3 -m venv venv
print_success "Virtual environment created"
else
print_info "Virtual environment already exists"
fi
# Activate virtual environment
print_info "Activating virtual environment..."
source venv/bin/activate
# Upgrade pip
print_info "Upgrading pip..."
pip install --upgrade pip > /dev/null 2>&1
print_success "pip upgraded"
# Install Click and dependencies
print_info "Installing Click and dependencies..."
if [ -f "requirements.txt" ]; then
pip install -r requirements.txt
print_success "Installed from requirements.txt"
else
pip install click rich
print_success "Installed click and rich"
fi
# Install development dependencies
print_info "Installing development dependencies..."
pip install pytest pytest-cov black pylint mypy
print_success "Development dependencies installed"
# Create .env.example if it doesn't exist
if [ ! -f ".env.example" ]; then
cat > .env.example <<'EOF'
# Environment variables for CLI
API_KEY=your_api_key_here
DEBUG=false
LOG_LEVEL=info
EOF
print_success "Created .env.example"
fi
# Setup pre-commit hooks if git repo
if [ -d ".git" ]; then
print_info "Setting up git hooks..."
cat > .git/hooks/pre-commit <<'EOF'
#!/bin/bash
# Run tests before commit
source venv/bin/activate
black src/ tests/ --check || exit 1
pylint src/ || exit 1
pytest tests/ || exit 1
EOF
chmod +x .git/hooks/pre-commit
print_success "Git hooks configured"
fi
# Verify installation
print_info "Verifying installation..."
python3 -c "import click; print(f'Click version: {click.__version__}')"
print_success "Click is properly installed"
echo ""
print_success "Setup completed successfully!"
echo ""
print_info "Next steps:"
echo " 1. source venv/bin/activate"
echo " 2. python src/cli.py --help"
echo " 3. pytest tests/"

View File

@@ -0,0 +1,162 @@
#!/bin/bash
#
# validate-click.sh - Validate Click CLI implementation
#
# Usage: validate-click.sh <cli-file.py>
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Function to print colored output
print_info() { echo -e "${CYAN}${NC} $1"; }
print_success() { echo -e "${GREEN}${NC} $1"; }
print_error() { echo -e "${RED}${NC} $1" >&2; }
print_warning() { echo -e "${YELLOW}${NC} $1"; }
# Validate arguments
if [ $# -lt 1 ]; then
print_error "Usage: $0 <cli-file.py>"
exit 1
fi
CLI_FILE="$1"
# Check if file exists
if [ ! -f "$CLI_FILE" ]; then
print_error "File not found: $CLI_FILE"
exit 1
fi
print_info "Validating Click CLI: $CLI_FILE"
echo ""
VALIDATION_PASSED=true
# Check 1: File is a Python file
if [[ ! "$CLI_FILE" =~ \.py$ ]]; then
print_error "File must be a Python file (.py)"
VALIDATION_PASSED=false
else
print_success "File extension is valid (.py)"
fi
# Check 2: File imports Click
if grep -q "import click" "$CLI_FILE"; then
print_success "Click module is imported"
else
print_error "Click module is not imported"
VALIDATION_PASSED=false
fi
# Check 3: Has at least one Click decorator
DECORATOR_COUNT=$(grep -c "@click\." "$CLI_FILE" || true)
if [ "$DECORATOR_COUNT" -gt 0 ]; then
print_success "Found $DECORATOR_COUNT Click decorator(s)"
else
print_error "No Click decorators found"
VALIDATION_PASSED=false
fi
# Check 4: Has main entry point or group
if grep -q "@click.command()\|@click.group()" "$CLI_FILE"; then
print_success "Has Click command or group decorator"
else
print_error "Missing @click.command() or @click.group()"
VALIDATION_PASSED=false
fi
# Check 5: Has if __name__ == '__main__' block
if grep -q "if __name__ == '__main__':" "$CLI_FILE"; then
print_success "Has main execution block"
else
print_warning "Missing main execution block (if __name__ == '__main__':)"
fi
# Check 6: Python syntax is valid
if python3 -m py_compile "$CLI_FILE" 2>/dev/null; then
print_success "Python syntax is valid"
else
print_error "Python syntax errors detected"
VALIDATION_PASSED=false
fi
# Check 7: Has help text
if grep -q '"""' "$CLI_FILE"; then
print_success "Contains docstrings/help text"
else
print_warning "No docstrings found (recommended for help text)"
fi
# Check 8: Has option or argument decorators
if grep -q "@click.option\|@click.argument" "$CLI_FILE"; then
print_success "Has options or arguments defined"
else
print_warning "No options or arguments defined"
fi
# Check 9: Uses recommended patterns
echo ""
print_info "Checking best practices..."
# Check for version option
if grep -q "@click.version_option" "$CLI_FILE"; then
print_success "Has version option"
else
print_warning "Consider adding @click.version_option()"
fi
# Check for help parameter
if grep -q "help=" "$CLI_FILE"; then
print_success "Uses help parameters"
else
print_warning "Consider adding help text to options"
fi
# Check for context usage
if grep -q "@click.pass_context" "$CLI_FILE"; then
print_success "Uses context for state sharing"
else
print_info "No context usage detected (optional)"
fi
# Check for command groups
if grep -q "@click.group()" "$CLI_FILE"; then
print_success "Uses command groups"
# Check for subcommands
SUBCOMMAND_COUNT=$(grep -c "\.command()" "$CLI_FILE" || true)
if [ "$SUBCOMMAND_COUNT" -gt 0 ]; then
print_success "Has $SUBCOMMAND_COUNT subcommand(s)"
fi
fi
# Check for validation
if grep -q "click.Choice\|click.IntRange\|click.FloatRange\|click.Path" "$CLI_FILE"; then
print_success "Uses Click's built-in validators"
else
print_info "No built-in validators detected (optional)"
fi
# Check for colored output (Rich or Click's styling)
if grep -q "from rich\|click.style\|click.echo.*fg=" "$CLI_FILE"; then
print_success "Uses colored output"
else
print_info "No colored output detected (optional)"
fi
# Summary
echo ""
if [ "$VALIDATION_PASSED" = true ]; then
print_success "All critical validations passed!"
echo ""
print_info "Try running: python3 $CLI_FILE --help"
exit 0
else
print_error "Validation failed. Please fix the errors above."
exit 1
fi