output

package
v1.10.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 2, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

Package output provides structured output formatting, table rendering, and progress indicators for CLI commands.

Output Formats

Commands can produce output in multiple formats controlled by the --output flag. The Format type defines the supported formats: text (default), json, yaml, csv, tsv, and markdown.

The Response type provides a standard JSON envelope for all command output, and the Emit/EmitError helpers handle format-aware serialisation.

Table Rendering

TableWriter renders tabular data with automatic column sizing, sorting, and format-aware output. Use struct tags to define columns:

type Row struct {
    Name   string `table:"NAME,sortable"`
    Status string `table:"STATUS"`
}

tw := output.NewTableWriter(os.Stdout, output.FormatText)
tw.WriteRows(rows)

Progress Indicators

Three components handle long-running operation feedback:

  • Spin/SpinWithResult — animated spinner for indeterminate operations
  • Progress — progress bar for operations with known total
  • Status — multi-step status display with success/warn/fail icons

All three detect interactive mode (TTY + CI check) and fall back to plain text logging in non-interactive environments.

// Spinner
output.Spin(ctx, "Checking for updates", func(ctx context.Context) error {
    return updater.Check(ctx)
})

// Progress bar
bar := output.NewProgress(len(files), "Processing")
for _, f := range files {
    processFile(f)
    bar.Increment()
}
bar.Done()

// Status display
s := output.NewStatus()
s.Update("Loading config")
s.Success("Config loaded")
s.Done()

Package output provides structured output formatting for CLI commands. It supports text (default) and JSON output modes, allowing commands to produce machine-readable output for CI/CD pipelines and scripting.

Index

Examples

Constants

View Source
const (
	StatusSuccess = "success"
	StatusError   = "error"
	StatusWarning = "warning"
)

Status constants for the Response envelope.

Variables

This section is empty.

Functions

func Emit added in v1.7.0

func Emit(cmd *cobra.Command, resp Response) error

Emit writes a Response to cmd.OutOrStdout() when --output is "json". It is a no-op when the output format is text or the flag is absent.

func EmitError added in v1.7.0

func EmitError(cmd *cobra.Command, commandName string, err error) error

EmitError builds an error Response envelope and emits it via Emit.

func IsInteractive added in v1.9.6

func IsInteractive() bool

IsInteractive returns true if stdout is a TTY and CI mode is not active. Used by progress helpers to decide between animated TUI output and plain text fallback.

func IsJSONOutput added in v1.7.0

func IsJSONOutput(cmd *cobra.Command) bool

IsJSONOutput returns true if the --output flag on the command is set to "json".

func RenderMarkdown added in v1.7.0

func RenderMarkdown(content string) string

RenderMarkdown renders markdown content to styled ANSI terminal output via glamour. It detects the terminal width automatically, falling back to 80 columns. If glamour fails for any reason, the original content is returned unchanged.

func Spin added in v1.9.6

func Spin(ctx context.Context, msg string, fn func(ctx context.Context) error) error

Spin shows a spinner with a message while fn executes. In interactive terminals, displays an animated spinner. In non-interactive environments (CI, piped output), prints plain text. The context is passed to fn and used for cancellation.

Example
package main

import (
	"context"
	"fmt"
	"time"

	"github.com/phpboyscout/go-tool-base/pkg/output"
)

func main() {
	// Spin shows a spinner while the function executes.
	// In non-interactive environments (CI), it prints plain text instead.
	err := output.Spin(context.Background(), "Loading data", func(ctx context.Context) error {
		time.Sleep(10 * time.Millisecond)
		return nil
	})

	if err != nil {
		fmt.Println("Error:", err)
	}
}

func SpinWithResult added in v1.9.6

func SpinWithResult[T any](ctx context.Context, msg string, fn func(ctx context.Context) (T, error)) (T, error)

SpinWithResult is like Spin but returns a value alongside the error.

Example
package main

import (
	"context"
	"fmt"

	"github.com/phpboyscout/go-tool-base/pkg/output"
)

func main() {
	result, err := output.SpinWithResult(context.Background(), "Fetching version", func(ctx context.Context) (string, error) {
		return "v1.2.3", nil
	})

	if err == nil {
		fmt.Println("Version:", result)
	}
}

Types

type Column added in v1.8.0

type Column struct {
	// Header is the display name shown in the table header row.
	Header string
	// Field is the struct field name or map key to extract the value from.
	Field string
	// Width is the fixed column width. Zero means auto-sized to content.
	Width int
	// Sortable indicates this column can be used as a sort key.
	Sortable bool
	// Formatter is an optional function to format the cell value.
	Formatter func(any) string
}

Column defines a single table column.

type Format

type Format string

Format represents the output format for commands.

const (
	// FormatText is the default human-readable output format.
	FormatText Format = "text"
	// FormatJSON produces machine-readable JSON output.
	FormatJSON Format = "json"
	// FormatYAML produces machine-readable YAML output.
	FormatYAML Format = "yaml"
	// FormatCSV produces comma-separated values output.
	FormatCSV Format = "csv"
	// FormatMarkdown produces a pipe-delimited markdown table with header separators.
	FormatMarkdown Format = "markdown"
	// FormatTSV produces tab-separated values output for shell pipelines.
	FormatTSV Format = "tsv"
)

type Progress added in v1.9.6

type Progress struct {
	// contains filtered or unexported fields
}

Progress tracks progress of a known-total operation. In interactive terminals, displays an animated progress bar. In non-interactive environments, logs periodic status lines. Safe for concurrent use from multiple goroutines.

func NewProgress added in v1.9.6

func NewProgress(total int, description string) *Progress

NewProgress creates a progress indicator with the given total and description.

Example
package main

import (
	"github.com/phpboyscout/go-tool-base/pkg/output"
)

