#!/usr/bin/env bash # Genera la base documental de un proyecto a partir de las plantillas de la skill. set -euo pipefail # bash >= 5.2 sustituye '&' del reemplazo por el patrón encontrado; lo desactivamos # para que los valores con '&' o '\' se inserten literales. shopt -u patsub_replacement 2>/dev/null || true SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" TEMPLATES_DIR="$SCRIPT_DIR/../templates" PROYECTO="" DESCRIPCION="" AUTOR="" DESTINO="" INIT_GIT=0 FORCE=0 DRY_RUN=0 FECHA_ISO="$(date +%Y-%m-%d)" uso() { cat <<'EOF' Uso: new-project.sh [opciones] Genera AGENTS.md, README.md, CHANGELOG.md, TODO.md, INSTALL.md y .gitignore. Opciones: -n, --nombre NOMBRE Nombre del proyecto (por defecto: nombre del directorio). -d, --descripcion TEXTO Descripción en una frase (por defecto: PENDIENTE). -a, --autor NOMBRE Autor (por defecto: git config user.name). -g, --git Inicializa un repositorio git en el destino. -f, --force Sobreescribe ficheros que ya existan. --dry-run Muestra lo que haría sin escribir nada. -h, --help Muestra esta ayuda. EOF } die() { printf 'error: %s\n' "$*" >&2; exit 1; } aviso() { printf 'aviso: %s\n' "$*" >&2; } while [[ $# -gt 0 ]]; do case "$1" in -n | --nombre) PROYECTO="${2:-}"; shift 2 ;; -d | --descripcion) DESCRIPCION="${2:-}"; shift 2 ;; -a | --autor) AUTOR="${2:-}"; shift 2 ;; -g | --git) INIT_GIT=1; shift ;; -f | --force) FORCE=1; shift ;; --dry-run) DRY_RUN=1; shift ;; -h | --help) uso; exit 0 ;; --) shift; break ;; -*) die "opción desconocida: $1 (usa --help)" ;; *) break ;; esac done [[ $# -ge 1 ]] || { uso >&2; exit 2; } DESTINO="$1" [[ $# -eq 1 ]] || die "solo se admite un directorio destino" [[ -d "$TEMPLATES_DIR" ]] || die "no encuentro las plantillas en $TEMPLATES_DIR" if [[ -z "$PROYECTO" ]]; then PROYECTO="$(basename -- "${DESTINO%/}")" fi [[ -n "$PROYECTO" ]] || die "no puedo deducir el nombre del proyecto; usa --nombre" if [[ -z "$DESCRIPCION" ]]; then DESCRIPCION="PENDIENTE: describir $PROYECTO en una frase." aviso "sin --descripcion; se deja un PENDIENTE en README.md y AGENTS.md" fi if [[ -z "$AUTOR" ]]; then AUTOR="$(git config user.name 2>/dev/null || true)" [[ -n "$AUTOR" ]] || AUTOR="PENDIENTE" fi FICHEROS=(AGENTS.md README.md CHANGELOG.md TODO.md INSTALL.md .gitignore) render() { local plantilla="$1" salida="$2" contenido contenido="$(<"$plantilla")" contenido="${contenido//'{{PROYECTO}}'/$PROYECTO}" contenido="${contenido//'{{DESCRIPCION}}'/$DESCRIPCION}" contenido="${contenido//'{{AUTOR}}'/$AUTOR}" contenido="${contenido//'{{FECHA}}'/$FECHA_ISO}" contenido="${contenido//'{{FECHA_ISO}}'/$FECHA_ISO}" printf '%s\n' "$contenido" > "$salida" } destino_abs="$(cd -- "$DESTINO" 2>/dev/null && pwd || true)" [[ -n "$destino_abs" ]] || destino_abs="$DESTINO" creados=() omitidos=() for fichero in "${FICHEROS[@]}"; do ruta="$DESTINO/$fichero" if [[ -e "$ruta" && $FORCE -eq 0 ]]; then omitidos+=("$fichero") aviso "$fichero ya existe; se omite (usa --force para sobreescribir)" continue fi if [[ $DRY_RUN -eq 1 ]]; then printf 'dry-run: escribiría %s\n' "$ruta" else mkdir -p -- "$DESTINO" render "$TEMPLATES_DIR/$fichero.tmpl" "$ruta" fi creados+=("$fichero") done if [[ $INIT_GIT -eq 1 && $DRY_RUN -eq 0 ]]; then if [[ -d "$DESTINO/.git" ]]; then aviso "$DESTINO ya es un repositorio git" else git -C "$DESTINO" init -q printf 'git: repositorio inicializado en %s\n' "$destino_abs" fi fi printf '\nproyecto: %s\n' "$PROYECTO" printf 'destino: %s\n' "$destino_abs" printf 'creados: %s\n' "${creados[*]:-ninguno}" [[ ${#omitidos[@]} -eq 0 ]] || printf 'omitidos: %s\n' "${omitidos[*]}" [[ $DRY_RUN -eq 1 ]] || printf 'siguiente: revisa README.md, INSTALL.md y las secciones PENDIENTE de AGENTS.md\n'