Wire it to a cobra CLI¶
The core output package takes an io.Writer and a Format — it knows nothing
about cobra. The opt-in output/cobra subpackage is the thin bridge: it reads
the --output flag and the command's writer off a *cobra.Command and hands them
to a core Renderer.
Importing the core never pulls cobra into your dependency graph; only importing this subpackage does.
Register the flag once¶
On your root command, so every subcommand inherits a consistently-defined flag:
ocobra.RegisterOutputFlag(rootCmd)
// adds: --output (default "text", values: text, json, yaml, csv, tsv, markdown)
Build a Renderer from the command¶
Inside a RunE, NewRenderer wires the writer (cmd.OutOrStdout()) and the
format (the --output value):
RunE: func(cmd *cobra.Command, args []string) error {
r := ocobra.NewRenderer(cmd)
result, err := doWork()
if err != nil {
_ = r.EmitError("update", err) // JSON envelope in json mode; no-op otherwise
return err
}
if r.IsJSON() {
return r.Emit(output.Response{
Status: output.StatusSuccess, Command: "update", Data: result,
})
}
fmt.Fprintf(cmd.OutOrStdout(), "Updated to %s\n", result.Version)
return nil
},
You can pass extra core options after the command — they apply last, so a theme or an explicit writer override composes cleanly:
The whole surface¶
| Function | Purpose |
|---|---|
RegisterOutputFlag(cmd) |
define the persistent --output flag |
Format(cmd) output.Format |
read the flag (default text) |
IsJSONOutput(cmd) bool |
is --output json? |
NewRenderer(cmd, opts...) *output.Renderer |
build a Renderer from the command |
Emit(cmd, resp) / EmitError(cmd, command, err) |
envelope sugar |
Not using cobra? Skip the subpackage and call output.New(...) directly with your
own writer and format — the same Renderer, from a urfave/cli app, an HTTP
handler, or a test.