clip

package module
v0.0.0-...-5e935e4 Latest Latest
Warning

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

Go to latest
Published: Jun 27, 2025 License: MIT Imports: 12 Imported by: 0

README

Clip

Clip is a highly opinionated, highly unstable library for building command-line applications.

Warning: Clip is currently incomplete software and should not yet be used by anyone.

Quick Start

To get an app running requires no special configuration and does not prescribe any directory structure. For an app named my-app:

package main

import (
  "log"
  "os"

  "github.com/rliebz/clip"
)

func main() {
  // Create a command-line application
  app := clip.NewCommand("my-app")

  // Run it
  os.Exit(app.Run())
}

By default, commands with no action specified print the help documentation:

$ my-app
my-app

Options:
  -h, --help  Print help and exit

Since this app doesn't do anything, the help documentation isn't very useful. Commands can be configured by passing a list of functional options, such as clip.CommandSummary for a one-line summary, or clip.CommandDescription for a slightly longer description:

app := clip.NewCommand(
  "my-app",
  clip.CommandSummary("A command-line application"),
  clip.CommandDescription(`This is a simple "Hello World" demo application.`),
)

os.Exit(app.Run())

Now when running my-app:

$ my-app
my-app - A command-line application

This is a simple "Hello World" demo application.

Options:
  -h, --help  Print help and exit

Let's add a sub-command using clip.SubCommand and functionality using clip.CommandAction:

app := clip.NewCommand(
  "my-app",
  clip.CommandSummary("A command-line application"),
  clip.CommandDescription(`This is a simple "Hello World" demo application.`),
  clip.SubCommand(
    "hello",
    clip.CommandSummary("Greet the world"),
    clip.CommandAction(func(ctx *clip.Context) error {
      fmt.Println("Hello, world!")
      return nil
    }),
  ),
)

// Run it
os.Exit(app.Run())

Sub-commands also appear in the help documentation:

$ my-app
my-app - A command-line application

This is a simple "Hello World" demo application.

Commands:
  hello  Greet the world

Options:
  -h, --help  Print help and exit

$ my-app hello --help
my-app hello - Greet the world

Options:
  -h, --help  Print help and exit

And the command can be run:

$ my-app hello
Hello, world!
Arguments

By default, any unexpected arguments passed to a command are considered an error.

To make arguments available as a slice from an action's context, the function clip.CommandArgs can be used:

var args []string
hello := clip.NewCommand(
  "hello",
  clip.CommandArgs(&args),
  clip.CommandAction(func (ctx *clip.Context) error {
    fmt.Println("Args: ", args)
    return nil
  }),
)

Generally, however, it is better to explicitly define the arguments. This gives the benefit of documentation, validation, and tab-completion.

name := "World"
hello := clip.NewCommand(
  "hello",
  clip.CommandSummary("Greet the world"),
  clip.StringArg(
    &name,
    "name",
    clip.ArgOptional,
    clip.ArgSummary("The person to greet"),
    clip.ArgValues([]string{"Alice", "Bruce", "Carl"}),
  ),
  clip.CommandAction(func(ctx *clip.Context) error {
    greeting := fmt.Sprintf("Hello, %s\n", name)
    fmt.Println(greeting)
    return nil
  }),
)

This produces an app with the following behavior:

$ my-app hello --help
my-app hello - Greet the world

Usage:
  my-app hello [<name>]

Args:
  name  The person to greet
        One of: Alice, Bruce, Carl

Options:
  -h, --help  Print help and exit

$ my-app hello
Hello, World!

$ my-app hello Alice
Hello, Alice!

$ my-app hello Alex
Error: argument "Alex" must be one of: Alice, Bruce, Carl

Arguments and sub-commands are mutually exclusive.

Flags

The -h/--help flag is defined by default.

To create a flag that prints the version and exits, use an action flag:

version := "v0.1.0"
app := clip.NewCommand(
  "app",
  clip.ToggleFlag(
    "version",
    clip.FlagShort("V"),
    clip.FlagDescription("Print the version and exit"),
    clip.FlagAction(func(ctx *clip.Context) error {
      fmt.Println(version)
      return nil
    })
  ),
)

Flags can be created with different types, such as bool and string:

loud := false
name := "world"
hello := clip.NewCommand(
  "hello",
  clip.CommandSummary("Greet the world"),
  clip.BoolFlag(
    &loud,
    "loud",
    clip.FlagDescription("Whether to pump up the volume to max"),
  ),
  clip.StringFlag(
    &name,
    "name",
    clip.FlagShort("l"),
    clip.FlagDescription("Who to greet"),
  ),
  clip.CommandAction(func(ctx *clip.Context) error {
    greeting := fmt.Sprintf("Hello, %s!", name)
    if loud {
      greeting = strings.ToUpper(greeting)
    }
    fmt.Println(greeting)

    return nil
  }),
)

Flags are defined using POSIX/GNU-style flags, with --foo for a flag named "foo", and a short, one character flag prefixed with - if specified.

$ my-app hello --help
my-app hello - Greet the world

Usage:
  my-app hello [options]

Flags:
  -l, --loud  Whether to pump up the volume to max
      --name  Who to greet
  -h, --help  Print help and exit

$ my-app hello
Hello, World!

$ my-app hello --loud
HELLO, WORLD!!!

$ my-app hello -l
HELLO, WORLD!!!

Documentation

Overview

Package clip is a library for building command-line applications.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CommandHidden

