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 ¶
- func Must(err error)
- func MustRun(cmd Command)
- func Run(cmd Command) error
- func RunWithContext(ctx context.Context, cmd Command) error
- type AccumulateAndOutputFunc
- type AccumulateAndProcessFunc
- type Command
- type CommandExecutor
- type File
- type Inputs
- type LineTransformFunc
- type StatefulLineTransformFunc
- type Switch
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 ¶
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 ¶
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 ¶
AccumulateAndOutputFunc collects all lines, processes them, and outputs directly.
type AccumulateAndProcessFunc ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
LineTransformFunc is a simple line-by-line transformation. Return (output, true) to emit the line, or (_, false) to skip it.
type StatefulLineTransformFunc ¶
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
}