fo

package
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Dec 5, 2025 License: MIT Imports: 26 Imported by: 0

README

fo

A Go library for running shell commands with formatted, colorful console output. Designed for use in build scripts, particularly with Mage.

Note: This library is the engine behind the fo CLI. All features available in the fo command-line tool are also available programmatically via this library. See the main README for CLI usage examples.

Installation

go get github.com/dkoosis/fo/fo

Quick Start

package main

import (
    "github.com/dkoosis/fo/fo"
)

func main() {
    console := fo.DefaultConsole()

    result, err := console.Run("Build", "go", "build", "./...")
    if err != nil {
        // Handle error
    }

    // Check exit code
    if result.ExitCode != 0 {
        // Command failed
    }
}

API Reference

Console

The main type for running commands.

NewConsole(config ConsoleConfig) *Console

Creates a new Console with the specified configuration.

console := fo.NewConsole(fo.ConsoleConfig{
    LiveStreamOutput: true,        // Stream output live
    ShowOutputMode:   "on-fail",   // Show captured output: "always", "on-fail", "never"
    Monochrome:       false,       // Disable colors
})
DefaultConsole() *Console

Creates a Console with sensible defaults.

console := fo.DefaultConsole()
Running Commands
Run(label, command string, args ...string) (*TaskResult, error)

Runs a command with a label and returns detailed results.

result, err := console.Run("Go Test", "go", "test", "-v", "./...")
if err != nil {
    // err is non-nil if command not found or non-zero exit
}
fmt.Printf("Exit code: %d\n", result.ExitCode)
fmt.Printf("Duration: %v\n", result.Duration)
RunSimple(command string, args ...string) error

Simplified interface that returns only an error.

if err := console.RunSimple("go", "build", "./..."); err != nil {
    return err
}
TaskResult

Returned by Run() with command execution details.

type TaskResult struct {
    Label    string        // The label you provided
    Status   string        // "success", "error", "warning"
    ExitCode int           // Command exit code
    Duration time.Duration // Execution time
    Lines    []Line        // Captured output lines (in capture mode)
}
Error Handling

The library exports ErrNonZeroExit for checking exit code errors:

result, err := console.Run("Test", "go", "test", "./...")
if errors.Is(err, fo.ErrNonZeroExit) {
    fmt.Printf("Tests failed with exit code %d\n", result.ExitCode)
}

For command-not-found errors:

result, err := console.Run("Missing", "nonexistent-command")
if errors.Is(err, exec.ErrNotFound) {
    fmt.Printf("Command not found (exit code %d)\n", result.ExitCode)
}

Note: TaskResult is always non-nil, even for infrastructure failures. This allows you to access duration, label, and error details regardless of how the command failed. Use result.ExitCode (127 for command not found) and result.Err for details.

For RunSimple, you can extract the exit code from errors:

err := console.RunSimple("go", "test", "./...")
if errors.Is(err, fo.ErrNonZeroExit) {
    var exitErr fo.ExitCodeError
    if errors.As(err, &exitErr) {
        fmt.Printf("Exit code: %d\n", exitErr.Code)
    }
}

Configuration Options

ConsoleConfig Fields
Field Type Default Description
LiveStreamOutput bool false Stream output live instead of capturing
ShowOutputMode string "on-fail" When to show captured output: "always", "on-fail", "never"
Monochrome bool false Disable ANSI colors
ShowTimer bool true Show execution duration
ThemeName string "unicode_vibrant" Visual theme name
UseBoxes bool true Use box-drawing characters
InlineProgress bool false Use inline progress instead of multi-line
MaxBufferSize int64 10MB Max buffer size for captured output
MaxLineLength int 1MB Max length for a single output line
Out io.Writer os.Stdout Output writer
Err io.Writer os.Stderr Error writer
Debug bool false Enable debug output
Example Configurations

CI Mode (no colors, no timer):

console := fo.NewConsole(fo.ConsoleConfig{
    Monochrome: true,
    ShowTimer:  false,
})

Streaming Mode:

console := fo.NewConsole(fo.ConsoleConfig{
    LiveStreamOutput: true,
})

Custom Writers (for testing):

var stdout, stderr bytes.Buffer
console := fo.NewConsole(fo.ConsoleConfig{
    Out: &stdout,
    Err: &stderr,
})

Usage Patterns

Mage Build Script
//go:build mage

package main

import "github.com/dkoosis/fo/fo"

var console = fo.DefaultConsole()

func Build() error {
    _, err := console.Run("Go Build", "go", "build", "./...")
    return err
}

func Test() error {
    _, err := console.Run("Go Test", "go", "test", "./...")
    return err
}

func QA() error {
    if _, err := console.Run("Format", "go", "fmt", "./..."); err != nil {
        return err
    }
    if _, err := console.Run("Vet", "go", "vet", "./..."); err != nil {
        return err
    }
    return nil
}
Error Aggregation
func RunAll() error {
    var errors []error

    for _, target := range []string{"./cmd/...", "./internal/...", "./pkg/..."} {
        result, err := console.Run("Build "+target, "go", "build", target)
        if err != nil {
            errors = append(errors, fmt.Errorf("%s failed: %w", target, err))
        }
    }

    if len(errors) > 0 {
        return fmt.Errorf("build failed: %v", errors)
    }
    return nil
}
Conditional Output
func VerboseBuild(verbose bool) error {
    mode := "on-fail"
    if verbose {
        mode = "always"
    }

    console := fo.NewConsole(fo.ConsoleConfig{
        ShowOutputMode: mode,
    })

    _, err := console.Run("Build", "go", "build", "-v", "./...")
    return err
}

Themes

Available themes:

  • unicode_vibrant (default) - Colorful with Unicode characters
  • ascii_minimal - Plain ASCII, suitable for limited terminals

Custom themes can be defined in .fo.yaml configuration files.

License

See the main project license.

Documentation

Overview

fo/content.go - Content rendering primitives for structured section output.

This file provides high-level content rendering functions that produce properly formatted, themed output inside section boxes. These primitives are the building blocks for creating consistent, beautiful mage output.

Package fo provides editor mode for viewing and editing output.

Package fo provides live rendering with in-place terminal updates.

fo/magetasks.go - Standard mage task helpers for common Go project operations.

This file provides ready-to-use mage tasks that work out of the box with beautiful, themed output. Import this in your magefile to get instant professional output for common operations like deps, build, test, lint.

Package fo provides a processor for handling command output.

fo/projectconfig.go - Project-specific configuration via .fo.yaml

This file provides support for loading project-specific configuration from a .fo.yaml file in the project root. This allows projects to customize themes, thresholds, and behavior without code changes.

Index

Constants

View Source
const (
	// DefaultTerminalWidth is the fallback terminal width when detection fails.
	DefaultTerminalWidth = 80

	// DefaultHeaderWidth is the default header width when not specified in theme.
	DefaultHeaderWidth = 60

	// ReadBufferSize is the buffer size for reading from pipes (4KB).
	ReadBufferSize = 4096

	// AdapterDetectionLineCount is the number of lines to buffer for adapter detection.
	AdapterDetectionLineCount = 15

	// SignalTimeout is the timeout for graceful process termination before force kill.
	SignalTimeout = 2 * time.Second

	// StreamCount is the number of output streams (stdout and stderr).
	StreamCount = 2
)

Constants for buffer sizes and limits.

Variables

View Source
var ErrFormattingNeeded = errors.New("files need formatting: run 'go fmt ./...'")

ErrFormattingNeeded indicates that files need formatting.

View Source
var ErrNonZeroExit = errors.New("command exited with non-zero code")

ErrNonZeroExit is returned when a command completes but exits with a non-zero code. Use errors.Is(err, ErrNonZeroExit) to check for this condition.

Functions

func FormatCount

func FormatCount(count int, singular, plural string) string

FormatCount formats a count with optional units.

func FormatDuration

func FormatDuration(d float64) string

FormatDuration formats a duration in a human-readable way for display.

func FormatTrend

func FormatTrend(current int, average float64, upIsBad bool) string

FormatTrend returns a trend indicator string based on current vs average. Returns "↑" (bad), "↓" (good), or "" (neutral) with appropriate color.

func HumanizeTestName

func HumanizeTestName(testName string) string

HumanizeTestName converts Go test names to human-friendly format.

func NewSectionWarning

func NewSectionWarning(err error) error

NewSectionWarning wraps an error as a warning that should be displayed but not fail the section execution.

Types

type BulletItem

type BulletItem struct {
	Text  string // Main text content
	Color string // Optional color for the text
}

BulletItem represents a bulleted list item.

type Console

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

func DefaultConsole

func DefaultConsole() *Console

func NewConsole

func NewConsole(cfg ConsoleConfig) *Console

func NewConsoleFromProject

func NewConsoleFromProject() *Console

NewConsoleFromProject creates a Console configured from project settings.

func (*Console) AnalyzeFileSizes

func (c *Console) AnalyzeFileSizes(root string, cfg FileSizeConfig) (*FileSizeAnalysis, error)

AnalyzeFileSizes performs file size analysis on the repository.

func (*Console) BuildGo

func (c *Console) BuildGo(outputName string, pkg string, ldflags ...string) error

BuildGo builds a Go binary with the given output name.

func (*Console) DepsTidy

func (c *Console) DepsTidy() error

DepsTidy cleans up go.mod and go.sum.

func (*Console) DepsUpdate

func (c *Console) DepsUpdate() (string, error)

DepsUpdate updates all Go dependencies to latest versions. Returns a summary message suitable for section display.

func (*Console) DepsVerify

func (c *Console) DepsVerify() error

DepsVerify verifies dependencies haven't been modified.

func (*Console) ErrorMsg

func (c *Console) ErrorMsg(msg string) string

ErrorMsg returns a themed error message with icon and color. Uses RenderDirectMessage as the single rendering engine.

func (*Console) FormatPath

func (c *Console) FormatPath(path string) string

FormatPath formats a file path with directory in muted color and filename in white.

func (*Console) FormatStatusIcon

func (c *Console) FormatStatusIcon(status string) string

FormatStatusIcon returns a fully styled icon string for the given status. Status can be "PASS", "FAIL", "SKIP", "SUCCESS", "ERROR", "WARNING", or "MUTED". Returns the icon with appropriate color and reset code.

func (*Console) FormatStatusText

func (c *Console) FormatStatusText(text, status string) string

FormatStatusText returns a fully styled text string for the given status. Status can be "PASS", "FAIL", "SKIP", "SUCCESS", "ERROR", "WARNING", or "MUTED". Returns the text with appropriate color and reset code.

func (*Console) FormatTestName

func (c *Console) FormatTestName(name, status string) string

FormatTestName returns a fully styled test name for the given status. This is a convenience method that combines FormatStatusIcon and FormatStatusText for common test rendering patterns.

func (*Console) GetBlueFgColor

func (c *Console) GetBlueFgColor() string

GetBlueFgColor returns the light blue color code from the theme.

func (*Console) GetBorderChars

func (c *Console) GetBorderChars() (string, string, string, string)

GetBorderChars returns the border characters from the theme.

func (*Console) GetColor

func (c *Console) GetColor(colorKey string) string

GetColor returns a color code from the theme by key.

func (*Console) GetErrorColor

func (c *Console) GetErrorColor() string

GetErrorColor returns the Error color code from the theme.

func (*Console) GetGreenFgColor

func (c *Console) GetGreenFgColor() string

GetGreenFgColor returns the light green color code from the theme.

func (*Console) GetHeaderWidth

func (c *Console) GetHeaderWidth() int

GetHeaderWidth returns the header width from the theme.

func (*Console) GetIcon

func (c *Console) GetIcon(iconKey string) string

GetIcon returns an icon from the theme by key.

func (*Console) GetMutedColor

func (c *Console) GetMutedColor() string

GetMutedColor returns the Muted color code from the theme.

func (*Console) GetSuccessColor

func (c *Console) GetSuccessColor() string

GetSuccessColor returns the Success color code from the theme.

func (*Console) GetWarningColor

func (c *Console) GetWarningColor() string

GetWarningColor returns the Warning color code from the theme.

func (*Console) InfoMsg

func (c *Console) InfoMsg(msg string) string

InfoMsg returns a themed info message with icon and color. Uses RenderDirectMessage as the single rendering engine.

func (*Console) LintFormat

func (c *Console) LintFormat() error

LintFormat checks if code is properly formatted.

func (*Console) LintGo

func (c *Console) LintGo() error

LintGo runs golangci-lint on the codebase.

func (*Console) LintStaticcheck

func (c *Console) LintStaticcheck() error

LintStaticcheck runs staticcheck on the codebase.

func (*Console) LintVet

func (c *Console) LintVet() error

LintVet runs go vet on the codebase.

func (*Console) PrintBlankLine

func (c *Console) PrintBlankLine()

PrintBlankLine prints an empty line inside the section box.

func (*Console) PrintBulletHeader

func (c *Console) PrintBulletHeader(text string)

PrintBulletHeader renders a bulleted section header inside a section box. Example: " ◉ File Metrics (Non-Test Files)".

func (*Console) PrintBulletItem

func (c *Console) PrintBulletItem(item BulletItem)

PrintBulletItem renders a bulleted list item.

func (*Console) PrintH1Header

func (c *Console) PrintH1Header(name string)

PrintH1Header prints a major headline (H1) using the console's theme.

func (*Console) PrintMetricLine

func (c *Console) PrintMetricLine(m MetricLine)

PrintMetricLine renders a single metric line inside a section box. The label is left-aligned, value is right-aligned at a fixed column.

func (*Console) PrintRankedList

func (c *Console) PrintRankedList(title string, items []RankedItem)

PrintRankedList renders a numbered list of ranked items. Example:

  1. 2562 internal/server/handler.go
  2. 1841 internal/client/client.go

func (*Console) PrintSectionContentLine

func (c *Console) PrintSectionContentLine(content ContentLine)

PrintSectionContentLine renders a structured content line with guaranteed icon alignment. Uses lipgloss for consistent rendering.

func (*Console) PrintSectionFooter

func (c *Console) PrintSectionFooter()

PrintSectionFooter closes the section box with a bottom border. Uses lipgloss for consistent rendering.

func (*Console) PrintSectionHeader

func (c *Console) PrintSectionHeader(name string)

PrintSectionHeader prints a section header and starts a section box. Uses lipgloss for consistent box rendering.

func (*Console) PrintSectionLine

func (c *Console) PrintSectionLine(line string)

PrintSectionLine prints a line of section content with side borders. Uses lipgloss for consistent rendering.

func (*Console) PrintSparkline

func (c *Console) PrintSparkline(title string, data []SparklineData, width int)

PrintSparkline renders a sparkline distribution chart. Each row shows a label and a colored bar representing proportions.

func (*Console) PrintText

func (c *Console) PrintText(text string)

PrintText renders plain text inside the section box with proper indentation.

func (*Console) ProcessStdin

func (c *Console) ProcessStdin(task *design.Task, input []byte)

ProcessStdin processes stdin input through the processor pipeline. This is the core of Editor mode - transforming raw input into formatted output.

func (*Console) ProcessStdinStream

func (c *Console) ProcessStdinStream(input io.Reader, onLine LineCallback) error

ProcessStdinStream processes streaming stdin input, calling back for each line. This enables live rendering as output arrives.

func (*Console) RenderFileSizeReport

func (c *Console) RenderFileSizeReport(analysis *FileSizeAnalysis, cfg FileSizeConfig)

RenderFileSizeReport renders the file size analysis inside a section box.

func (*Console) ResetColor

func (c *Console) ResetColor() string

ResetColor returns the reset color code from the theme.

func (*Console) Run

func (c *Console) Run(label, command string, args ...string) (*TaskResult, error)

Run executes a command and returns the result.

Error semantics:

  • Returns (result, nil) when the command runs successfully (exit code 0)
  • Returns (result, error) when the command runs but exits non-zero; the error wraps the underlying exec.ExitError
  • Returns (result, error) for infrastructure failures (command not found, IO errors, context cancelled)

Note: TaskResult is always non-nil. Even for infrastructure failures, the result contains useful information like duration, label, and any captured internal error messages. Use TaskResult.ExitCode (127 for command not found, 1 for other failures) and TaskResult.Err for failure details.

Use errors.Is(err, exec.ErrNotFound) to check for missing commands.

func (*Console) RunCapture

func (c *Console) RunCapture(label, command string, args ...string) (string, error)

RunCapture executes a command and returns the combined output as a string. This is useful when you need to parse command output.

func (*Console) RunLive

func (c *Console) RunLive(input io.Reader) error

RunLive processes streaming input with live terminal updates. Lines are classified and rendered as they arrive, with in-place updates for status information. Falls back to simple streaming on non-TTY outputs.

func (*Console) RunLiveSection

func (c *Console) RunLiveSection(ls *LiveSection) SectionResult

RunLiveSection executes a LiveSection and returns its result. It prints a section header, runs the work function (which can update rows), renders all rows (including expanded content), and prints a summary.

func (*Console) RunSection

func (c *Console) RunSection(s Section) SectionResult

RunSection executes a single section and returns its result. It prints a section header, runs the work function, and prints a one-line summary with status icon and duration.

func (*Console) RunSections

func (c *Console) RunSections(sections ...Section) ([]SectionResult, error)

RunSections executes multiple sections in sequence and returns all results plus an aggregated error. If any section fails (SectionError), the aggregated error will be non-nil, but all sections will still be executed. Warnings (SectionWarning) are displayed but do not contribute to the aggregated error.

func (*Console) RunSimple

func (c *Console) RunSimple(command string, args ...string) error

RunSimple executes a command and returns only an error. This is a convenience wrapper around Run for simple use cases where you only need to know success vs failure.

Returns nil on success (exit code 0). Returns ErrNonZeroExit (wrapped with ExitCodeError) if the command exits with non-zero code. Returns other errors for infrastructure failures.

To check for non-zero exit and extract the code:

if errors.Is(err, ErrNonZeroExit) {
    var exitErr ExitCodeError
    if errors.As(err, &exitErr) {
        fmt.Printf("Exit code: %d\n", exitErr.Code)
    }
}

For detailed results including captured output, use Run() instead.

func (*Console) SetSectionSummary

func (c *Console) SetSectionSummary(summary string)

SetSectionSummary sets a summary message for the current section being executed. This should be called by section work functions to provide a summary message that will be shown instead of the section name on success.

func (*Console) SuccessMsg

func (c *Console) SuccessMsg(msg string) string

SuccessMsg returns a themed success message with icon and color. Uses RenderDirectMessage as the single rendering engine.

func (*Console) TestGo

func (c *Console) TestGo(coverageFile string, packages ...string) (*TestSummary, error)

TestGo runs Go tests with optional coverage.

func (*Console) WarnMsg

func (c *Console) WarnMsg(msg string) string

WarnMsg returns a themed warning message with icon and color. Uses RenderDirectMessage as the single rendering engine.

type ConsoleConfig

type ConsoleConfig struct {
	ThemeName        string
	UseBoxes         bool
	UseBoxesSet      bool
	Monochrome       bool
	ShowTimer        bool
	ShowTimerSet     bool
	ShowOutputMode   string
	LiveStreamOutput bool
	PatternHint      string // Manual pattern selection hint (e.g., "test-table", "sparkline", "leaderboard")
	Debug            bool
	Profile          bool   // Enable performance profiling
	ProfileOutput    string // Profile output destination
	MaxBufferSize    int64
	MaxLineLength    int
	Design           *design.Config
	Out              io.Writer // Output writer, defaults to os.Stdout
	Err              io.Writer // Error writer, defaults to os.Stderr
}

type ContentLine

type ContentLine struct {
	Icon      string // Optional icon (e.g., checkmark) - will be rendered at fixed position
	IconColor string // Optional color for icon (empty = no color)
	Text      string // Main text content
	TextColor string // Optional color for text (empty = no color)
}

ContentLine represents structured content for consistent rendering. This ensures icons and text align properly across all section lines.

type CoverageThreshold

type CoverageThreshold struct {
	Min      float64
	Max      float64
	ColorKey string
}

CoverageThreshold defines a coverage range and its associated color.

type EditorMode

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

EditorMode provides an interface for viewing/editing output in an external editor.

func NewEditorMode

func NewEditorMode(editor string) *EditorMode

NewEditorMode creates a new EditorMode instance. If editor is empty, it will attempt to detect from $EDITOR environment variable.

func (*EditorMode) GetEditorCommand

func (e *EditorMode) GetEditorCommand() string

GetEditorCommand returns the editor command being used.

func (*EditorMode) OpenInEditor

func (e *EditorMode) OpenInEditor(content string) (string, error)

OpenInEditor opens the given content in an external editor. Returns the edited content and any error that occurred.

type ExitCodeError

type ExitCodeError struct {
	Code int
}

ExitCodeError wraps an exit code for programmatic access. Use errors.As(err, &ExitCodeError{}) to extract the exit code from RunSimple errors.

func (ExitCodeError) Error

func (e ExitCodeError) Error() string

type FileInfo

type FileInfo struct {
	Path      string
	LineCount int
	IsTest    bool
}

FileInfo holds information about a file's size.

type FileSizeAnalysis

type FileSizeAnalysis struct {
	Files         []FileInfo
	NonTestFiles  []FileInfo
	Warnings      []string
	Errors        []string
	MarkdownCount int
	TotalFiles    int
	Over500Count  int
	Over750Count  int
	Over1000Count int
	GreenCount    int // Files < 500 LOC
	YellowCount   int // Files 500-999 LOC
	RedCount      int // Files >= 1000 LOC
}

FileSizeAnalysis holds the results of file size analysis.

type FileSizeConfig

type FileSizeConfig struct {
	WarnLineCount      int    // Warn when regular files exceed this (default: 500)
	ErrorLineCount     int    // Error when regular files exceed this (default: 1000)
	WarnLineCountTest  int    // Warn when test files exceed this (default: 800)
	ErrorLineCountTest int    // Error when test files exceed this (default: 1400)
	TopFilesCount      int    // Show top N largest files (default: 5)
	WarnMarkdownCount  int    // Warn when markdown file count exceeds (default: 50)
	SnapshotDir        string // Directory for storing snapshots (default: ".fo")
}

FileSizeConfig configures the file size analysis.

func DefaultFileSizeConfig

func DefaultFileSizeConfig() FileSizeConfig

DefaultFileSizeConfig returns sensible defaults.

type Line

type Line struct {
	Content   string
	Type      string // "detail", "error", "warning", "success", "info", "progress"
	Timestamp time.Time
}

Line represents a classified line of command output. This is the public-facing type that doesn't leak internal design package types.

type LineCallback

type LineCallback func(line string, lineType string, ctx design.LineContext)

LineCallback is called for each processed line during streaming. It receives the line content, its classified type, and context.

type LiveRenderer

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

LiveRenderer handles in-place terminal updates for streaming output. It tracks rendered lines and uses ANSI cursor control for updates.

func NewLiveRenderer

func NewLiveRenderer(out io.Writer) *LiveRenderer

NewLiveRenderer creates a renderer for the given output. If out is not a TTY, updates will append rather than overwrite.

func (*LiveRenderer) AppendLine

func (r *LiveRenderer) AppendLine(line string)

AppendLine adds a new line without affecting previous content. Use this for streaming output that shouldn't be overwritten.

func (*LiveRenderer) Clear

func (r *LiveRenderer) Clear()

Clear removes all rendered lines from the display.

func (*LiveRenderer) Complete

func (r *LiveRenderer) Complete()

Complete ends the live rendering session. Shows cursor and optionally leaves final state visible.

func (*LiveRenderer) IsTTY

func (r *LiveRenderer) IsTTY() bool

IsTTY returns whether the output supports cursor control.

func (*LiveRenderer) Render

func (r *LiveRenderer) Render(lines []string)

Render displays lines, replacing any previous content. This is atomic - the entire update happens in one write.

func (*LiveRenderer) Start

func (r *LiveRenderer) Start()

Start begins a live rendering session. Hides cursor if TTY to reduce visual noise during updates.

func (*LiveRenderer) UpdateLastLine

func (r *LiveRenderer) UpdateLastLine(line string)

UpdateLastLine overwrites just the last rendered line. Useful for progress indicators or status updates.

type LiveRow

type LiveRow struct {
	ID              string   // Unique identifier for the row
	Content         string   // Current content of the row (summary line)
	Expanded        bool     // Whether the row is expanded
	ExpandedContent []string // Additional content lines shown when expanded
}

LiveRow represents a single row in a LiveSection that can be updated dynamically.

type LiveSection

type LiveSection struct {
	Name            string                   // Human-readable section name, shown in header
	Description     string                   // Optional description
	Summary         string                   // Optional summary message
	Rows            map[string]*LiveRow      // Map of row ID to row content
	Run             func(*LiveSection) error // Work function that receives the LiveSection for updates
	DefaultExpanded bool                     // Default expansion state for new rows (default: false, collapsed)
	// contains filtered or unexported fields
}

LiveSection represents a section that can update its content in real-time. Rows can be added, updated, or removed dynamically during execution.

func NewLiveSection

func NewLiveSection(name string, run func(*LiveSection) error) *LiveSection

NewLiveSection creates a new LiveSection with the given name and run function.

func (*LiveSection) AddRow

func (ls *LiveSection) AddRow(id, content string)

AddRow adds or updates a row in the LiveSection.

func (*LiveSection) AddRowWithExpansion

func (ls *LiveSection) AddRowWithExpansion(id, content string, expandedContent []string)

AddRowWithExpansion adds or updates a row with expandable content. If expandedContent is provided, the row can be expanded to show additional details. New rows default to collapsed state unless DefaultExpanded is true.

func (*LiveSection) CollapseAll

func (ls *LiveSection) CollapseAll()

CollapseAll collapses all rows in the LiveSection.

func (*LiveSection) CollapseRow

func (ls *LiveSection) CollapseRow(id string)

CollapseRow collapses a row to hide its expanded content.

func (*LiveSection) ExpandAll

func (ls *LiveSection) ExpandAll()

ExpandAll expands all rows in the LiveSection that have expanded content.

func (*LiveSection) ExpandRow

func (ls *LiveSection) ExpandRow(id string)

ExpandRow expands a row to show its expanded content.

func (*LiveSection) GetRows

func (ls *LiveSection) GetRows() []*LiveRow

GetRows returns a snapshot of all rows in the LiveSection.

func (*LiveSection) RemoveRow

func (ls *LiveSection) RemoveRow(id string)

RemoveRow removes a row from the LiveSection.

func (*LiveSection) SetExpandedContent

func (ls *LiveSection) SetExpandedContent(id string, expandedContent []string)

SetExpandedContent sets the expanded content for a row.

func (*LiveSection) ToggleRowExpansion

func (ls *LiveSection) ToggleRowExpansion(id string)

ToggleRowExpansion toggles the expansion state of a row.

func (*LiveSection) UpdateRow

func (ls *LiveSection) UpdateRow(id, content string)

UpdateRow updates the content of an existing row.

type MetricLine

type MetricLine struct {
	Label string // e.g., "Total files"
	Value string // e.g., "367"
	Trend string // e.g., "↑", "↓", "" (empty for no trend)
	Color string // Optional color for the value (e.g., "success", "warning", "error")
}

MetricLine represents a key-value metric with optional trend indicator. Example: "Total files: 367 ↑".

type Processor

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

Processor handles processing of command output, including classification and adapter-based parsing.

func NewProcessor

func NewProcessor(
	patternMatcher *design.PatternMatcher,
	adapterRegistry *adapter.Registry,
	maxLineLength int,
	debug bool,
) *Processor

NewProcessor creates a new Processor with the given configuration.

func (*Processor) ProcessOutput

func (p *Processor) ProcessOutput(
	task *design.Task,
	output []byte,
	command string,
	args []string,
)

ProcessOutput processes buffered output, attempting adapter-based parsing first, then falling back to line-by-line classification.

func (*Processor) ProcessStream

func (p *Processor) ProcessStream(
	input io.Reader,
	command string,
	args []string,
	onLine LineCallback,
) error

ProcessStream processes input from an io.Reader line-by-line, calling onLine for each classified line. This enables live rendering as output arrives.

The processor buffers the first N lines for adapter detection. If an adapter matches, it processes buffered lines through the adapter, then streams the rest. Otherwise, it falls back to line-by-line classification.

type ProfileData

type ProfileData struct {
	Stage          string        `json:"stage"`
	Duration       time.Duration `json:"duration"`
	DurationMs     int64         `json:"duration_ms"`
	PatternMatches int           `json:"pattern_matches,omitempty"`
	PatternSuccess int           `json:"pattern_success,omitempty"`
	BufferSize     int64         `json:"buffer_size,omitempty"`
	LineCount      int           `json:"line_count,omitempty"`
	MemoryAlloc    int64         `json:"memory_alloc,omitempty"`
}

ProfileData tracks performance metrics for each pipeline stage.

type Profiler

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

Profiler tracks performance metrics throughout command execution.

func NewProfiler

func NewProfiler(enabled bool, output string) *Profiler

NewProfiler creates a new profiler instance.

func (*Profiler) EndStage

func (p *Profiler) EndStage(name string, start time.Time, metrics map[string]interface{})

EndStage records the duration of a performance stage.

func (*Profiler) StartStage

func (p *Profiler) StartStage(_ string) time.Time

StartStage marks the start of a performance stage.

func (*Profiler) Write

func (p *Profiler) Write() error

Write outputs the profile data to the configured destination.

type ProjectConfig

type ProjectConfig struct {
	// Theme settings
	Theme string `yaml:"theme"` // Theme name: "orca", "unicode_vibrant", "ascii_minimal"

	// Project metadata (for display in headers)
	Project struct {
		Name string `yaml:"name"` // Project name for headers
	} `yaml:"project"`

	// File size thresholds
	FileSizes struct {
		WarnLines      int `yaml:"warn_lines"`       // Warn when files exceed (default: 500)
		ErrorLines     int `yaml:"error_lines"`      // Error when files exceed (default: 1000)
		WarnTestLines  int `yaml:"warn_test_lines"`  // Warn for test files (default: 800)
		ErrorTestLines int `yaml:"error_test_lines"` // Error for test files (default: 1400)
		TopFilesCount  int `yaml:"top_files_count"`  // Show top N files (default: 5)
		WarnMarkdown   int `yaml:"warn_markdown"`    // Warn on markdown count (default: 50)
	} `yaml:"file_sizes"`

	// Directories to skip during analysis
	SkipDirs []string `yaml:"skip_dirs"` // Additional dirs to skip (vendor, node_modules always skipped)

	// Snapshot storage
	SnapshotDir string `yaml:"snapshot_dir"` // Directory for storing snapshots (default: ".fo")

	// Section configurations
	Sections struct {
		Dependencies struct {
			Enabled bool `yaml:"enabled"` // Run dependency section (default: true)
		} `yaml:"dependencies"`
		FileSizes struct {
			Enabled bool `yaml:"enabled"` // Run file sizes section (default: true)
		} `yaml:"file_sizes"`
		Build struct {
			Enabled   bool   `yaml:"enabled"`    // Run build section (default: true)
			OutputDir string `yaml:"output_dir"` // Binary output directory (default: ".")
		} `yaml:"build"`
		Test struct {
			Enabled      bool   `yaml:"enabled"`       // Run test section (default: true)
			CoverageFile string `yaml:"coverage_file"` // Coverage output file
		} `yaml:"test"`
		Lint struct {
			Enabled bool `yaml:"enabled"` // Run lint section (default: true)
		} `yaml:"lint"`
	} `yaml:"sections"`
}

ProjectConfig represents project-specific fo configuration. This is loaded from .fo.yaml in the project root.

func DefaultProjectConfig

func DefaultProjectConfig() *ProjectConfig

DefaultProjectConfig returns a ProjectConfig with sensible defaults.

func LoadProjectConfig

func LoadProjectConfig() *ProjectConfig

LoadProjectConfig loads configuration from .fo.yaml, falling back to defaults.

func (*ProjectConfig) ToFileSizeConfig

func (p *ProjectConfig) ToFileSizeConfig() FileSizeConfig

ToFileSizeConfig converts project config to FileSizeConfig.

type ProjectLayout

type ProjectLayout struct {
	TopDirs      []string
	ModulePrefix string
	GroupFunc    func(pkgPath string) string
}

ProjectLayout configures how to extract group names from package paths.

type RankedItem

type RankedItem struct {
	Rank  int    // 1-based rank
	Value string // The metric value (e.g., "2562")
	Label string // Description (e.g., "internal/server/handler.go")
	Color string // Optional color for the value
}

RankedItem represents an item in a ranked/numbered list.

type Section

type Section struct {
	Name        string      // Human-readable section name, shown in header
	Description string      // Optional description
	Summary     string      // Optional summary message (shown instead of name/description on success)
	Run         SectionFunc // Work to perform for this section
}

Section represents a unit of orchestration with a name and work function.

type SectionFunc

type SectionFunc func() error

SectionFunc is a function that performs work for a section.

type SectionResult

type SectionResult struct {
	Name     string
	Status   SectionStatus
	Duration time.Duration
	Err      error
	Summary  string // Optional summary message from the section
}

SectionResult contains the outcome of running a section.

type SectionStatus

type SectionStatus string

SectionStatus represents the outcome status of a section execution.

