clif

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Jan 25, 2026 License: MIT Imports: 15 Imported by: 1

Documentation

Overview

Package clif provides a framework for writing command line applications.

The framework starts with an Application, which defines some global flags that apply to all commands and the different Commands that the application accepts.

Each flag is defined by a FlagDef, which describes the flag name and any constraints on it.

Each Command describes the command name, any subcommands and flags it accepts, and other information about parsing the command and how to execute it.

Once input is matched to the Command, it calls the HandlerBuilder associated with that Command. The HandlerBuilder is responsible for turning flags and arguments into a Handler. It's separated out from the Handler so the business logic of the Handler can be separated out from the logic to parse the flags and arguments.

Finally, once we have a Handler, it gets executed, with a Response to write output to and record the desired exit code of the command.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrAppHasNoCommands is returned when an application does not define
	// any commands, which is invalid.
	ErrAppHasNoCommands = errors.New("application does not define any commands")
)

Functions

This section is empty.

Types

type Application

type Application struct {
	// Name is the name of the binary this application builds. Used when
	// generating help output.
	Name string

	// Version is the version of this application. Used when generating
	// help output.
	Version string

	// Description is a short, one-line description of the command, used
	// when generating help output.
	Description string

	// DetailedDescription is one or more paragraphs describing the
	// application, what it does, and what it's used for. Used when
	// generating help output.
	DetailedDescription string

	// Commands are the commands that the application supports.
	Commands []Command

	// Flags are the definitions for any global flags the application
	// supports.
	Flags []FlagDef

	Handler HandlerBuilder

	// HandlerMiddleware holds the middleware to run before executing the
	// HandlerBuilder of the Application. If any return false, the
	// HandlerBuilder will not be run. The context.Context and *Response
	// passed to the middleware will also be passed to the HandlerBuilder
	// and Handler; everything else is not guaranteed to persist any
	// changes the middleware makes.
	//
	// Middleware is largely intended to support use cases like checking
	// for a help flag being passed and printing the help output, or other
	// scenarios where invocation-time information (what command is being
	// run, what flags are set) is necessary but all or many handlers
	// should have consistent behavior.
	HandlerMiddleware []Middleware

	// GlobalMiddleware holds the middleware to run before executing the
	// any HandlerBuilder. If any return false, the HandlerBuilder will not
	// be run. The context.Context and *Response passed to the middleware
	// will also be passed to the HandlerBuilder and Handler; everything
	// else is not guaranteed to persist any changes the middleware makes.
	//
	// Middleware is largely intended to support use cases like checking
	// for a help flag being passed and printing the help output, or other
	// scenarios where invocation-time information (what command is being
	// run, what flags are set) is necessary but all or many handlers
	// should have consistent behavior.
	GlobalMiddleware []Middleware
}

Application is the root definition of a CLI.

Example
package main

import (
	"context"
	"fmt"

	"impractical.co/clif"
)

type funcCommandHandler func(ctx context.Context, resp *clif.Response)

func (f funcCommandHandler) Build(_ context.Context, _ clif.FlagSet, _ []string, _ *clif.Response) clif.Handler { //nolint:ireturn // filling an interface
	return f
}

func (f funcCommandHandler) Handle(ctx context.Context, resp *clif.Response) {
	f(ctx, resp)
}

type flagCommandHandler struct {
	flags clif.FlagSet
	args  []string
	f     func(ctx context.Context, flags clif.FlagSet, args []string, resp *clif.Response)
}

func (f flagCommandHandler) Build(_ context.Context, flags clif.FlagSet, args []string, _ *clif.Response) clif.Handler { //nolint:ireturn // filling an interface
	f.flags = flags
	f.args = args
	return f
}

func (f flagCommandHandler) Handle(ctx context.Context, resp *clif.Response) {
	f.f(ctx, f.flags, f.args, resp)
}

//nolint:errcheck // several places we're not checking errors because they can't fail
func main() {
	app := clif.Application{
		Commands: []clif.Command{
			{
				Name:        "help",
				Description: "Displays help information about this program.",
				Handler: funcCommandHandler(func(_ context.Context, resp *clif.Response) {
					resp.Output.Write([]byte("this is help information\n"))
				}),
			},
			{
				Name: "foo",
				Subcommands: []clif.Command{
					{
						Name: "bar",
						Flags: []clif.FlagDef{
							{
								Name: "--quux",
							},
						},
						Handler: flagCommandHandler{
							f: func(_ context.Context, flags clif.FlagSet, args []string, resp *clif.Response) {
								fmt.Fprintln(resp.Output, flags, args)
							},
						},
					},
				},
			},
		},
		Flags: []clif.FlagDef{
			{
				Name:     "--baaz",
				IsToggle: true,
			},
		},
	}
	res := app.Run(context.Background(), clif.WithArgs([]string{"help"}))
	fmt.Println(res)
	res = app.Run(context.Background(), clif.WithArgs([]string{"foo", "bar", "--quux", "hello"}))
	fmt.Println(res)
	res = app.Run(context.Background(), clif.WithArgs([]string{"foo", "--quux", "hello", "bar"}))
	fmt.Println(res)
	res = app.Run(context.Background(), clif.WithArgs([]string{"--quux", "hello", "foo", "bar"}))
	fmt.Println(res)
	res = app.Run(context.Background(), clif.WithArgs([]string{"foo", "bar", "--quux=hello"}))
	fmt.Println(res)
	res = app.Run(context.Background(), clif.WithArgs([]string{"foo", "--quux=hello", "bar"}))
	fmt.Println(res)
	res = app.Run(context.Background(), clif.WithArgs([]string{"--quux=hello", "foo", "bar"}))
	fmt.Println(res)
	res = app.Run(context.Background(), clif.WithArgs([]string{"--baaz", "foo", "bar", "--quux", "hello"}))
	fmt.Println(res)
}
Output:

this is help information
0
map[quux:[{true hello quux quux}]] []
0
map[quux:[{true hello quux quux}]] []
0
map[quux:[{true hello quux quux}]] []
0
map[quux:[{true hello quux quux}]] []
0
map[quux:[{true hello quux quux}]] []
0
map[quux:[{true hello quux quux}]] []
0
map[baaz:[{false  baaz baaz}] quux:[{true hello quux quux}]] []
0

func (Application) Run

func (app Application) Run(ctx context.Context, opts ...RunOption) int

Run executes the invoked command. It routes the input to the appropriate Command, parses it with the HandlerBuilder, and executes the Handler. The return is the status code the command has indicated it exited with.

func (Application) Validate added in v0.1.0

func (app Application) Validate(ctx context.Context) error

Validate determines whether an Application has a valid definition or not.

type Command

type Command struct {
	// Name is the name of the command, what the user will type to prompt
	// its functionality.
	Name string

	// Aliases are acceptable variations on Name; they will be treated as
	// equivalent to Name, but will not be listed in the SubcommandsHelp
	// output.
	Aliases []string

	// Description is a short, one-line description of the command, used
	// when generating help output.
	Description string

	// DetailedDescription is one or more paragraphs describing the
	// command, what it does, and what it's used for. Used when generating
	// help output.
	DetailedDescription string

	// UsageExample is an example of how the command is meant to be used,
	// displayed as part of help output.
	UsageExample string

	// Hidden indicates whether a command should be included in
	// SubcommandsHelp output or not. If set to true, the command will be
	// omitted from SubcommandsHelp output.
	Hidden bool

	// ArgsAccepted indicates whether free input is expected as part of
	// this command. If true, this command cannot have any subcommands.
	ArgsAccepted bool

	// Flags holds definitions for the flags, if any, that this command
	// accepts.
	Flags []FlagDef

	// Subcommands are the various subcommands, if any, that this command
	// accepts.
	Subcommands []Command

	// Handler is the HandlerBuilder executed when this Command is used.
	// The Handler will not be executed if a subcommand of this Command is
	// used.
	Handler HandlerBuilder

	// Middleware holds the middleware to run before executing the Command.
	// If any return false, the Handler will not be run. The
	// context.Context and *Response passed to the middleware will also be
	// passed to the HandlerBuilder and Handler; everything else is not
	// guaranteed to persist any changes the middleware makes.
	//
	// Middleware is largely intended to support use cases like checking
	// for a help flag being passed and printing the help output, or other
	// scenarios where invocation-time information (what command is being
	// run, what flags are set) is necessary but all or many handlers
	// should have consistent behavior.
	Middleware []Middleware
}

Command defines a command the user can run. Commands can have handlers, that get invoked when the command is run, and subcommands, which are other commands namespaced under their command. Commands with subcommands can still be invoked, and should still have a handler defined, even if it just prints out usage information on the subcommands.

func (Command) Validate added in v0.1.0

func (cmd Command) Validate(ctx context.Context, path []string, parentFlags map[string]struct{}) error

Validate determines whether a Command has a valid definition or not.

type CommandAcceptsArgumentsAndSubcommandsError added in v0.1.0

