ctrl

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 14, 2026 License: BSD-3-Clause Imports: 6 Imported by: 0

README

ctrl

Zero-Dependency CLI Application Framework & Terminal UI Toolkit for Go

«In the terminal, latency and clutter are the default — let ctrl be your sharp, zero-dependency command surface»

Go Version Go Reference License Zero-Dependencies Zero-Alloc Ecosystem POSIX Semantics

ctrl is a zero-dependency CLI application framework and terminal UI toolkit for Go. It provides full POSIX flag parsing with short-flag clumping and attached values, subcommand routing with command grouping, terminal capability sniffing, and terminal UI styling primitives (tables, boxes, progress bars, sparklines, badges) built entirely on Go standard library primitives.

English • Русский • Architecture Concept

Installation

ctrl requires Go version 1.27 or higher.

go get github.com/lemon4ksan/ctrl

Quickstart

Build a CLI tool with subcommands, POSIX flag clumping, and styled terminal output in minutes:

package main

import (
	"context"
	"flag"
	"fmt"
	"io"
	"os"

	"github.com/lemon4ksan/ctrl"
	"github.com/lemon4ksan/ctrl/tuikit"
)

func main() {
	app := ctrl.NewApp("seal", ctrl.Version, "High-performance compression & archiving utility",
		ctrl.NewCommand("create", "Create an archive from files", "seal create [flags] <archive> <files...>",
			func(ctx context.Context, args []string, stdout, stderr io.Writer) error {
				fs := flag.NewFlagSet("create", flag.ContinueOnError)
				level := fs.Int("l", 3, "Compression level (1-9)")
				verbose := fs.Bool("v", false, "Verbose output")

				posArgs, err := ctrl.ParseInterspersedFlags(fs, args)
				if err != nil {
					return err
				}

				if len(posArgs) < 2 {
					return fmt.Errorf("archive path and target files required")
				}

				fmt.Fprintf(stdout, "%s Creating archive %s (level %d, verbose=%v)\n",
					tuikit.BadgePass(), posArgs[0], *level, *verbose)
				return nil
			},
			"c", "add",
		),
	)

	app.CommandGroups = []ctrl.CommandGroup{
		{
			Title:    "Core Operations",
			Commands: []string{"create"},
		},
	}

	if err := app.Run(context.Background(), os.Args[1:]); err != nil {
		fmt.Fprintf(os.Stderr, "%s %v\n", tuikit.BadgeFail(), err)
		os.Exit(1)
	}
}

Features & Architectural Pillars

Capability Standard Library (flag) spf13/cobra ctrl
External Dependencies 0 ~15+ transitive 0
Interspersed Flags ✗ (halts at first positional) ✓ ✓ (argkit)
Short Flag Clumping (-la) ✗ ✓ ✓ (argkit)
Attached Values (-I*.tmp) ✗ ✓ ✓ (argkit)
Fuzzy Typo Suggestions ✗ ✓ ✓ (Levenshtein)
Subcommand Routing ✗ ✓ ✓ (tuikit.App)
Terminal Capability Sniffing ✗ ✗ (separate lib) ✓ (tuikit.ProbeTerminal)
NO_COLOR & TTY Awareness ✗ ✗ ✓ (Built-in)
Tables, Boxes, Progress Bars ✗ ✗ (needs lipgloss) ✓ (tuikit)

Subpackages Overview

1. argkit — POSIX Argument & Flag Engine
  • Interspersed Arguments: Mix options and positional arguments freely (app -v src/ -o=bin dst/).
  • Short Flag Clumping: -la automatically unpacks into -l and -a.
  • Attached Values: -I*.tmp maps directly to -I=*.tmp.
  • POSIX Terminator: -- treats all subsequent tokens as raw positional arguments.
  • Fuzzy Suggestions: Suggests corrections for mistyped flags using stack-allocated Levenshtein distance ("flag provided but not defined: --timout (did you mean: --timeout?)").
  • Shell Normalization: Resolves argument splitting bugs caused by PowerShell and CMD shell tokenizers (argkit.NormalizeArgs).