func main() {
	// Progress tracks a known-total operation.
	bar := &output.Progress{}
	_ = bar // In real usage: bar = output.NewProgress(100, "Processing files")

	// bar.Increment()    // advance by 1
	// bar.IncrementBy(5) // advance by 5
	// bar.Done()         // mark complete
}

func (*Progress) Done added in v1.9.6

func (p *Progress) Done()

Done marks the progress as complete and cleans up the display.

func (*Progress) Increment added in v1.9.6

func (p *Progress) Increment()

Increment advances the progress by one unit.

func (*Progress) IncrementBy added in v1.9.6

func (p *Progress) IncrementBy(n int)

IncrementBy advances the progress by n units.

type Response added in v1.7.0

type Response struct {
	Status  string `json:"status"`
	Command string `json:"command"`
	Data    any    `json:"data,omitempty"`
	Error   string `json:"error,omitempty"`
}

Response is the standard JSON envelope for all command output.

type Status added in v1.9.6

type Status struct {
	// contains filtered or unexported fields
}

Status displays a live-updating status message for multi-step operations. In interactive terminals, updates the current line in place. In non-interactive environments, prints sequential lines. Safe for concurrent use from multiple goroutines.

func NewStatus added in v1.9.6

func NewStatus() *Status

NewStatus creates a status display.

Example
package main

import (
	"bytes"

	"github.com/phpboyscout/go-tool-base/pkg/output"
)

func main() {
	var buf bytes.Buffer

	s := &output.Status{}
	_ = s
	_ = buf
	// In real usage:
	// s := output.NewStatus()
	// s.Update("Loading configuration")
	// s.Success("Configuration loaded")
	// s.Update("Connecting to API")
	// s.Warn("Connection slow")
	// s.Done()
}

func (*Status) Done added in v1.9.6

func (s *Status) Done()

Done cleans up the status display.

func (*Status) Fail added in v1.9.6

func (s *Status) Fail(msg string)

Fail marks the current step as failed and moves to the next line.

func (*Status) Success added in v1.9.6

func (s *Status) Success(msg string)

Success marks the current step as successful and moves to the next line.

func (*Status) Update added in v1.9.6

func (s *Status) Update(msg string)

Update replaces the current status message with a spinner icon.

func (*Status) Warn added in v1.9.6

func (s *Status) Warn(msg string)

Warn marks the current step as a warning and moves to the next line.

type TableOption added in v1.8.0

type TableOption func(*tableConfig)

TableOption configures the TableWriter.

func WithColumns added in v1.8.0

func WithColumns(cols ...Column) TableOption

WithColumns explicitly defines the table columns. When not provided, columns are derived from struct tags on the row data type.

func WithMaxWidth added in v1.8.0

func WithMaxWidth(width int) TableOption

WithMaxWidth overrides automatic terminal width detection.

func WithNoHeader added in v1.8.0

func WithNoHeader() TableOption

WithNoHeader suppresses the header row in text table output.

func WithNoTruncation added in v1.8.0

func WithNoTruncation() TableOption

WithNoTruncation disables terminal-width truncation. Useful when output is piped to a file or another process.

func WithSortBy added in v1.8.0

func WithSortBy(field string) TableOption

WithSortBy sets the column to sort rows by. The column must be marked Sortable.

func WithSortDescending added in v1.8.0

func WithSortDescending() TableOption

WithSortDescending reverses the sort order.

type TableWriter added in v1.8.0

type TableWriter struct {
	// contains filtered or unexported fields
}

TableWriter renders structured data as an aligned table or machine-readable format.

func NewTableWriter added in v1.8.0

func NewTableWriter(w io.Writer, format Format, opts ...TableOption) *TableWriter

NewTableWriter creates a TableWriter that writes to the given io.Writer.

Example
package main

import (
	"bytes"
	"fmt"

	"github.com/phpboyscout/go-tool-base/pkg/output"
)

func main() {
	type release struct {
		Name    string `table:"NAME,sortable"`
		Version string `table:"VERSION"`
		Status  string `table:"STATUS"`
	}

	rows := []release{
		{Name: "my-tool", Version: "v1.2.3", Status: "up to date"},
		{Name: "other", Version: "v0.9.1", Status: "update available"},
	}

	var buf bytes.Buffer
	tw := output.NewTableWriter(&buf, output.FormatText, output.WithNoTruncation())

	if err := tw.WriteRows(rows); err != nil {
		fmt.Println("Error:", err)
		return
	}

	fmt.Print(buf.String())
}
Output:
NAME      VERSION   STATUS
my-tool   v1.2.3    up to date
other     v0.9.1    update available

func (*TableWriter) WriteRows added in v1.8.0

func (t *TableWriter) WriteRows(rows any) error

WriteRows renders the provided slice as a table. The input must be a slice of structs (for tag-based columns) or []map[string]any. For JSON/YAML formats, the raw data is marshalled directly. For CSV format, columns are used as the header row. For text format, an aligned table with padding is produced.

type Writer

type Writer struct {
	// contains filtered or unexported fields
}

Writer handles formatted output based on the configured format.

func NewWriter

func NewWriter(w io.Writer, format Format) *Writer

NewWriter creates an output writer for the given format.

func (*Writer) IsJSON

func (o *Writer) IsJSON() bool

IsJSON returns true if the writer is configured for JSON output.

func (*Writer) Render added in v1.7.0

func (o *Writer) Render(markdown string) error

Render writes markdown to the Writer using glamour styling in text mode. In JSON mode it is a no-op — callers should use Write for JSON output.

func (*Writer) Write

func (o *Writer) Write(data any, textFunc func(io.Writer)) error

Write outputs data in the configured format. For JSON format, data is marshalled to indented JSON. For text format, the textFunc is called to produce human-readable output.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL