Skip to content

Migration: pkg/outputgo/output

pkg/output has been extracted to the standalone module gitlab.com/phpboyscout/go/output (v0.1.0) and, unlike the earlier leaf extractions, redesigned at the same time. The scattered constructors collapse into a single configured Renderer (output.New(...)), and the cobra-specific helpers move to an opt-in subpackage so the core carries no CLI-framework dependency.

Add the dependencies:

go get gitlab.com/phpboyscout/go/[email protected]
# the cobra binding is a subpackage of the same module — no separate go get

Import the core, and (for cobra CLIs) the subpackage aliased to avoid the clash with spf13/cobra:

import (
    "gitlab.com/phpboyscout/go/output"
    ocobra "gitlab.com/phpboyscout/go/output/cobra"
)

The Renderer façade

Everything now hangs off one configured value. Build it once, reuse it; the writer, format, theme and interactivity are fixed at construction and every method reads them.

r := output.New(
    output.WithWriter(cmd.OutOrStdout()), // default os.Stderr
    output.WithFormat(format),            // default FormatText
    // output.WithTheme(t), output.WithInteractive(v)
)

Old → new mapping

Before (pkg/output) After (go/output)
output.NewWriter(w, f) output.New(output.WithWriter(w), output.WithFormat(f))
wr.Write(data, textFn) r.Write(data, textFn) (now also honours YAML/CSV/TSV/Markdown)
wr.Render(md) / wr.IsJSON() r.Render(md) / r.IsJSON()
output.NewTableWriter(w, f, opts...) + tw.WriteRows(rows) output.New(output.WithWriter(w), output.WithFormat(f)) + r.Table(rows, opts...)
output.NewStatus() output.New().Status()
output.NewProgress(total, desc) output.New().Progress(total, desc)
output.Spin(ctx, msg, fn) output.New().Spin(ctx, msg, fn)
output.SpinWithResult(ctx, msg, fn) output.SpinWithResult(output.New(), ctx, msg, fn)
output.IsJSONOutput(cmd) ocobra.IsJSONOutput(cmd)
output.Emit(cmd, resp) ocobra.Emit(cmd, resp) — or ocobra.NewRenderer(cmd).Emit(resp)
output.EmitError(cmd, name, err) ocobra.EmitError(cmd, name, err)

Unchanged: the Format type and constants, Response, the Status* constants, RenderMarkdown, Column, and the With* table options — all keep their names.

Why the cobra helpers moved

The old Emit/EmitError/IsJSONOutput took a *cobra.Command only to read the --output flag value and the command's writer — neither needs cobra. The core now takes plain values (io.Writer, Format), so importing go/output never pulls cobra or pflag into the graph (a depfootprint_test.go guard enforces this). The *cobra.Command → (writer, format) binding lives in go/output/cobra, imported only by tools that want it. That subpackage also offers NewRenderer(cmd) and RegisterOutputFlag(cmd).

Why it moved

output is a general-purpose CLI-output formatter with no framework weight beyond the terminal-rendering stack it intrinsically needs. Extracting it lets any tool reuse it without depending on go-tool-base, and the redesign gives it a coherent, format-complete API with its own release cadence and docs at output.go.phpboyscout.uk.