188 lines
5.0 KiB
Bash
Executable File
188 lines
5.0 KiB
Bash
Executable File
#!/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 <command> [args]
|
|
|
|
Commands:
|
|
init <project-name> Create a new project directory
|
|
list List all projects
|
|
clean <project-name> Remove build artifacts (keep source)
|
|
info <project-name> 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" <<SCAD
|
|
// ============================================
|
|
// Project: $name
|
|
// Description: TODO
|
|
// Author: Claude Code + User
|
|
// ============================================
|
|
|
|
// --- Parameters (user-configurable) ---
|
|
width = 50; // [mm] overall width
|
|
height = 30; // [mm] overall height
|
|
depth = 20; // [mm] overall depth
|
|
wall = 2.0; // [mm] wall thickness
|
|
tolerance = 0.3; // [mm] printer tolerance
|
|
|
|
// --- Rendering quality ---
|
|
\$fn = 64; // curve smoothness (use 128+ for final export)
|
|
|
|
// --- Derived dimensions ---
|
|
inner_width = width - 2 * wall;
|
|
inner_height = height - 2 * wall;
|
|
inner_depth = depth - 2 * wall;
|
|
|
|
// --- Debug output ---
|
|
echo(str("BBOX: ", width, " x ", depth, " x ", height, " mm"));
|
|
echo(str("Wall: ", wall, " mm | Tolerance: ", tolerance, " mm"));
|
|
|
|
// --- Main Assembly ---
|
|
// TODO: Replace with your design
|
|
example();
|
|
|
|
module example() {
|
|
difference() {
|
|
cube([width, depth, height], center = true);
|
|
translate([0, 0, wall])
|
|
cube([inner_width, inner_depth, inner_height + wall], center = true);
|
|
}
|
|
}
|
|
SCAD
|
|
|
|
# Create a project README
|
|
cat > "$project_dir/README.md" <<EOF
|
|
# $name
|
|
|
|
OpenSCAD project created $(date +%Y-%m-%d).
|
|
|
|
## Structure
|
|
- \`src/\` — OpenSCAD source files (.scad)
|
|
- \`output/\` — Exported STL, 3MF files
|
|
- \`previews/\` — Rendered PNG previews
|
|
|
|
## Quick Commands
|
|
\`\`\`bash
|
|
# Preview
|
|
bash ~/.claude/skills/openscad/scripts/openscad-render.sh preview src/main.scad
|
|
|
|
# Export STL
|
|
bash ~/.claude/skills/openscad/scripts/openscad-render.sh stl src/main.scad
|
|
|
|
# With custom parameters
|
|
bash ~/.claude/skills/openscad/scripts/openscad-render.sh stl src/main.scad -D 'width=60' -D 'height=40'
|
|
\`\`\`
|
|
EOF
|
|
|
|
echo "Project created: $project_dir"
|
|
echo ""
|
|
echo "Structure:"
|
|
echo " $project_dir/"
|
|
echo " ├── src/"
|
|
echo " │ └── main.scad (starter template)"
|
|
echo " ├── output/"
|
|
echo " ├── previews/"
|
|
echo " └── README.md"
|
|
}
|
|
|
|
cmd_list() {
|
|
if [[ ! -d "$PROJECTS_ROOT" ]]; then
|
|
echo "No projects directory found at $PROJECTS_ROOT"
|
|
exit 0
|
|
fi
|
|
|
|
echo "OpenSCAD Projects in $PROJECTS_ROOT:"
|
|
echo ""
|
|
|
|
for dir in "$PROJECTS_ROOT"/*/; do
|
|
[[ ! -d "$dir" ]] && continue
|
|
local name
|
|
name="$(basename "$dir")"
|
|
local scad_count
|
|
scad_count=$(find "$dir/src" -name "*.scad" 2>/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
|