implement a multi-file template interpreter

This commit is contained in:
2025-09-05 01:46:26 -06:00
parent 0bccd28134
commit 88d757546a
25 changed files with 1525 additions and 1 deletions

View File

@ -11,6 +11,7 @@ func main() {
commands := []*cli.Command{
createCmd(),
generateCmd(),
generateMultiCmd(), // New command for multi-file template generation
webappCmd(),
tailwindCmd(),
setupCmd(),

View File

@ -664,3 +664,133 @@ func templateCmd() *cli.Command {
},
}
}
func generateMultiCmd() *cli.Command {
return &cli.Command{
Name: "generate-multi",
Aliases: []string{"gen-multi"},
Usage: "Generate multiple files using a template manifest",
Description: "This command parses a Masonry file and applies a template manifest to generate multiple output files with per-item iteration support.",
Category: "generator",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "input",
Usage: "Path to the Masonry input file",
Required: true,
Aliases: []string{"i"},
},
&cli.StringFlag{
Name: "template-dir",
Usage: "Path to the directory containing template files",
Required: true,
Aliases: []string{"d"},
},
&cli.StringFlag{
Name: "manifest",
Usage: "Name of the manifest file (defaults to manifest.yaml)",
Value: "manifest.yaml",
Aliases: []string{"m"},
},
&cli.StringFlag{
Name: "output-dir",
Usage: "Output directory for generated files (defaults to ./generated)",
Value: "./generated",
Aliases: []string{"o"},
},
&cli.BoolFlag{
Name: "dry-run",
Usage: "Show what files would be generated without writing them",
Value: false,
},
&cli.BoolFlag{
Name: "clean",
Usage: "Clean output directory before generating files",
Value: false,
},
},
Action: func(c *cli.Context) error {
inputFile := c.String("input")
templateDir := c.String("template-dir")
manifestFile := c.String("manifest")
outputDir := c.String("output-dir")
dryRun := c.Bool("dry-run")
clean := c.Bool("clean")
// Validate input files exist
if _, err := os.Stat(inputFile); os.IsNotExist(err) {
return fmt.Errorf("input file does not exist: %s", inputFile)
}
if _, err := os.Stat(templateDir); os.IsNotExist(err) {
return fmt.Errorf("template directory does not exist: %s", templateDir)
}
manifestPath := filepath.Join(templateDir, manifestFile)
if _, err := os.Stat(manifestPath); os.IsNotExist(err) {
return fmt.Errorf("manifest file does not exist: %s", manifestPath)
}
fmt.Printf("Processing multi-file generation...\n")
fmt.Printf("Input: %s\n", inputFile)
fmt.Printf("Template Dir: %s\n", templateDir)
fmt.Printf("Manifest: %s\n", manifestFile)
fmt.Printf("Output Dir: %s\n", outputDir)
// Clean output directory if requested
if clean && !dryRun {
if _, err := os.Stat(outputDir); !os.IsNotExist(err) {
fmt.Printf("Cleaning output directory: %s\n", outputDir)
err := os.RemoveAll(outputDir)
if err != nil {
return fmt.Errorf("error cleaning output directory: %w", err)
}
}
}
// Create template interpreter
templateInterpreter := interpreter.NewTemplateInterpreter()
// Generate multiple files using manifest
outputs, err := templateInterpreter.InterpretToFiles(inputFile, templateDir, manifestFile)
if err != nil {
return fmt.Errorf("error generating files: %w", err)
}
if len(outputs) == 0 {
fmt.Println("No files were generated (check your manifest conditions)")
return nil
}
fmt.Printf("Generated %d file(s):\n", len(outputs))
if dryRun {
// Dry run - just show what would be generated
for filePath, content := range outputs {
fmt.Printf(" [DRY-RUN] %s (%d bytes)\n", filePath, len(content))
}
return nil
}
// Write all output files
for filePath, content := range outputs {
fullPath := filepath.Join(outputDir, filePath)
// Create directory if it doesn't exist
dir := filepath.Dir(fullPath)
err := os.MkdirAll(dir, 0755)
if err != nil {
return fmt.Errorf("error creating directory %s: %w", dir, err)
}
// Write file
err = os.WriteFile(fullPath, []byte(content), 0644)
if err != nil {
return fmt.Errorf("error writing file %s: %w", fullPath, err)
}
fmt.Printf(" Generated: %s\n", fullPath)
}
fmt.Printf("Successfully generated %d file(s) in %s\n", len(outputs), outputDir)
return nil
},
}
}