gloo

package module
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Nov 7, 2025 License: AGPL-3.0 Imports: 7 Imported by: 74

README

Documentation

Overview

Package gloo provides a framework for building Unix-style command-line tools in Go.

For Command Users

If you're using gloo.foo commands, you'll primarily interact with:

  • Command interface: Represents any executable command
  • Run: Execute a command with os.Stdin/Stdout/Stderr
  • MustRun: Execute a command and panic on error (useful for examples/tests)

Example:

cmd := cat.Cat("file.txt")
gloo.Run(cmd)

For Command Developers

If you're building gloo.foo commands, see:

  • types.go: Core types (File, Inputs, Switch)
  • initialize.go: Parameter parsing with Initialize()
  • helpers.go: Helper patterns for common command implementations

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Must

func Must(err error)

Must panics if the provided error is non-nil. This is useful for examples and tests where you want to fail fast on errors.

Example:

result, err := someOperation()
gloo.Must(err)
// proceed with result

func MustRun

func MustRun(cmd Command)

MustRun runs a command and panics if it returns an error. This is useful for examples and tests where you want to fail fast.

Example:

func ExampleCat() {
    gloo.MustRun(cat.Cat("file.txt"))
}

func Run

func Run(cmd Command) error

Run executes a command with the standard os.Stdin, os.Stdout, and os.Stderr streams. This is the primary way to run commands in production code.

Example:

cmd := cat.Cat("file.txt")
if err := gloo.Run(cmd); err != nil {
    log.Fatal(err)
}

func RunWithContext

func RunWithContext(ctx context.Context, cmd Command) error

RunWithContext executes a command with a custom context and the standard os.Stdin, os.Stdout, and os.Stderr streams. Use this when you need to pass cancellation signals, deadlines, or context values to the command.

Example:

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
cmd := grep.Grep("pattern", "largefile.txt")
if err := gloo.RunWithContext(ctx, cmd); err != nil {
    log.Fatal(err)
}

Types

type AccumulateAndOutputFunc

type AccumulateAndOutputFunc func(lines []string, stdout io.Writer) error

AccumulateAndOutputFunc collects all lines, processes them, and outputs directly.

type AccumulateAndProcessFunc

type AccumulateAndProcessFunc func(lines []string) []string

AccumulateAndProcessFunc collects all lines, processes them, and returns the result.

type Command

type Command interface {
	Executor() CommandExecutor
}

Command represents an executable command. All gloo.foo commands implement this interface.

func AccumulateAndOutput

func AccumulateAndOutput(fn AccumulateAndOutputFunc) Command

AccumulateAndOutput creates a Command that collects all lines and outputs with full control. Best for: wc - need to accumulate and produce custom output format

Example:

func (c command) Executor() gloo.CommandExecutor {
    return gloo.AccumulateAndOutput(func(lines []string, stdout io.Writer) error {
        fmt.Fprintf(stdout, "%d lines\n", len(lines))
        return nil
    }).Executor()
}

func AccumulateAndProcess

func AccumulateAndProcess(fn AccumulateAndProcessFunc) Command

AccumulateAndProcess creates a Command that collects all lines, processes them, and outputs. Best for: sort, tac, shuf - need to see all input before producing output

Example:

func (c command) Executor() gloo.CommandExecutor {
    return gloo.AccumulateAndProcess(func(lines []string) []string {
        sort.Strings(lines)
        return lines
    }).Executor()
}

func LineTransform

func LineTransform(fn LineTransformFunc) Command

LineTransform creates a Command that transforms lines one at a time. Best for: grep, cut, tr, sed - stateless line transformations

Example:

func (c command) Executor() gloo.CommandExecutor {
    return gloo.LineTransform(func(line string) (string, bool) {
        if strings.Contains(line, c.pattern) {
            return line, true
        }
        return "", false
    }).Executor()
}

func RawCommand

func RawCommand(fn CommandExecutor) Command

RawCommand wraps a raw CommandExecutor function. Best for: diff, paste, comm, find, ls - need full control over I/O

Example:

func (c command) Executor() gloo.CommandExecutor {
    return gloo.RawCommand(func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer) error {
        // Full control over I/O
        return nil
    }).Executor()
}

func StatefulLineTransform

func StatefulLineTransform(fn StatefulLineTransformFunc) Command

StatefulLineTransform creates a Command that transforms lines with state tracking. Best for: uniq, nl, head - need line numbers or previous line tracking

Example:

