#!/usr/bin/env bash # openscad-project.sh — Project scaffolding and management for OpenSCAD skill set -euo pipefail PROJECTS_ROOT="$HOME/openscad-projects" usage() { cat <<'EOF' Usage: openscad-project.sh [args] Commands: init Create a new project directory list List all projects clean Remove build artifacts (keep source) info Show project info and file listing EOF exit 1 } cmd_init() { local name="$1" # Sanitize project name to prevent directory traversal if [[ ! "$name" =~ ^[a-zA-Z0-9_-]+$ ]]; then echo "ERROR: Project name must contain only letters, numbers, hyphens, and underscores." >&2 exit 1 fi local project_dir="$PROJECTS_ROOT/$name" if [[ -d "$project_dir" ]]; then echo "Project already exists: $project_dir" echo "Use existing project or choose a different name." exit 1 fi mkdir -p "$project_dir"/{src,output,previews} # Create a starter main.scad (name injected directly, no sed needed) cat > "$project_dir/src/main.scad" < "$project_dir/README.md" </dev/null | wc -l | tr -d ' ') local stl_count stl_count=$(find "$dir/output" -name "*.stl" 2>/dev/null | wc -l | tr -d ' ') local preview_count preview_count=$(find "$dir/previews" -name "*.png" 2>/dev/null | wc -l | tr -d ' ') echo " $name — ${scad_count} .scad, ${stl_count} .stl, ${preview_count} previews" done } cmd_clean() { local name="$1" local project_dir="$PROJECTS_ROOT/$name" if [[ ! -d "$project_dir" ]]; then echo "Project not found: $name" exit 1 fi rm -rf "${project_dir:?}/output/"* rm -rf "${project_dir:?}/previews/"* echo "Cleaned build artifacts for: $name" } cmd_info() { local name="$1" local project_dir="$PROJECTS_ROOT/$name" if [[ ! -d "$project_dir" ]]; then echo "Project not found: $name" exit 1 fi echo "Project: $name" echo "Path: $project_dir" echo "" echo "Source files:" find "$project_dir/src" -name "*.scad" -exec echo " {}" \; 2>/dev/null echo "" echo "Exports:" find "$project_dir/output" -type f -exec echo " {}" \; 2>/dev/null || echo " (none)" echo "" echo "Previews:" find "$project_dir/previews" -name "*.png" -exec echo " {}" \; 2>/dev/null || echo " (none)" } # --- Main --- [[ $# -lt 1 ]] && usage command="$1" shift case "$command" in init) [[ $# -lt 1 ]] && usage; cmd_init "$1" ;; list) cmd_list ;; clean) [[ $# -lt 1 ]] && usage; cmd_clean "$1" ;; info) [[ $# -lt 1 ]] && usage; cmd_info "$1" ;; *) echo "Unknown command: $command"; usage ;; esac