type CommandAcceptsArgumentsAndSubcommandsError struct {
	// Path indicates that parents, if any, of the Command that accepts
	// both arguments and subcommands. The Command in question will be the
	// last entry in the slice.
	Path []string
}

CommandAcceptsArgumentsAndSubcommandsError is returned when a Command is defined that accepts both arguments and subcommands, which is invalid. A Command may only accept one.

func (CommandAcceptsArgumentsAndSubcommandsError) Error added in v0.1.0

type CommandAliasEmptyError added in v0.1.0

type CommandAliasEmptyError struct {
	// Path is the list of parents, if any, of the Command with an empty
	// string in the Aliases slice. If empty, this indicates the Command is
	// in Application.Commands.
	Path []string

	// Command is the name of the Command with an empty string in its
	// Aliases list.
	Command string
}

CommandAliasEmptyError is returned when the [Command.Alias] property includes an empty string, which is invalid.

func (CommandAliasEmptyError) Error added in v0.1.0

func (err CommandAliasEmptyError) Error() string

type CommandDuplicatesNameAsAliasError added in v0.1.0

type CommandDuplicatesNameAsAliasError struct {
	// Path indicates the parents, if any, of the Command that duplicated
	// its Name property into its Aliases property. If Path is empty, that
	// indicates the Command is defined in Application.Commands. Otherwise,
	// the Command is defined in the Subcommands property of the Command
	// named by the last element of the slice.
	Path []string

	// Command is the name that was included as both a Name and in the
	// Aliases.
	Command string
}

CommandDuplicatesNameAsAliasError is returned when a Command has the same value used in its Name property in its Aliases property, which is invalid.

func (CommandDuplicatesNameAsAliasError) Error added in v0.1.0

type CommandMissingNameError added in v0.1.0

type CommandMissingNameError struct {
	// Pos is the position of the Command in Application.Commands or
	// Command.Subcommands without a Name property set. Because there's no
	// Name property, we have no other way to indicate which Command we're
	// talking about.
	Pos int

	// Path is the list of Commands that were traversed to get to the
	// Command that's missing a Name. An empty slice indicates the Command
	// is defined in Application.Commands. Otherwise, the Command is
	// defined in the Subcommands property of the last Command in the
	// slice.
	Path []string
}

CommandMissingNameError is returned when a Command, either defined on [Application.Commands] or [Command.Subcommands], doesn't have its Name property set.

func (CommandMissingNameError) Error added in v0.1.0

func (err CommandMissingNameError) Error() string

type CommandMissingSubcommandsOrHandlerError added in v0.1.0

type CommandMissingSubcommandsOrHandlerError struct {
	// Path indicates that parents, if any, of the Command with no
	// Subcommands or Handler defined. The Command in question will be the
	// last entry in the slice.
	Path []string
}

CommandMissingSubcommandsOrHandlerError is returned when a Command has no Subcommands or Handler set, meaning it can't do anything, which is invalid.

func (CommandMissingSubcommandsOrHandlerError) Error added in v0.1.0

type DefInjector added in v0.2.0

type DefInjector interface {
	HandlerBuilder
	InjectDefs(ctx context.Context, defs DefParams, resp *Response)
}

DefInjector is an interface that a HandlerBuilder can optionally implement. If implemented, the InjectDefs method will be called to make the DefParams available at runtime to the HandlerBuilder before [HandlerBuilder.Build] is called.

type DefParams added in v0.2.0

type DefParams struct {
	CommandPath     []Command
	Command         *Command
	AcceptableFlags []FlagDef
	App             Application
}

DefParams holds a parameter bundle of the definitions that are relevant to a given execution. A definition is relevant to a given execution if it's a Command in the command path of a Command that has been routed to, the Command that has been routed to, the root Application, or a FlagDef that is set on any of those [Command]s or the Application.

type DuplicateCommandError added in v0.1.0

type DuplicateCommandError struct {
	// Path is the list of parents, if any, of the Commands that have
	// reused the same name or alias. If empty, this indicates that
	// Application.Commands are in conflict; otherwise, the last element in
	// the slice is the Command containing the conflicting Commands.
	Path []string

	// Command is the name that has been reused.
	Command string
}

DuplicateCommandError is returned when a Command is defined in the an [Application.Commands] or [Command.Subcommands] that already uses the [Command.Name] or one of the [Command.Aliases] for another Command. [Command.Name] and [Command.Aliases] must be unique within their parent.

func (DuplicateCommandError) Error added in v0.1.0

func (err DuplicateCommandError) Error() string

type DuplicateFlagNameError

