sink

package
v0.1.0-dev.20260821035910 Latest Latest
Warning

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

Go to latest
Published: Aug 21, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

Package sink defines the byte-out endpoint contract used by pkg/status (categorized narration) and pkg/result (structured result emission).

A Sink is an io.WriteCloser that knows whether it's writing to a TTY. Higher-level wrappers (status.Narrator, result.Pipeline) consume a Sink and decide what to write through it; the Sink just delegates writes to its underlying io.Writer and reports TTY-ness derived at construction.

Six convenience constructors ship in this package, each pre-wiring the underlying writer:

  • Stderr / Stdout — the two standard process streams; TTY-awareness derived from the fd.
  • Capture — returns a Sink + the bytes.Buffer it wraps so tests can assert on captured bytes.
  • Discard — wraps io.Discard; every write succeeds and goes nowhere.
  • File — opens the named path; the returned Sink owns the file and closes it on [Sink.Close].
  • Tee — fans out writes to multiple sinks; closes all on [Sink.Close].

The generic New constructor wraps any io.Writer; the caller owns the writer's lifecycle and the returned Sink's [Sink.Close] is a no-op. TTY-ness is derived from the writer when possible (writer is an *os.File pointing at a terminal); false otherwise.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Sink

type Sink interface {
	io.WriteCloser

	// IsTTY reports whether the underlying writer is connected to a terminal.
	//
	// Computed at construction from the writer (true iff the writer is an [*os.File] whose fd passes
	// [term.IsTerminal]); always false for [Capture], [Discard], [File], and [Tee], and false for [New] when the
	// wrapped writer isn't a terminal-backed [*os.File].
	IsTTY() bool
}

Sink is the byte-out contract.

Wraps an io.Writer with io.Closer (default no-op for sinks that don't own their writer) and a Sink.IsTTY query so higher-level wrappers can decide whether to emit ANSI color codes.

Sinks shipped by this package are constructed via the convenience functions (Stderr, Stdout, Capture, Discard, File, Tee) or via the generic New. Implementations are unexported; callers always interact with the interface.

func Capture

func Capture() (Sink, *bytes.Buffer)

Capture returns a Sink whose writes accumulate into an in-memory buffer.

Test fixture. The returned Sink does not own anything that needs cleanup; [Sink.Close] is a no-op. IsTTY always returns false.

Returns:

  • Sink: the buffer-backed sink, ready to install on a status.Narrator or result.Pipeline.
  • *bytes.Buffer: the underlying buffer; pass to test assertions.

func Discard

func Discard() Sink

Discard returns a Sink whose writes go nowhere.

Wraps io.Discard; every write succeeds, every byte is dropped. [Sink.Close] is a no-op. IsTTY always returns false. The cli boundary picks this when `--silent` is set.

Returns:

  • Sink: the no-op sink.

func File

func File(path string) (Sink, error)

File opens the named path for writing and returns a Sink that owns the file's lifecycle.

The Sink's [Sink.Close] closes the underlying os.File, so the caller pairs construction with `defer iox.Close(&err, sink)` to release the fd. IsTTY returns false (regular files are not terminals).

Parameters:

  • path: the filesystem path to open. The file is created or truncated via os.Create.

Returns:

  • Sink: the file-backed sink.
  • error: non-nil if the file could not be opened.

func New

func New(w io.Writer) Sink

New wraps an arbitrary io.Writer in a Sink.

The returned Sink does not own the writer's lifecycle — [Sink.Close] is a no-op. The caller is responsible for closing the writer if it requires cleanup. IsTTY is derived: true iff the writer is an *os.File whose fd passes term.IsTerminal; false otherwise (including all non-file writers — buffers, pipes, network connections).

Parameters:

  • w: the writer to wrap. Must not be nil.

Returns:

  • Sink: the writer-backed sink.

func Stderr

func Stderr() Sink

Stderr returns a Sink wrapping os.Stderr. TTY-awareness is derived from the fd.

The cli boundary's default narration sink. [Sink.Close] is a no-op — stderr is owned by the OS, never closed by user code.

Returns:

  • Sink: the stderr-backed sink.

func Stdout

func Stdout() Sink

Stdout returns a Sink wrapping os.Stdout. TTY-awareness is derived from the fd.

The cli boundary's default result-emission sink. [Sink.Close] is a no-op — stdout is owned by the OS, never closed by user code.

Returns:

  • Sink: the stdout-backed sink.

func Tee

func Tee(sinks ...Sink) Sink

Tee returns a Sink that fans writes out to every supplied sink in order.

[Sink.Close] cascades to every supplied sink and joins their errors via errors.Join.

IsTTY always returns false — even if every supplied sink is TTY-aware, fanning out implies "this is being captured/logged in addition to displayed," which usually means decoration should be suppressed. Callers that need TTY-aware fan-out can build a custom impl.

Parameters:

  • sinks: the destinations to fan out to. Empty slice produces a Sink whose writes are no-ops.

Returns:

  • Sink: the fan-out sink.

Jump to

Keyboard shortcuts

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