const (
	// SectionOK indicates the section completed successfully.
	SectionOK SectionStatus = "ok"
	// SectionWarning indicates the section completed with warnings.
	SectionWarning SectionStatus = "warning"
	// SectionError indicates the section failed.
	SectionError SectionStatus = "error"
)

type SectionWarningError

type SectionWarningError struct {
	Err error
}

SectionWarningError is a special error type that signals a section completed with warnings but should not be treated as a fatal error.

func (*SectionWarningError) Error

func (e *SectionWarningError) Error() string

Error implements the error interface.

func (*SectionWarningError) Unwrap

func (e *SectionWarningError) Unwrap() error

Unwrap returns the underlying error for error wrapping compatibility.

type SparklineData

type SparklineData struct {
	Label    string // Row label (e.g., "Week -1")
	Segments []SparklineSegment
}

SparklineData represents data for a sparkline chart.

type SparklineSegment

type SparklineSegment struct {
	Proportion float64 // 0.0 to 1.0
	Color      string  // Color name (e.g., "success", "warning", "error")
}

SparklineSegment represents one colored segment of a sparkline.

type SubtestConfig

type SubtestConfig struct {
	GroupByParent    bool
	IndentSize       int
	ShowParentStatus bool
	HumanizeNames    bool
}

SubtestConfig configures how subtests are rendered.

type TaskResult

type TaskResult struct {
	Label    string
	Intent   string
	Status   string
	Duration time.Duration
	ExitCode int
	Lines    []Line
	Err      error
}

func (*TaskResult) ToJSON

func (r *TaskResult) ToJSON() ([]byte, error)

ToJSON converts TaskResult to JSON format for structured output.

type TestPackageResult

type TestPackageResult struct {
	Name        string
	Passed      int
	Failed      int
	Skipped     int
	Duration    time.Duration
	Coverage    float64
	FailedTests []string
	AllTests    []TestResult // All tests with their status (when ShowAllTests is enabled)
}

TestPackageResult represents the results for a single test package.

type TestRenderer

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

TestRenderer renders test results in a clean tree-style format.

func NewTestRenderer

func NewTestRenderer(console *Console, writer io.Writer) *TestRenderer

NewTestRenderer creates a new test renderer.

func (*TestRenderer) GetConfig

func (r *TestRenderer) GetConfig() TestTableConfig

GetConfig returns the current test table configuration.

func (*TestRenderer) GetGroupName

func (r *TestRenderer) GetGroupName(pkgPath string) string

GetGroupName extracts a group name from a package path.

func (*TestRenderer) RenderAll

func (r *TestRenderer) RenderAll()

RenderAll outputs the complete test summary. Call this after all groups have been added.

func (*TestRenderer) RenderGroupFooter

func (r *TestRenderer) RenderGroupFooter()

RenderGroupFooter finishes the current group.

func (*TestRenderer) RenderGroupHeader

func (r *TestRenderer) RenderGroupHeader(dirName string)

RenderGroupHeader starts collecting packages for a group.

func (*TestRenderer) RenderPackageLine

func (r *TestRenderer) RenderPackageLine(pkg TestPackageResult)

RenderPackageLine adds a package to the current group.

func (*TestRenderer) RenderTableHeader

func (r *TestRenderer) RenderTableHeader()

RenderTableHeader is now a no-op - header rendered in RenderSummary.

func (*TestRenderer) SetConfig

func (r *TestRenderer) SetConfig(config TestTableConfig)

SetConfig updates the test table configuration.

type TestResult

type TestResult struct {
	Name   string
	Status string // "PASS", "FAIL", "SKIP"
}

TestResult represents a single test with its status.

type TestSummary

type TestSummary struct {
	Passed   int
	Failed   int
	Skipped  int
	Total    int
	Coverage float64
}

TestSummary contains aggregated test results.

type TestTableConfig

type TestTableConfig struct {
	// SparkbarFilled is the character used for filled portions of the sparkbar
	SparkbarFilled string
	// SparkbarEmpty is the character used for empty portions of the sparkbar
	SparkbarEmpty string
	// SparkbarLength is the number of characters in the sparkbar
	SparkbarLength int
	// CoverageThresholds defines the coverage ranges for color coding
	CoverageThresholds []CoverageThreshold
	// ShowPercentage controls whether to show percentage after sparkbar
	ShowPercentage bool
	// UseTreeChars controls whether to use tree characters (├─, └─)
	UseTreeChars bool
	// NoTestIcon is the icon to use for packages with no tests
	NoTestIcon string
	// NoTestColor is the color key for packages with no tests
	NoTestColor string
	// ShowAllTests controls whether to show all tests (including passed) with their status
	ShowAllTests bool
	// SubtestConfig controls subtest hierarchy rendering
	SubtestConfig SubtestConfig
	// ProjectLayout configures how to extract group names from package paths
	ProjectLayout ProjectLayout
}

TestTableConfig configures how test results are rendered.

Jump to

Keyboard shortcuts

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