cli

package module
v0.0.0-...-02a4793 Latest Latest
Warning

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

Go to latest
Published: Jul 29, 2025 License: MIT Imports: 9 Imported by: 22

Documentation

Overview

Package cli provides a lightweight framework for creating command-line interfaces (CLIs). It supports defining commands as functions or objects, organizing them into subcommand groups, parsing flags using the [flag.FlagSet]s, and generating documentation via built-in commands: "help", "flags", and "commands".

Key features:

  • Commands defined as functions or objects implementing the Command interface.
  • Hierarchical subcommand groups.
  • Flag parsing using flag.FlagSet with custom error handling.
  • Automatic documentation through built-in commands.
  • Custom documentation using optional interfaces.
  • Context-aware execution for cancellation and timeouts.
  • Redirect a command's stdout to any io.Writer.

Create commands with NewCommand for functions, NewGroup for subcommands, or custom types implementing the Command interface. Execute the CLI by passing commands to Run with command-line arguments.

Example (Function-based command):

var listFlags flag.FlagSet
verbose := listFlags.Bool("v", false, "Enable verbose output")
listCmd := func(ctx context.Context, args []string) error {
    if *verbose {
        fmt.Println("Verbose listing")
    } else {
        fmt.Println("Listing")
    }
    return nil
}
cmd := cli.NewCommand("list", listCmd, &listFlags, "List resources")
cli.Run(context.Background(), []cli.Command{cmd}, os.Args)

Example (Object-based command):

type GreetCommand struct {
    name  string
}
func (c *GreetCommand) Command() (string, *flag.FlagSet, cli.CmdFunc) {
    fset := new(flag.FlagSet)
    fset.StringVar(&c.name, "name", "World", "Name to greet")
    return "greet", fset, func(ctx context.Context, args []string) error {
        fmt.Printf("Hello, %s!\n", c.name)
        return nil
    }
}
cmd := &GreetCommand{}
cli.Run(context.Background(), []cli.Command{cmd}, os.Args)

Optional interfaces for documentation:

type Purpose interface {
  // One line use or summary for the command.
  Purpose() string
}

type Description interface {
  // Multi line or multi-paragraph help for the command.
  Description() string
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Run

func Run(ctx context.Context, cmds []Command, args []string) error

Run executes the CLI, parsing arguments to invoke a command from the provided commands. It supports built-in "help", "flags", and "commands" for documentation and uses the context for cancellation. Returns an error if parsing or execution fails.

Example:

cmd := cli.NewCommand("version", versionCmd, nil, "Display version")
err := cli.Run(context.Background(), []cli.Command{cmd}, os.Args)

func Stdout

func Stdout(ctx context.Context) io.Writer

Stdout retrieves io.Writer meant to capture stdout from the input context. Returns os.Stdout when no such io.Writer is found.

func WithStdout

func WithStdout(ctx context.Context, w io.Writer) context.Context

WithStdout adds the input io.Writer to the input context. Command functions that wish to support different stdout backends can retrieve the io.Writer from the context.

Types

type CmdFunc

type CmdFunc func(ctx context.Context, args []string) error

CmdFunc defines the behavior of a CLI command. It accepts a context for cancellation and a slice of arguments (excluding the command name and flags), returning an error if execution fails.

Example:

cmd := func(ctx context.Context, args []string) error {
    fmt.Println("Hello, CLI")
    return nil
}
command := cli.NewCommand("hello", cmd, nil, "Print greeting")

type Command

type Command interface {
	// Command returns a command name, it's flags and the implementation
	// function.
	Command() (string, *flag.FlagSet, CmdFunc)
}

Command defines a CLI command or subcommand group. Implementations must provide a flag.FlagSet and CmdFunc via the Command method. The FlagSet's name serves as the command name and must be non-empty.

Commands may implement optional interfaces for documentation:

  • Purpose() string: Returns a brief description.
  • Description() string: Returns detailed help text.

Create commands using NewCommand, NewGroup, or custom types.

Example:

type VersionCommand struct {
    flags flag.FlagSet
}
func (c *VersionCommand) Command() (string, *flag.FlagSet, cli.CmdFunc) {
    c.flags.Init("version", flag.ContinueOnError)
    return "version", c.flags, func(ctx context.Context, args []string) error {
        fmt.Println("Version 1.0.0")
        return nil
    }
}

func NewCommand

func NewCommand(name string, cmd CmdFunc, fset *flag.FlagSet, purpose string) Command

NewCommand creates a function-based command with the specified name, function, flags, and a single line purpose. The flag.FlagSet is optional; if nil, no flags are supported. The package overrides flag.FlagSet's default error handling.

Returns nil if command name is empty.

Example:

var flags flag.FlagSet
name := flags.String("name", "World", "Name to greet")
cmd := func(ctx context.Context, args []string) error {
    fmt.Printf("Hello, %s!\n", *name)
    return nil
}
command := cli.NewCommand("greet", cmd, &flags, "Greet a user")

func NewGroup

func NewGroup(name, purpose string, cmds ...Command) Command

NewGroup creates a subcommand group with the specified name, purpose, and subcommands. Returns a Command, enabling nested command hierarchies. Returns nil if group name is empty.

Example:

startCmd := cli.NewCommand("start", startFunc, nil, "Start server")
stopCmd := cli.NewCommand("stop", stopFunc, nil, "Stop server")
group := cli.NewGroup("server", "Server operations", startCmd, stopCmd)

Jump to

Keyboard shortcuts

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