package main import ( "bytes" "flag" "fmt" "io" "os" "olexsmir.xyz/clerk/journal" "olexsmir.xyz/clerk/journal/printer" ) func runFormat(args []string) { fs := flag.NewFlagSet("format", flag.ExitOnError) write := fs.Bool("w", false, "Write result back to file instead of stdout") diff := fs.Bool("d", false, "Display diffs instead of rewriting files") check := fs.Bool("check", false, "Exit code 0 if already formatted, 1 otherwise") fs.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: clerk format [flags] [path ...]\n") fs.PrintDefaults() } fs.Parse(args) paths := fs.Args() // Read from stdin if no paths given if len(paths) == 0 { src, err := io.ReadAll(os.Stdin) if err != nil { fmt.Fprintf(os.Stderr, "error reading stdin: %v\n", err) os.Exit(1) } pf, err := journal.NewLoader().LoadBytes("stdin", src) if err != nil { fmt.Fprintf(os.Stderr, "parse error: %v\n", err) os.Exit(1) } var buf bytes.Buffer if err := printer.Fprint(&buf, pf.Ast); err != nil { fmt.Fprintf(os.Stderr, "format error: %v\n", err) os.Exit(1) } if *check { if bytes.Equal(src, buf.Bytes()) { os.Exit(0) } os.Exit(1) } os.Stdout.Write(buf.Bytes()) return } // Process each file exitCode := 0 for _, path := range paths { info, err := os.Stat(path) if err != nil { fmt.Fprintf(os.Stderr, "error: %s: %v\n", path, err) exitCode = 1 continue } if info.IsDir() { fmt.Fprintf(os.Stderr, "error: %s: can only format files, not directories\n", path) exitCode = 1 continue } src, err := os.ReadFile(path) if err != nil { fmt.Fprintf(os.Stderr, "error: %s: %v\n", path, err) exitCode = 1 continue } pf, err := journal.NewLoader().LoadBytes(path, src) if err != nil { fmt.Fprintf(os.Stderr, "error: %s: %v\n", path, err) exitCode = 1 continue } var buf bytes.Buffer if err := printer.Fprint(&buf, pf.Ast); err != nil { fmt.Fprintf(os.Stderr, "error: %s: %v\n", path, err) exitCode = 1 continue } formatted := buf.Bytes() if *check { if !bytes.Equal(src, formatted) { fmt.Fprintf(os.Stderr, "%s: not formatted\n", path) exitCode = 1 } continue } if *diff { diffLines(path, src, formatted) continue } if *write { if err := os.WriteFile(path, formatted, 0o644); err != nil { fmt.Fprintf(os.Stderr, "error: %s: %v\n", path, err) exitCode = 1 } } else { os.Stdout.Write(formatted) } } os.Exit(exitCode) } func diffLines(path string, src, formatted []byte) { // simple diff display if bytes.Equal(src, formatted) { return } fmt.Fprintf(os.Stderr, "--- %s\n+++ %s\n", path, path) // TODO: proper line-by-line diff }