github.com/grafana/tanka@v0.26.1-0.20240506093700-c22cfc35c21a/cmd/tk/fmt.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 8 "github.com/go-clix/cli" 9 "github.com/gobwas/glob" 10 "github.com/posener/complete" 11 12 "github.com/grafana/tanka/pkg/tanka" 13 ) 14 15 // ArgStdin is the "magic" argument for reading from stdin 16 const ArgStdin = "-" 17 18 func fmtCmd() *cli.Command { 19 cmd := &cli.Command{ 20 Use: "fmt <FILES|DIRECTORIES>", 21 Short: "format Jsonnet code", 22 Args: cli.Args{ 23 Validator: cli.ArgsMin(1), 24 Predictor: complete.PredictFiles("*.*sonnet"), 25 }, 26 } 27 28 stdout := cmd.Flags().Bool("stdout", false, "print formatted contents to stdout instead of writing to disk") 29 test := cmd.Flags().BoolP("test", "t", false, "exit with non-zero when changes would be made") 30 exclude := cmd.Flags().StringSliceP("exclude", "e", []string{"**/.*", ".*", "**/vendor/**", "vendor/**"}, "globs to exclude") 31 verbose := cmd.Flags().BoolP("verbose", "v", false, "print each checked file") 32 33 cmd.Run = func(cmd *cli.Command, args []string) error { 34 if len(args) == 1 && args[0] == ArgStdin { 35 return fmtStdin(*test) 36 } 37 38 globs := make([]glob.Glob, len(*exclude)) 39 for i, e := range *exclude { 40 g, err := glob.Compile(e) 41 if err != nil { 42 return err 43 } 44 globs[i] = g 45 } 46 47 var outFn tanka.OutFn 48 switch { 49 case *test: 50 outFn = func(name, content string) error { return nil } 51 case *stdout: 52 outFn = func(name, content string) error { 53 fmt.Printf("// %s\n%s", name, content) 54 fmt.Fprintln(os.Stderr) // some spacing 55 return nil 56 } 57 } 58 59 opts := &tanka.FormatOpts{ 60 Excludes: globs, 61 OutFn: outFn, 62 PrintNames: *verbose, 63 } 64 65 changed, err := tanka.FormatFiles(args, opts) 66 if err != nil { 67 return err 68 } 69 70 if *verbose { 71 fmt.Fprintln(os.Stderr) 72 } 73 74 switch { 75 case *test && len(changed) > 0: 76 fmt.Fprintln(os.Stderr, "The following files are not properly formatted:") 77 for _, s := range changed { 78 fmt.Fprintln(os.Stderr, s) 79 } 80 os.Exit(ExitStatusDiff) 81 case len(changed) == 0: 82 fmt.Fprintln(os.Stderr, "All discovered files are already formatted. No changes were made") 83 case len(changed) > 0: 84 fmt.Fprintf(os.Stderr, "Formatted %v files", len(changed)) 85 } 86 87 return nil 88 } 89 90 return cmd 91 } 92 93 func fmtStdin(test bool) error { 94 content, err := io.ReadAll(os.Stdin) 95 if err != nil { 96 return err 97 } 98 99 formatted, err := tanka.Format("<stdin>", string(content)) 100 if err != nil { 101 return err 102 } 103 104 fmt.Print(formatted) 105 if test && string(content) != formatted { 106 os.Exit(ExitStatusDiff) 107 } 108 return nil 109 }