type DuplicateFlagNameError string

DuplicateFlagNameError is returned when multiple Commands use the same flag name, and it would be ambiguous which Command the flag applies to. The underlying string will be the flag name, without leading --.

func (DuplicateFlagNameError) Error

func (err DuplicateFlagNameError) Error() string

type FlagDef

type FlagDef struct {
	// Name is the name of the flag. It's what will be surfaced in
	// documentation and what the user will use when applying the flag to a
	// command. Names must be unique across the command and all parent or
	// child commands, or the parser won't know which command to apply the
	// flag to.
	Name string

	// Aliases holds any alternative names the flag should accept from the
	// user. Aliases are not surfaced in documentation, by default. Aliases
	// must be unique across all other aliases and names for the command
	// and all parent or child commands, or the parser won't know which
	// command to apply the flag to.
	Aliases []string

	// Description is a user-friendly description of what the flag does and
	// what it's for, to be presented as part of help output.
	Description string

	// OnlyToggle indicates whether or not the flag should allow a value.
	// If set to true, attempting to pass a value will surface an error.
	//
	// If OnlyToggle is true, IsToggle must also be true.
	OnlyToggle bool

	// IsToggle indicates whether or not the flag should require a value.
	// If set to false, attempting to not pass a value with surface an
	// error.
	IsToggle bool

	// AllowMultiple indicates whether multiple instances of this flag
	// should be accepted, with the values returned as a list. False means
	// that specifying the flag more than once will result in an error.
	AllowMultiple bool

	// FromEnvVars indicates which, if any, environment variables should be
	// used as default values if the flag isn't specified. FromEnvVars
	// should be set to the list of environment variables to check, and the
	// first one to hold a non-empty value will be used as the flag value.
	//
	// It's important to note that the calling application will not be able
	// to distinguish between a flag value set via environment variable and
	// via actual flag; they'll appear the same. If you need to distinguish
	// between those cases, do not use FromEnvVars, and check the
	// environment variable(s) yourself in the Build method of your
	// [HandlerBuilder].
	FromEnvVars []string

	// Default sets the default values of this flag if it's not specified.
	// If FromEnvVars is set, the flag must not be specified in the
	// invocation or in the environment variables before the default will
	// be used.
	//
	// It's important to note that the calling application will not be able
	// to distinguish between a flag value set via this default value and
	// via actual flag; they'll appear the same. If you need to distinguish
	// between those cases, do not use Default, and instead set the value
	// yourself in the Build method of your [HandlerBuilder].
	Default FlagValues
}

FlagDef describes the definition of a flag. [Application]s and [Command]s will use FlagDefs to describe what flags they accept.

func (FlagDef) Validate added in v0.1.0

func (def FlagDef) Validate(_ context.Context, path []string) error

Validate determines whether a FlagDef is valid or not.

type FlagKeyNotInStructError added in v0.1.0

type FlagKeyNotInStructError struct {
	// Key is the flag key that was not defined in the struct.
	Key string

	// StructType is the package-delimited type of the struct that was
	// missing the flag key.
	StructType string
}

FlagKeyNotInStructError is returned when a flag key is passed during invocation that isn't found in the struct being parsed into. This usually indicates that a struct doesn't have a field for every defined flag; flags with no FlagDef will return an UnknownFlagNameError instead.

func (FlagKeyNotInStructError) Error added in v0.1.0

func (err FlagKeyNotInStructError) Error() string

type FlagSet added in v0.1.0

type FlagSet map[string]FlagValues

FlagSet holds the FlagValues that were specified for each flag key in the invocation. It's its own type so we can map an entire specification of flags onto a struct using reflection, if we want.

func (FlagSet) As added in v0.1.0

func (set FlagSet) As(ctx context.Context, target any) error

As parses the values of the FlagSet into the target, which must be a pointer to a struct, a pointer to a map, or a pointer to a type that implements FlagSetSetter.

If a pointer to a map, the flag keys will be used as the keys of the map. All flag values must be parsed into the same type, and will be parsed into the types supported by FlagValues.As.

If a pointer to a struct, the `flag` struct tag will control which fields a flag key parses into. The value of the tag should be the canonical name (i.e., not an alias) of the flag that should be parsed into that field. Unexported struct fields cannot be parsed into. All exported struct fields must have a `flag` struct tag; use "-" as a struct tag to not parse into a field. Field types can be any type supported by FlagValues.As.

If a pointer to a type that implements FlagSetSetter, the `SetFromFlagSet` method will be called and the FlagSet will be passed.

type FlagSetSetter added in v0.1.0