2. tuikit — Terminal UI & CLI App Router
  • Subcommand App Router (tuikit.App): Handles command routing, aliases, grouped help listings, and default fallback commands.
  • Terminal Prober (tuikit.ProbeTerminal): Sniffs TTY interactive status and enables Virtual Terminal escape processing on Windows 10/11.
  • Auto-Aligned Tables (tuikit.Table): Pixel-perfect column formatting with left, right, and center alignments.
  • Bordered Boxes (tuikit.Box): Clean bordered card containers (BorderSingle, BorderRounded, BorderHeavy) with guaranteed straight right borders.
  • Live Progress & Throughput (tuikit.Progress): Real-time progress bars with throughput rate (MB/s or items/s) and ETA calculations. Gracefully falls back to periodic summary logs in CI/CD or piped output.
  • Sparklines & Trend Graphs (tuikit.RenderSparkline): Renders inline trend graphs from floating-point sequences ( ▂▃▅▆▇█).
  • Badges & Pipeline Steps: Universal status tags (BadgePass, BadgeFail, BadgeWarn, BadgeActive) and numbered pipeline stages (RenderStep).

Performance & Zero-Allocation Guarantees

Tested under parallel CPU load:

  • VisibleWidth: Monospaced width calculation runs without heap allocations.
  • Levenshtein & Typo Suggest: Uses stack-allocated arrays for strings up to 64 runes, guaranteeing 0 allocs/op during interactive CLI flag validation.
  • LinesSeq: Go 1.27 push iterator over string lines without intermediate slice allocations.

Contributing & Development

# Run unit tests
make test

# Run tests with race detector
make race

# Run code linters
make lint

# Run benchmark suite
make bench

📄 License

This project is licensed under the BSD 3-Clause License. See the LICENSE file for details.

Documentation

Overview

Package ctrl provides a unified, zero-dependency CLI application framework and high-performance terminal UI toolkit for Go.

It consolidates POSIX argument and flag parsing (argkit), subcommand routing, terminal capability sniffing, and terminal UI styling primitives (tuikit) into a single, cohesive architecture.

Architectural Foundations

Basic Usage

package main

import (
	"context"
	"fmt"
	"io"
	"os"

	"github.com/lemon4ksan/ctrl"
	"github.com/lemon4ksan/ctrl/tuikit"
)

func main() {
	app := ctrl.NewApp("mycli", ctrl.Version, "High-performance CLI utility",
		ctrl.NewCommand("hello", "Print a greeting", "mycli hello [name]",
			func(ctx context.Context, args []string, stdout, stderr io.Writer) error {
				name := "World"
				if len(args) > 0 {
					name = args[0]
				}
				fmt.Fprintf(stdout, "%s Hello, %s!\n", tuikit.BadgePass(), name)
				return nil
			},
		),
	)

	if err := app.Run(context.Background(), os.Args[1:]); err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}
}
Example

Example demonstrates constructing a CLI application using ctrl.

package main

import (
	"context"
	"fmt"
	"io"

	"github.com/lemon4ksan/ctrl"
)

func main() {
	app := ctrl.NewApp("example", "1.0.0", "Minimal example CLI",
		ctrl.NewCommand("greet", "Print greeting message", "example greet [name]",
			func(ctx context.Context, args []string, stdout, stderr io.Writer) error {
				name := "World"
				if len(args) > 0 {
					name = args[0]
				}
				fmt.Fprintf(stdout, "Hello, %s!\n", name)
				return nil
			},
		),
	)

	_ = app.Run(context.Background(), []string{"greet", "Gopher"})
}
Output:
Hello, Gopher!

Index

Examples

Constants

View Source
const Version = "0.1.0"

Version is the current semantic release version of the ctrl framework.

Variables

View Source
var (
	Bold      = tuikit.Bold
	Dim       = tuikit.Dim
	Italic    = tuikit.Italic
	Underline = tuikit.Underline
	Red       = tuikit.Red
	Green     = tuikit.Green
	Yellow    = tuikit.Yellow
	Blue      = tuikit.Blue
	Magenta   = tuikit.Magenta
	Cyan      = tuikit.Cyan
	Gray      = tuikit.Gray
	White     = tuikit.White

	BadgePass   = tuikit.BadgePass
	BadgePassed = tuikit.BadgePassed
	BadgeWarn   = tuikit.BadgeWarn
	BadgeFail   = tuikit.BadgeFail
	BadgeInfo   = tuikit.BadgeInfo
	BadgeActive = tuikit.BadgeActive
	BadgeSync   = tuikit.BadgeSync

	StripANSI    = tuikit.StripANSI
	VisibleWidth = tuikit.VisibleWidth
	RenderStep   = tuikit.RenderStep
	RenderBar    = tuikit.RenderBar
)

