src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/cmd/elvmdfmt/main.go (about) 1 // Command elvmdfmt reformats Markdown sources. 2 // 3 // This command is used to reformat all Markdown files in this repo; see the 4 // [contributor's manual] on how to use it. 5 // 6 // For general information about the Markdown implementation used by this 7 // command, see [src.elv.sh/pkg/md]. 8 // 9 // [contributor's manual]: https://github.com/elves/elvish/blob/master/CONTRIBUTING.md#formatting 10 package main 11 12 import ( 13 "flag" 14 "fmt" 15 "html" 16 "io" 17 "os" 18 19 "src.elv.sh/pkg/diff" 20 "src.elv.sh/pkg/md" 21 ) 22 23 var ( 24 overwrite = flag.Bool("w", false, "write result to source file (requires -fmt)") 25 showDiff = flag.Bool("d", false, "show diff") 26 width = flag.Int("width", 0, "if > 0, reflow content to width") 27 ) 28 29 func main() { 30 md.UnescapeHTML = html.UnescapeString 31 flag.Parse() 32 33 files := flag.Args() 34 if len(files) == 0 { 35 text, err := io.ReadAll(os.Stdin) 36 handleReadError("stdin", err) 37 result, unsupported := format(string(text)) 38 fmt.Print(result) 39 handleUnsupported("stdin", unsupported) 40 return 41 } 42 for _, file := range files { 43 textBytes, err := os.ReadFile(file) 44 handleReadError(file, err) 45 text := string(textBytes) 46 result, unsupported := format(text) 47 handleUnsupported(file, unsupported) 48 if *overwrite { 49 err := os.WriteFile(file, []byte(result), 0644) 50 if err != nil { 51 fmt.Fprintf(os.Stderr, "write %s: %v\n", file, err) 52 os.Exit(2) 53 } 54 } else if !*showDiff { 55 fmt.Print(result) 56 } 57 if *showDiff { 58 os.Stdout.Write(diff.Diff(file+".orig", text, file, result)) 59 } 60 } 61 } 62 63 func format(original string) (string, *md.FmtUnsupported) { 64 codec := &md.FmtCodec{Width: *width} 65 formatted := md.RenderString(original, codec) 66 return formatted, codec.Unsupported() 67 } 68 69 func handleReadError(name string, err error) { 70 if err != nil { 71 fmt.Fprintf(os.Stderr, "read %s: %v\n", name, err) 72 os.Exit(2) 73 } 74 } 75 76 func handleUnsupported(name string, u *md.FmtUnsupported) { 77 if u == nil { 78 return 79 } 80 if u.NestedEmphasisOrStrongEmphasis { 81 fmt.Fprintln(os.Stderr, name, "contains nested emphasis or strong emphasis") 82 } 83 if u.ConsecutiveEmphasisOrStrongEmphasis { 84 fmt.Fprintln(os.Stderr, name, "contains consecutive emphasis or strong emphasis") 85 } 86 os.Exit(2) 87 }