type FlagSetSetter interface {
	// SetFromFlagSet updates the receiver to hold the FlagSet that was
	// passed in, returning an error if it cannot.
	SetFromFlagSet(ctx context.Context, flags FlagSet) error
}

FlagSetSetter is an interface to control how a FlagSet will be parsed into a type. The type can implement the SetFromFlagSet method to override how the FlagSet.As method will parse flag values for that type.

type FlagSetterMethodInvalidError added in v0.1.0

type FlagSetterMethodInvalidError struct {
	// Receiver is the value the method was called on.
	Receiver any

	// Method is the name of the method that was called.
	Method string
}

FlagSetterMethodInvalidError is returned when the SetFromFlagSet method can't be found on a FlagSetSetter, the SetFromFlagValues method can't be found on a FlagValuesSetter, or the SetFromFlagValue method can't be found on a FlagValueSetter. This shouldn't ever happen, and if it does, it probably means clif's reflection code has drifted from the interface type definitions.

If you encounter this, report it as a bug.

func (FlagSetterMethodInvalidError) Error added in v0.1.0

type FlagSetterResponseError added in v0.1.0

type FlagSetterResponseError struct {
	// Receiver is the value the method was called on.
	Receiver any

	// Method is the name of the method that was called.
	Method string

	// Value is the value that was returned.
	Value any
}

FlagSetterResponseError is returned when the SetFromFlagSet, SetFromFlagValues, or SetFromFlagValue method is called on a FlagValueSetter, FlagValuesSetter, or FlagSetSetter], and the return value is somehow does not fill the error interface.

This pretty much always means there's a bug in clif.

func (FlagSetterResponseError) Error added in v0.1.0

func (err FlagSetterResponseError) Error() string

type FlagValue added in v0.1.0

type FlagValue struct {
	// HasValue indicates whether the flag had a value set. If false, it
	// indicates that the flag was used as a toggle, without a value, i.e.
	// --flag. If true, it indicates the flag was used with a value, i.e.
	// --flag=value or --flag value.
	HasValue bool

	// Raw holds the value the flag was given, if Set is true.
	Raw string

	// Key is the key used to invoke the flag, which could be an alias.
	Key string

	// CanonicalKey is the Name of the flag in the FlagDef, the canonical
	// way to refer to the flag.
	CanonicalKey string
}

FlagValue holds the value of a flag specified at runtime.

func (FlagValue) As added in v0.1.0

func (flag FlagValue) As(ctx context.Context, target any) error

As parses the value of the FlagValue into the target, which must be a pointer to a boolean, a pointer to a string, a pointer to an integer, a pointer to an unsigned integer, a pointer to a float, a pointer to a time.Time, a pointer to a *big.Int, a pointer to a *big.Float, or a pointer to a type that implements FlagValueSetter.

For a boolean, strconv.ParseBool will be used to parse the value, unless [FlagValue.Set] is false, in which case the value will be `true`.

For a string, no conversion will be done and [FlagValue.Raw] will be returned.

For an integer, strconv.ParseInt will be used to parse the value.

For an unsigned integer, strconv.ParseUint will be used to parse the value.

For a float, strconv.ParseFloat will be used to parse the value.

For a time.Time, dateparser.Parse will be used to parse the value.

For a big.Int, big.Int.SetString will be used to parse the value.

For a big.Float, big.Float.SetString will be used to parse the value.

For a type that implements FlagValueSetter, the `SetFromFlagValue` method will be called and the FlagValue will be passed.

type FlagValueSetter added in v0.1.0

type FlagValueSetter interface {
	// SetFromFlagValue updates the receiver to hold the FlagValue that was
	// passed in, returning an error if it cannot.
	SetFromFlagValue(ctx context.Context, value FlagValue) error
}

FlagValueSetter is an interface to control how a FlagValue will be parsed into a type. The type can implement the SetFromFlagValue method to override how the FlagSet.As, FlagValues.As, and FlagValue.As methods will parse a flag value for that type.

type FlagValueWithoutFlagKeyError added in v0.1.0

type FlagValueWithoutFlagKeyError struct {
	Value string
}

FlagValueWithoutFlagKeyError is returned when the parser finds a token that it believes can only be a flag value, but it's not preceded by a flag key. This should never happen.

func (FlagValueWithoutFlagKeyError) Error added in v0.1.0

type FlagValues added in v0.1.0

type FlagValues []FlagValue

FlagValues holds the values of a flag specified at runtime. It's a list of [FlagValue]s, in the order they were specified.

