Skip to content

Getting started

Install

go get gitlab.com/phpboyscout/go/output

Requires Go 1.26.5 or newer — that is the version declared in the module's go.mod, so an older toolchain refuses to build it.

The cobra binding lives in the output/cobra subpackage and is fetched by the same go get. cobra therefore appears in your module graph, but Go links only the packages you import, so a binary that never imports the subpackage never contains cobra — see framework-free core.

The Renderer

Everything starts with a Renderer, built once from options and reused. It holds four things: a destination writer, an output format, a theme, and whether output is interactive.

import "gitlab.com/phpboyscout/go/output"

r := output.New(
    output.WithWriter(os.Stdout),      // default: os.Stderr
    output.WithFormat(output.FormatText), // default: text
    // output.WithTheme(myTheme),      // default: DefaultTheme()
    // output.WithInteractive(true),   // default: auto-detected
)

If you do not call WithInteractive, the renderer auto-detects: interactive when stdout is a TTY and CI is not set to true. Interactive renderers animate; non-interactive ones print plain lines — the same code path works in a terminal and under CI.

Writing data

Write is format-aware. You supply the data and a function that renders the human-readable form; the renderer decides which to use:

type Result struct {
    Name    string `json:"name"    table:"Name,sortable"`
    Version string `json:"version" table:"Version"`
}

r := output.New(output.WithWriter(os.Stdout), output.WithFormat(format))

_ = r.Write(res, func(w io.Writer) {
    fmt.Fprintf(w, "%s %s\n", res.Name, res.Version)
})
Configured format What Write does
text calls your textFunc
json / yaml marshals data directly
csv / tsv / markdown renders data as a table (needs a slice)

Write calls Table with no options on that last row, so column definitions and sorting are not available through it — call Table directly when you need them. The full matrix is in behaviour by format.

Formats

The supported set is text, json, yaml, csv, tsv, markdown.

output.Formats()                 // the canonical slice, stable order
f, ok := output.ParseFormat(s)   // case-insensitive; ok=false → falls back to FormatText

ParseFormat lower-cases its input, so JSON, Json and json all parse to FormatJSON. An empty or unrecognised string returns (FormatText, false) — it never errors, so a typo silently produces text output unless you check ok.

Formats() is exactly the value set a CLI's --output flag should accept — see the cobra guide, which wires it up for you.

Your first table

rows := []Result{
    {Name: "alpha", Version: "1.2.0"},
    {Name: "beta",  Version: "0.9.1"},
}

r := output.New(output.WithWriter(os.Stdout), output.WithFormat(output.FormatText))
_ = r.Table(rows, output.WithSortBy("Name"))

Columns come from the table:"Header,sortable" struct tags, or pass output.WithColumns(...) explicitly (required for []map[string]any). More in Render a table.

Next