cmd/tilstream/cmd/new.go

package cmd

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/spf13/cobra"
)

var (
	newTitle string
	newDir   string
	newDraft bool
)

var newCmd = &cobra.Command{
	Use:   "new [slug]",
	Short: "Create a new TIL entry",
	Args:  cobra.ExactArgs(1),
	RunE:  runNew,
}

func init() {
	newCmd.Flags().StringVar(&newTitle, "title", "", "post title (defaults to slug)")
	newCmd.Flags().StringVar(&newDir, "dir", "content", "content directory")
	newCmd.Flags().BoolVar(&newDraft, "draft", false, "mark post as draft")
}

func runNew(cmd *cobra.Command, args []string) error {
	slug := strings.ToLower(args[0])
	slug = strings.ReplaceAll(slug, " ", "-")
	if slug == "" {
		return fmt.Errorf("empty slug")
	}
	title := newTitle
	if title == "" {
		title = titleFromSlug(slug)
	}
	if err := os.MkdirAll(newDir, 0o755); err != nil {
		return err
	}
	path := filepath.Join(newDir, slug+".md")
	if _, err := os.Stat(path); err == nil {
		return fmt.Errorf("%s already exists", path)
	}
	body := buildScaffold(title, newDraft)
	if err := os.WriteFile(path, []byte(body), 0o644); err != nil {
		return err
	}
	fmt.Printf("created %s\n", path)
	return nil
}

func titleFromSlug(slug string) string {
	parts := strings.Split(slug, "-")
	for i, p := range parts {
		if p == "" {
			continue
		}
		parts[i] = strings.ToUpper(p[:1]) + p[1:]
	}
	return strings.Join(parts, " ")
}

func buildScaffold(title string, draft bool) string {
	var b strings.Builder
	b.WriteString("---\n")
	fmt.Fprintf(&b, "title: %q\n", title)
	fmt.Fprintf(&b, "date: %s\n", time.Now().UTC().Format("2006-01-02"))
	b.WriteString("tags: []\n")
	if draft {
		b.WriteString("draft: true\n")
	}
	b.WriteString("---\n\n")
	b.WriteString("Write your TIL here.\n")
	return b.String()
}