FlagValues gets its own type to enable normalization of multiple ways of specifying multiple values. For example, an application may want to accept both --flag=value1,value2,value3 and --flag=value1 --flag=value2 --flag=value3 to set flag to ["value1", "value2", "value3"]. Making FlagValues a proper type allows clif to support normalizing those values.

func (FlagValues) As added in v0.1.0

func (values FlagValues) As(ctx context.Context, target any) error

As parses the values of the FlagValues into the target, which must be a pointer to a slice, a pointer to a type that implements FlagValuesSetter, or a pointer that FlagValue.As knows how to parse into.

If a pointer to a slice, the slice's element type must be a type that FlagValue.As can parse into. The slice will be populated with one value per FlagValue, according to the rules of FlagValue.As.

If a pointer to a type that FlagValue.As can parse into *and* there's zero or one flag values passed during invocation, the parsing logic of FlagValue.As will be used. If no flag values are passed during invocation, the target will be set to its empty value. This is to simplify parsing a flag key that only accepts a single value, so the caller need not always deal with it as a slice. This approach is only recommended if the FlagDef prohibits multiple values for that flag key.

If a pointer to a type that implements FlagValuesSetter, the `SetFromFlagValues` method will be called and the FlagValues will be passed.

type FlagValuesSetter added in v0.1.0

type FlagValuesSetter interface {
	// SetFromFlagValues updates the receiver to hold the FlagValues that
	// were passed in, returning an error if it cannot.
	SetFromFlagValues(ctx context.Context, values FlagValues) error
}

FlagValuesSetter is an interface to control how a FlagValues will be parsed into a type. The type can implement the SetFromFlagValues method to override how the FlagSet.As and FlagValues.As methods will parse flag values for that type.

type Handler

type Handler interface {
	// Handle is a method that will be called when the command is executed.
	// It should contain the business logic of the command.
	Handle(ctx context.Context, resp *Response)
}

Handler is an interface that commands should implement. The implementing type should probably be a struct, with arguments and dependencies defined as fields on the struct.

type HandlerBuilder

type HandlerBuilder interface {
	// Build creates a Handler by parsing the flags and args into the
	// appropriate handler type.
	Build(ctx context.Context, flags FlagSet, args []string, resp *Response) Handler
}

HandlerBuilder is an interface that should wrap a Handler. It parses the passed [Flags] and args into a Handler, to separate out the parsing logic from the business logic.

type HelpHandler added in v0.2.0

type HelpHandler struct {
	App     Application
	CmdPath []Command
	Cmd     *Command
	Flags   []FlagDef
}

HelpHandler is a Handler that writes help output to the [Response.Output]. The help output is not guaranteed to be stable between versions of clif.

func (HelpHandler) Handle added in v0.2.0

func (handler HelpHandler) Handle(ctx context.Context, resp *Response)

Handle is a method that will be called when the command is executed. It should contain the business logic of the command.

type HelpMiddleware added in v0.2.0

type HelpMiddleware struct {
	Flags []string
}

HelpMiddleware provides a middleware that, when any of the specified flags are passed, will print the help output and prevent any other Handler or Middleware from executing.

func (HelpMiddleware) Intercept added in v0.2.0

func (middleware HelpMiddleware) Intercept(ctx context.Context, flags FlagSet, _ []string, defs DefParams, resp *Response) bool

type InvalidCommandNameError added in v0.1.0

type InvalidCommandNameError struct {
	// Name is the name or alias that's invalid.
	Name string

	// Path is list of parents, if any, that lead to the invalid Command,
	// including the invalid name.
	Path []string

	// Alias is set to true if the invalid name is defined in
	// Command.Aliases; if false, it's the Command.Name.
	Alias bool
}

InvalidCommandNameError is returned when a Command is defined with a Name or an Aliases key that is not a valid Command name.

func (InvalidCommandNameError) Error added in v0.1.0

func (err InvalidCommandNameError) Error() string

type InvalidConversionError added in v0.1.0

type InvalidConversionError struct {
	// Source is the FlagValue that was parsed.
	Source FlagValue

	// Target is the value being parsed into.
	Target reflect.Value
}

InvalidConversionError is returned when a FlagValue is parsed into a type that isn't supported.

func (InvalidConversionError) Error added in v0.1.0

func (err InvalidConversionError) Error() string

type InvalidFlagKeyError added in v0.1.0

type InvalidFlagKeyError struct {
	// CommandPath indicates the command and parents, if any, that the flag
	// is defined on.
	CommandPath []string

	// FlagKey is the invalid value used as a flag key.
	FlagKey string
}