func CommandHidden(c *commandConfig)

CommandHidden hides a command from documentation.

func FlagHidden

func FlagHidden(c *flagConfig)

FlagHidden prevents the flag from being shown.

func NewExitError

func NewExitError(code int, message string) error

NewExitError creates an error with an associated exit code.

func NewExitErrorf

func NewExitErrorf(code int, format string, a ...any) error

NewExitErrorf creates an error with an associated exit code using fmt.Errorf semantics.

func WithExitCode

func WithExitCode(code int, err error) error

WithExitCode wraps an existing error with an associated exit code.

func WriteHelp

func WriteHelp(w io.Writer, ctx *Context) error

WriteHelp writes the command's help text to the given writer.

Types

type Command

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

Command is a command or sub-command that can be run from the command-line.

To create a new command with the default settings, use NewCommand.

func NewCommand

func NewCommand(name string, options ...CommandOption) *Command

NewCommand creates a new command given a name and command options.

By default, commands will print their help documentation when invoked.

func (*Command) Description

func (cmd *Command) Description() string

Description is a multi-line description of the command.

func (*Command) Execute

func (cmd *Command) Execute(args []string) error

Execute runs a command using given args and returns the raw error.

This function provides more fine-grained control than Run, and can be used in situations where handling arguments or errors needs more granular control.

func (*Command) Name

func (cmd *Command) Name() string

Name is the name of the command.

func (*Command) Run

func (cmd *Command) Run() int

Run runs a command.

The args passed should begin with the name of the command itself. For the root command in most applications, the args will be os.Args and the result should be passed to os.Exit.

func (*Command) Summary

func (cmd *Command) Summary() string

Summary is a one-line description of the command.

type CommandOption

type CommandOption func(*commandConfig)

An CommandOption is used to commandConfigure a new command.

func BoolFlag

func BoolFlag(value *bool, name string, options ...FlagOption) CommandOption

BoolFlag creates a new boolean flag.

func CommandAction

func CommandAction(action func(*Context) error) CommandOption

CommandAction sets a Command's behavior when invoked.

func CommandDescription

func CommandDescription(description string) CommandOption

CommandDescription adds a multi-line description to a command.

func CommandStderr

func CommandStderr(writer io.Writer) CommandOption

CommandStderr sets the writer for command error output.

func CommandStdout

func CommandStdout(writer io.Writer) CommandOption

CommandStdout sets the writer for command output.

func CommandSummary

func CommandSummary(summary string) CommandOption

CommandSummary adds a one-line description to a command.

func StringFlag

func StringFlag(value *string, name string, options ...FlagOption) CommandOption

StringFlag creates a new string flag.

func SubCommand

func SubCommand(name string, options ...CommandOption) CommandOption

SubCommand adds a sub-command.

func TextVarFlag

func TextVarFlag(value TextVar, name string, options ...FlagOption) CommandOption

TextVarFlag creates a new flag based on encoding.TextMarshaler and encoding.TextUnmarshaler.

func ToggleFlag

func ToggleFlag(name string, options ...FlagOption) CommandOption

ToggleFlag creates a new toggle flag.

Toggle flags have no associated value, but can be passed like boolean flags to toggle something on. This is the simplest way to create an action flag.

type Context

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

Context is a command context with runtime metadata.

func (*Context) Description

func (ctx *Context) Description() string

Description is a multi-line description of the command.

func (*Context) Name

func (ctx *Context) Name() string

Name is the name of the command.

func (*Context) Parent

func (ctx *Context) Parent() *Context

Parent is the context's parent context.

func (*Context) Root

func (ctx *Context) Root() *Context

Root is the context's root context.

func (*Context) Stderr

func (ctx *Context) Stderr() io.Writer

Stderr is the writer for the command error output.

func (*Context) Stdout

func (ctx *Context) Stdout() io.Writer

Stdout is the writer for the command output.

func (*Context) Summary

func (ctx *Context) Summary() string

Summary is a one-line description of the command.

type FlagOption

type FlagOption func(*flagConfig)

FlagOption is an option for creating a Flag.

func FlagAction

func FlagAction(action func(*Context) error) FlagOption

FlagAction sets the behavior of the flag to replace the command's action when set.

The action will occur if the flag is passed, regardless of the value.

func FlagDeprecated

func FlagDeprecated(derepcation string) FlagOption

FlagDeprecated adds a deprecation to a flag.

func FlagDescription

func FlagDescription(description string) FlagOption

FlagDescription adds a description to a flag.

Descriptions can span multiple lines.

func FlagEnv

func FlagEnv(env ...string) FlagOption

FlagEnv sets the list of environment variables for a flag.

Successive calls will replace earlier values.

func FlagHelpDefault

func FlagHelpDefault(value string) FlagOption

FlagHelpDefault sets the default value of a flag in help docs.

Help text will display non-zero values when possible. To disable, pass an empty string to this function.

func FlagPlaceholder

func FlagPlaceholder(name string) FlagOption

FlagPlaceholder sets the name of the flag's placeholder value.

func FlagShort

func FlagShort(name string) FlagOption

FlagShort adds a short name to a flag. Panics if the name is not exactly one ASCII character.

type TextVar

type TextVar interface {
	encoding.TextMarshaler
	encoding.TextUnmarshaler
}

TextVar can be marshaled to and from text.

This is the recommended interface to implement for custom types.

Jump to

Keyboard shortcuts

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