package cmd import ( "fmt" "io" "os" "github.com/spf13/cobra" "sourcecraft.dev/bigbes/confluence-md-utilities/format" ) var ( fmtOutput string fmtIndent string fmtColor string ) var fmtCmd = &cobra.Command{ Use: "fmt [input.xml]", Short: "Pretty-print Confluence storage XML", Long: `Format Confluence storage XML with sensible indentation. Block elements (p, h1-h6, ul, ol, li, table, tr, td, th, macros, layout) get their own lines with indentation. Inline elements (strong, em, code, a, ac:link, ac:image) stay on the same line. CDATA content inside code blocks is preserved as-is. Syntax highlighting is enabled by default when outputting to a terminal. Reads from stdin if no file is specified.`, Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { var input []byte var err error if len(args) > 0 { input, err = os.ReadFile(args[0]) } else { input, err = io.ReadAll(os.Stdin) } if err != nil { return fmt.Errorf("reading input: %w", err) } result := format.PrettyXML(string(input), fmtIndent) useColor := resolveColor(fmtColor, fmtOutput) if useColor { result = format.Colorize(result) } if fmtOutput != "" { return os.WriteFile(fmtOutput, []byte(result), 0644) } fmt.Print(result) return nil }, } func init() { fmtCmd.Flags().StringVarP(&fmtOutput, "output", "o", "", "Output file (default: stdout)") fmtCmd.Flags().StringVar(&fmtIndent, "indent", " ", "Indentation string (default: 2 spaces)") fmtCmd.Flags().StringVar(&fmtColor, "color", "auto", "Colorize output: auto, force, disabled") _ = fmtCmd.RegisterFlagCompletionFunc("color", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{"auto", "force", "disabled"}, cobra.ShellCompDirectiveNoFileComp }) rootCmd.AddCommand(fmtCmd) } func resolveColor(mode string, outputFile string) bool { switch mode { case "force": return true case "disabled": return false default: // "auto" if outputFile != "" { return false } return isTerminal(os.Stdout) } } func isTerminal(f *os.File) bool { stat, err := f.Stat() if err != nil { return false } return (stat.Mode() & os.ModeCharDevice) != 0 }