InvalidFlagKeyError is returned when a flag key has an invalid name. Flag keys must start with -- (or just -, for short flags that are only used as toggles) and can only contain letters, numbers, -, _, and :. Flag keys must start with a letter or number, and short flags must be exactly one character.

func (InvalidFlagKeyError) Error added in v0.1.0

func (err InvalidFlagKeyError) Error() string

type InvalidKindError added in v0.1.0

type InvalidKindError struct {
	// Value holds the value that the caller was attempting to parse into.
	Value any

	// Kind indicates the reflect.Kind of the value that the caller was
	// attempting to parse into.
	Kind reflect.Kind
}

InvalidKindError is returned when a flag value cannot be parsed into a type because the kind of type it is isn't supported.

func (InvalidKindError) Error added in v0.1.0

func (err InvalidKindError) Error() string

type Middleware added in v0.2.0

type Middleware interface {
	// Intercept is the code that will run when the Middleware is executed.
	// All the runtime parameters available to a Handler are available,
	// along with DefParams describing the Application, the Command to
	// execute (if any), the parents of that Command (if any), and the
	// acceptable flags for that particular Command.
	//
	// If Intercept returns false, execution will halt and the Handler and
	// any other Middleware will not be executed.
	Intercept(ctx context.Context, flags FlagSet, args []string, defs DefParams, resp *Response) bool
}

Middleware provides an interface for specifying code to run after the appropriate Handler to execute is identified but before the Handler is executed.

type MissingFlagValueError

type MissingFlagValueError string

MissingFlagValueError is returned when a flag was used without a value, but the flag requires a value. The underlying string is the name of the flag, without leading --.

func (MissingFlagValueError) Error

func (err MissingFlagValueError) Error() string

type OnlyToggleWithoutIsToggleError added in v0.1.0

type OnlyToggleWithoutIsToggleError struct {
	// FlagKey is the Name property of the FlagDef that is misconfigured.
	FlagKey string

	// Path is the Command, and any parents, that the FlagDef is defined
	// on. The last element in the slice will be the Command the FlagDef is
	// defined on.
	Path []string
}

OnlyToggleWithoutIsToggleError is returned when a FlagDef has its OnlyToggle property set to true but its IsToggle property set to false. OnlyToggle indicates that a flag can *only* be used without a value, but IsToggle is what makes the value optional to begin with, so having OnlyToggle true and IsToggle false means no invocations can ever be valid. This is obviously nonsensical, so it's an invalid configuration.

func (OnlyToggleWithoutIsToggleError) Error added in v0.1.0

type Response

type Response struct {
	// Code is the status code the command will exit with.
	Code int

	// Output is the writer that should be used for command output. It will
	// usually be set to the shell's standard output.
	Output io.Writer

	// Error is the writer that should be used to communicate error
	// conditions. It will usually be set to the shell's standard error.
	Error io.Writer
}

Response holds the ways a command can present information to the user.

type RouteResult

type RouteResult struct {
	// Command is the Command that Route believes should be run. If nil, no
	// command was passed and the top-level Application handler should be
	// called. A nil value does not indicate a command was specified but
	// couldn't be found; that will be an explicit error.
	Command *Command

	// CommandPath is the list of Commands that were invoked to reach
	// Command, including Command itself.
	CommandPath []Command

	// Flags are the flags that should be applied to that command.
	Flags FlagSet

	// DefinedFlags are the FlagDefs that are defined along the
	// CommandPath.
	DefinedFlags []FlagDef

	// Args are the positional arguments that should be passed to that
	// command.
	Args []string
}

RouteResult holds information about the Command that should be run and the FlagSet and arguments to pass to it, based on the parsing done by Route.

func Route

func Route(ctx context.Context, app Application, input []string) (RouteResult, error)

Route parses the passed input in the context of the passed Application, turning it into a Command with a FlagSet and arguments.

type RunOption

type RunOption func(*RunOptions)

RunOption is a function type that modifies a passed RunOptions when called. It's used to configure the behavior of Application.Run.

func WithArgs

func WithArgs(args []string) RunOption

WithArgs is a RunOption that sets the arguments that will be parsed as the command's input to the passed strings.

func WithError

func WithError(w io.Writer) RunOption

WithError is a RunOption that sets the io.Writer the application will write information about errors to to the passed io.Writer.

func WithOutput

func WithOutput(w io.Writer) RunOption

WithOutput is a RunOption that sets the command output to the passed io.Writer.

type RunOptions