Styling and badge re-exports for rapid zero-dependency console formatting.

View Source
var (
	// ErrUnknownCommand is returned when an unrecognized command name is invoked.
	ErrUnknownCommand = errors.New("ctrl: unknown command")

	// ErrMissingArgument is returned when required positional arguments are absent.
	ErrMissingArgument = errors.New("ctrl: missing required argument")

	// ErrFlagParsing is returned when flag decoding fails.
	ErrFlagParsing = errors.New("ctrl: flag parsing error")
)

Standard error definitions for the ctrl framework.

Functions

func ParseInterspersedFlags

func ParseInterspersedFlags(fs *flag.FlagSet, args []string) ([]string, error)

ParseInterspersedFlags parses a flag.FlagSet correctly with full POSIX semantics: clumping (-la), attached values (-I*.tmp), interspersed arguments, and typo suggestions.

Example

ExampleParseInterspersedFlags demonstrates parsing POSIX flags and positional arguments.

package main

import (
	"flag"
	"fmt"

	"github.com/lemon4ksan/ctrl"
)

func main() {
	fs := flag.NewFlagSet("build", flag.ContinueOnError)
	v := fs.Bool("v", false, "verbose")
	out := fs.String("o", "", "output binary")

	args := []string{"main.go", "-v", "-o=app.exe", "extra.go"}
	posArgs, _ := ctrl.ParseInterspersedFlags(fs, args)

	fmt.Printf("Verbose: %t\n", *v)
	fmt.Printf("Output: %s\n", *out)
	fmt.Printf("Positionals: %v\n", posArgs)
}
Output:
Verbose: true
Output: app.exe
Positionals: [main.go extra.go]

Types

type App

type App = tuikit.App

App manages the lifecycle, subcommand routing, help formatting, and execution of CLI tools.

func NewApp

func NewApp(name, version, description string, commands ...Command) *App

NewApp constructs a new CLI application instance.

type Box

type Box = tuikit.Box

Box formats enclosed text cards and panels with borders.

func NewBox

func NewBox(title string, innerWidth int) *Box

NewBox creates a new rectangular box card with the given title and inner width constraint.

Example

ExampleNewBox demonstrates creating an auto-sized bordered card panel.

package main

import (
	"os"

	"github.com/lemon4ksan/ctrl"
)

func main() {
	card := ctrl.NewBox("Status Card", 28)
	card.AddLine("Engine: OK")
	_ = card.Render(os.Stdout)
}

type Command

type Command = tuikit.Command

Command represents an isolated, testable CLI subcommand contract.

func NewCommand

func NewCommand(
	name, synopsis, usage string,
	run func(ctx context.Context, args []string, stdout, stderr io.Writer) error,
	aliases ...string,
) Command

NewCommand creates a functional subcommand adapter.

type CommandGroup

type CommandGroup = tuikit.CommandGroup

CommandGroup organizes subcommands under logical sections in help listings.

type FuncCommand

type FuncCommand = tuikit.FuncCommand

FuncCommand is a lightweight adapter creating a Command from functional closures.

type Progress

type Progress = tuikit.Progress

Progress manages live terminal feedback, throughput, ETA calculations, and progress rendering.

func NewProgress

func NewProgress(opts ...tuikit.ProgressOption) *Progress

NewProgress creates and initializes a new Progress widget.

type Table

type Table = tuikit.Table

Table manages columnar data formatting with guaranteed alignment.

func NewTable

func NewTable(headers ...string) *Table

NewTable constructs a new Table with the specified header titles.

Example

ExampleNewTable demonstrates creating an auto-aligned data table.

package main

import (
	"os"

	"github.com/lemon4ksan/ctrl"
)

func main() {
	tbl := ctrl.NewTable("Method", "Route", "Latency")
	tbl.AddRow("GET", "/health", "1.2 ms")
	_ = tbl.Render(os.Stdout)
}

Directories

Path Synopsis
Package argkit provides a zero-dependency POSIX argument and flag parsing engine.
Package argkit provides a zero-dependency POSIX argument and flag parsing engine.
Package tuikit provides a zero-dependency terminal UI toolkit for building CLI applications, REPLs, formatted tables, styled borders, badges, and progress indicators.
Package tuikit provides a zero-dependency terminal UI toolkit for building CLI applications, REPLs, formatted tables, styled borders, badges, and progress indicators.

Jump to

Keyboard shortcuts

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