package cmd import ( "bufio" "bytes" "context" "fmt" "os" "path/filepath" "strings" "time" "edge-infra.dev/pkg/lib/cli/rags" "edge-infra.dev/pkg/lib/cli/sink" "edge-infra.dev/pkg/tools/dlog" ) // TODO: automatically increment based on last dlog (eg 0004 is biggest is 0003) // TODO: allow setting more pieces of frontmatter on create func newCreateCmd() *sink.Command { var ( dir, template string tags []string ) cmd := &sink.Command{ Use: "create [flags] ", Short: "Create decision logs from a template.", Flags: []*rags.Rag{ dirFlag(&dir), templateFlag(&template), { Name: "tags", Usage: "Comma separated list of tags to apply to new dlog. Can be provided multiple times", Value: &rags.StringSet{Var: &tags}, }, }, Exec: func(_ context.Context, r sink.Run) error { if len(r.Args()) != 1 { return fmt.Errorf("a name for the decision log file is required") } p := filepath.Join(dir, r.Args()[0]) _, err := os.Stat(p) if err == nil { return fmt.Errorf("%s already exists", p) } t, err := os.Open(template) if err != nil { return fmt.Errorf("failed to open template %s: %w", template, err) } return createDLog(p, t, time.Now(), tags) }, } return cmd } func createDLog(path string, t *os.File, d time.Time, tags []string) error { buf := new(bytes.Buffer) scanner := bufio.NewScanner(t) for scanner.Scan() { text := scanner.Text() // Cheat here by updating the frontmatter in string form to avoid // encoding roundtrip and losing comments in the template describing // frontmatter elements if strings.HasPrefix(text, "date:") { buf.WriteString(fmt.Sprintf("date: %s", dlog.Time{Time: d})) buf.WriteString("\n") continue } if len(tags) > 0 && strings.HasPrefix(text, "tags:") { buf.WriteString(fmt.Sprintf( "tags: [%s]", // Rebuild string for consistent spacing strings.Join(tags, ", ")), ) buf.WriteString("\n") continue } buf.WriteString(text) buf.WriteString("\n") } if scanner.Err() != nil { return fmt.Errorf("failed to read template %s: %w", t.Name(), scanner.Err()) } f, err := os.Create(path) if err != nil { return fmt.Errorf("failed to create %s: %w", path, err) } if _, err := buf.WriteTo(f); err != nil { return fmt.Errorf("failed to write %s: %w", path, err) } return nil }