func (c command) Executor() gloo.CommandExecutor {
    return gloo.StatefulLineTransform(func(lineNum int64, line string) (string, bool) {
        if lineNum <= c.maxLines {
            return line, true
        }
        return "", false
    }).Executor()
}

type CommandExecutor

type CommandExecutor func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer) error

CommandExecutor is the function signature for executing a command. It receives context, input/output streams, and returns an error.

type File

type File string

File represents a file path that should be opened for reading. When used as positional type with Initialize, the framework automatically opens the files. If no files are provided, stdin is used.

Example:

inputs := gloo.Initialize[gloo.File, flags](params...)
// Framework automatically opens files and handles stdin

type Inputs

type Inputs[T any, O any] struct {
	Positional []T   // Parsed positional arguments
	Flags      O     // Parsed flags
	Ambiguous  []any // Arguments that couldn't be parsed
	// contains filtered or unexported fields
}

Inputs holds parsed command parameters: positional arguments, flags, and I/O streams. This is the primary type command developers work with.

Type Parameters:

  • T: Type of positional arguments (e.g., gloo.File, string, custom types)
  • O: Type of flags struct

Example:

type command gloo.Inputs[gloo.File, myFlags]

func (c command) Executor() gloo.CommandExecutor {
    inputs := gloo.Inputs[gloo.File, myFlags](c)
    return inputs.Wrap(...)
}

func Initialize

func Initialize[T any, O any](parameters ...any) Inputs[T, O]

Initialize parses parameters into Inputs and automatically handles file opening based on the positional type T:

  • gloo.File: Automatically opens files for reading (or uses stdin if no files)
  • io.Reader: Wraps readers for stdin
  • Other types: Just parses (commands define their own types as needed)

Example:

func Cat(parameters ...any) gloo.Command {
    inputs := gloo.Initialize[gloo.File, Flags](parameters...)
    return command(inputs)
}

Custom types:

type DirPath string  // Command-defined type
inputs := gloo.Initialize[DirPath, Flags](parameters...)

func (Inputs[T, O]) Close

func (inputs Inputs[T, O]) Close() error

Close closes all opened file handles. Call this when done with the inputs.

Example:

inputs := gloo.Initialize[gloo.File, flags](params...)
defer inputs.Close()

func (Inputs[T, O]) Reader

func (inputs Inputs[T, O]) Reader(stdin io.Reader) io.Reader

Reader returns a single io.Reader that combines all stdin sources. If multiple files were opened, they're concatenated. If none, returns the stdin parameter. This is useful for commands that want to treat multiple files as one stream.

Example:

func (c command) Executor() gloo.CommandExecutor {
    return func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer) error {
        input := gloo.Inputs[gloo.File, flags](c).Reader(stdin)
        scanner := bufio.NewScanner(input)
        // ... process combined stream
    }
}

func (Inputs[T, O]) Readers

func (inputs Inputs[T, O]) Readers() []io.Reader

Readers returns the opened readers for commands that need direct access to io.Reader. This allows commands to work with readers without caring about file paths.

Example:

for _, r := range inputs.Readers() {
    scanner := bufio.NewScanner(r)
    // ... process each file separately
}

func (Inputs[T, O]) Wrap

func (inputs Inputs[T, O]) Wrap(executor CommandExecutor) CommandExecutor

Wrap wraps a CommandExecutor to automatically use the correct input source. This allows commands to use helper functions without worrying about stdin vs files. The framework automatically routes input based on how the command was initialized.

Example:

func (c command) Executor() gloo.CommandExecutor {
    inputs := gloo.Inputs[gloo.File, flags](c)
    return inputs.Wrap(
        gloo.AccumulateAndProcess(func(lines []string) []string {
            return c.process(lines)
        }).Executor(),
    )
}

type LineTransformFunc

type LineTransformFunc func(line string) (output string, emit bool)

LineTransformFunc is a simple line-by-line transformation. Return (output, true) to emit the line, or (_, false) to skip it.

type StatefulLineTransformFunc

type StatefulLineTransformFunc func(lineNum int64, line string) (output string, emit bool)

StatefulLineTransformFunc is a line transformation with line number tracking. Return (output, true) to emit the line, or (_, false) to skip it.

type Switch

type Switch[T any] interface {
	Configure(*T)
}

Switch is the interface for flag types. All flag types should implement this interface to configure the flags struct.

Example:

type IgnoreCase bool
const (
    CaseSensitive   IgnoreCase = false
    CaseInsensitive IgnoreCase = true
)

func (f IgnoreCase) Configure(flags *Flags) {
    flags.IgnoreCase = f
}

Jump to

Keyboard shortcuts

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