type RunOptions struct {
	// Output is where command output should be written. Defaults to
	// os.Stdout.
	Output io.Writer

	// Error is where the command should write information about errors.
	// Defaults to os.Stderr.
	Error io.Writer

	// Args are the arguments that were passed to the command. Defaults
	// to os.Args[1:].
	Args []string
}

RunOptions holds all the options to pass to Application.Run. It should be built by using RunOption functions to modify a passed in RunOptions.

type ShortFlagIsNotToggleError added in v0.1.0

type ShortFlagIsNotToggleError struct {
	// FlagKey is the Name property of the FlagDef that is misconfigured.
	FlagKey string

	// Path is the Command, and any parents, that the FlagDef is defined
	// on. The last element in the slice will be the Command the FlagDef is
	// defined on.
	Path []string

	// BecauseOfAlias is the entry of FlagDef.Aliases that requires the
	// flag to be a short flag. If unset, it means the FlagDef.Name makes
	// the flag a short flag, not an alias.
	BecauseOfAlias string
}

ShortFlagIsNotToggleError is returned when a FlagDef has a Name (or a key in Aliases) that makes it a short flag (the key starts with only one -), but is not marked as a toggle flag. Short flags must be toggle flags.

func (ShortFlagIsNotToggleError) Error added in v0.1.0

func (err ShortFlagIsNotToggleError) Error() string

type StructFieldMissingFlagTagError added in v0.1.0

type StructFieldMissingFlagTagError struct {
	// Struct is a value of the struct type that the field belongs to.
	Struct any

	// Field is the name of the field missing the tag.
	Field string
}

StructFieldMissingFlagTagError is returned when parsing a FlagSet into a struct type using FlagSet.As, and one of the struct's fields doesn't have a "flag" struct tag on it. All exported fields of the struct must have a "flag" struct tag.

func (StructFieldMissingFlagTagError) Error added in v0.1.0

type TooManyFlagValuesError added in v0.1.0

type TooManyFlagValuesError string

TooManyFlagValuesError is returned when a flag only accepts a single value, but multiple values were specified in the invocation.

func (TooManyFlagValuesError) Error added in v0.1.0

func (err TooManyFlagValuesError) Error() string

type UnexpectedCommandArgError

type UnexpectedCommandArgError string

UnexpectedCommandArgError is returned when a command that wasn't expecting an argument gets one.

func (UnexpectedCommandArgError) Error

func (err UnexpectedCommandArgError) Error() string

type UnexpectedFlagValueError

type UnexpectedFlagValueError struct {
	// Flag is the flag name, without leading --.
	Flag string

	// Value is the value that was passed to the flag.
	Value string
}

UnexpectedFlagValueError is returned when a flag was used with a value, but the flag doesn't accept values.

func (UnexpectedFlagValueError) Error

func (err UnexpectedFlagValueError) Error() string

type UnexpectedTokenTypeError added in v0.1.0

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

UnexpectedTokenTypeError is returned when the router encounters a token type it doesn't know how to handle. This usually indicates a bug in clif.

func (UnexpectedTokenTypeError) Error added in v0.1.0

func (err UnexpectedTokenTypeError) Error() string

type UnknownCommandError added in v0.1.0

type UnknownCommandError struct {
	// Path is the list of commands that were invoked, with the Command
	// that has not been defined as the last element of the slice.
	Path []string
}

UnknownCommandError is returned when an invocation asks for a Command that has not been defined.

func (UnknownCommandError) Error added in v0.1.0

func (err UnknownCommandError) Error() string

type UnknownFlagNameError

type UnknownFlagNameError string

UnknownFlagNameError is returned when an argument uses flag syntax, starting with a --, but doesn't match a flag configured for that Command. The underlying string will be the flag name, without leading --.

func (UnknownFlagNameError) Error

func (err UnknownFlagNameError) Error() string

type UnknownTokenTypeError added in v0.1.0

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

UnknownTokenTypeError is returned when the router encounters a token and isn't sure what type it is. This usually indicates a bug in clif.

func (UnknownTokenTypeError) Error added in v0.1.0

func (err UnknownTokenTypeError) Error() string

type VersionMiddleware added in v0.2.0

type VersionMiddleware struct {
	Flags []string
}

VersionMiddleware provides a middleware that, when any of the specified flags are passed, will print the version output and prevent any other Handler or Middleware from executing.

func (VersionMiddleware) Intercept added in v0.2.0

func (middleware VersionMiddleware) Intercept(ctx context.Context, flags FlagSet, _ []string, defs DefParams, resp *Response) bool

Jump to

Keyboard shortcuts

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