serpent package - github.com/coder/serpent - Go Packages

Package serpent offers an all-in-one solution for a highly configurable CLI application. Within Coder, we use it for all of our subcommands, which demands more functionality than cobra/viber offers.

The Command interface is loosely based on the chi middleware pattern and http.Handler/HandlerFunc.

CompletionModeEnv is a special environment variable that is set when the command is being run in completion mode.

DiscardValue does nothing but implements the pflag.Value interface. It's useful in cases where you want to accept an option, but access the underlying value directly instead of through the Option methods.

func DefaultCompletionHandler added in v0.8.0

func DefaultCompletionHandler(inv *Invocation) []string

DefaultCompletionHandler is a handler that prints all the subcommands, or all the options that haven't been exhaustively set, if the current word starts with a dash.

Annotations is an arbitrary key-mapping used to extend the Option and Command types. Its methods won't panic if the map is nil.

Get retrieves a key from the map, returning false if the key is not found or the map is nil.

IsSet returns true if the key is set in the annotations map.

Mark sets a value on the annotations map, creating one if it doesn't exist. Mark does not mutate the original and returns a copy. It is suitable for chaining.

func BoolOf(b *bool) *Bool
func (b Bool) Value() bool

type Command added in v0.5.0

type Command struct {
	
	
	
	Parent *Command

	
	Children []*Command

	
	Use string

	
	Aliases []string

	
	Short string

	
	Hidden bool

	
	
	
	Deprecated string `json:"deprecated,omitempty"`

	
	
	
	RawArgs bool

	
	
	Long        string
	Options     OptionSet
	Annotations Annotations

	
	
	Middleware  MiddlewareFunc
	Handler     HandlerFunc
	HelpHandler HandlerFunc
	
	
	
	
	
	CompletionHandler CompletionHandlerFunc
}

Command describes an executable command.

func (*Command) AddSubcommands added in v0.5.0

func (c *Command) AddSubcommands(cmds ...*Command)

AddSubcommands adds the given subcommands, setting their Parent field automatically.

func (*Command) FullName added in v0.5.0

FullName returns the full invocation name of the command, as seen on the command line.

func (*Command) FullOptions added in v0.5.0

func (c *Command) FullOptions() OptionSet

FullOptions returns the options of the command and its parents.

func (*Command) FullUsage added in v0.5.0

FullName returns usage of the command, preceded by the usage of its parents.

func (*Command) Invoke added in v0.5.0

Invoke creates a new invocation of the command, with stdio discarded.

The returned invocation is not live until Run() is called.

func (*Command) Name added in v0.5.0

Name returns the first word in the Use string.

func (*Command) Walk added in v0.5.0

func (c *Command) Walk(fn func(*Command))

Walk calls fn for the command and all its children.

func (d *Duration) MarshalYAML() (interface{}, error)
func (e *Enum) MarshalYAML() (interface{}, error)

Var represents a single environment variable of form NAME=VALUE.

ParseEnviron returns all environment variables starting with prefix without said prefix.

func (e *Environ) Set(name, value string)
type Group struct {
	Parent      *Group `json:"parent,omitempty"`
	Name        string `json:"name,omitempty"`
	YAML        string `json:"yaml,omitempty"`
	Description string `json:"description,omitempty"`
}

Group describes a hierarchy of groups that an option or command belongs to.

func (g *Group) Ancestry() []Group

Ancestry returns the group and all of its parents, in order.

type HandlerFunc

type HandlerFunc func(i *Invocation) error

HandlerFunc handles an Invocation of a command.

func DefaultHelpFn() HandlerFunc

DefaultHelpFn returns a function that generates usage (help) output for a given command.

HostPort is a host:port pair.

func (hp *HostPort) MarshalYAML() (interface{}, error)

Invocation represents an instance of a command being executed.

func (inv *Invocation) IsCompletionMode() bool

IsCompletionMode returns true if the command is being run in completion mode.

func (inv *Invocation) Run() (err error)

Run executes the command. If two command share a flag name, the first command wins.

SignalNotifyContext is equivalent to signal.NotifyContext, but supports being overridden in tests.

WithContext returns a copy of the Invocation with the given context.

func (inv *Invocation) WithOS() *Invocation

WithOS returns the invocation as a main package, filling in the invocation's unset fields with OS defaults.

WithTestSignalNotifyContext allows overriding the default implementation of SignalNotifyContext. This should only be used in testing.

type MiddlewareFunc func(next HandlerFunc) HandlerFunc

MiddlewareFunc returns the next handler in the chain, or nil if there are no more.

func Chain(ms ...MiddlewareFunc) MiddlewareFunc

Chain returns a Handler that first calls middleware in order.

func RequireNArgs(want int) MiddlewareFunc
func RequireRangeArgs(start, end int) MiddlewareFunc

RequireRangeArgs returns a Middleware that requires the number of arguments to be between start and end (inclusive). If end is -1, then the number of arguments must be at least start.

Net abstracts CLI commands interacting with the operating system networking.

At present, it covers opening local listening sockets, since doing this in testing is a challenge without flakes, since it's hard to pick a port we know a priori will be free.

type NoOptDefValuer interface {
	NoOptDefValue() string
}

NoOptDefValuer describes behavior when no option is passed into the flag.

This is useful for boolean or otherwise binary flags.

type Option struct {
	Name        string `json:"name,omitempty"`
	Description string `json:"description,omitempty"`
	
	
	
	Required bool `json:"required,omitempty"`

	
	
	Flag string `json:"flag,omitempty"`
	
	
	FlagShorthand string `json:"flag_shorthand,omitempty"`

	
	
	Env string `json:"env,omitempty"`

	
	
	YAML string `json:"yaml,omitempty"`

	
	
	Default string `json:"default,omitempty"`
	
	
	
	
	
	
	
	
	DefaultFn func() string `json:"-"`
	
	Value pflag.Value `json:"value,omitempty"`

	
	
	Annotations Annotations `json:"annotations,omitempty"`

	
	
	Group *Group `json:"group,omitempty"`

	
	
	UseInstead []Option `json:"use_instead,omitempty"`

	Hidden bool `json:"hidden,omitempty"`

	ValueSource ValueSource `json:"value_source,omitempty"`

	CompletionHandler CompletionHandlerFunc `json:"-"`
}

Option is a configuration option for a CLI application.

OptionSet is a group of options that can be applied to a command.

func (optSet *OptionSet) Add(opts ...Option)

Add adds the given Options to the OptionSet.

ByName returns the Option with the given name, or nil if no such option exists.

func (optSet OptionSet) Filter(filter func(opt Option) bool) OptionSet

Filter will only return options that match the given filter. (return true)

FlagSet returns a pflag.FlagSet for the OptionSet.

MarshalYAML converts the option set to a YAML node, that can be converted into bytes via yaml.Marshal.

The node is returned to enable post-processing higher up in the stack.

It is isomorphic with FromYAML.

func (optSet *OptionSet) ParseEnv(vs []EnvVar) error

ParseEnv parses the given environment variables into the OptionSet. Use EnvsWithPrefix to filter out prefixes.

func (optSet *OptionSet) SetDefaults() error

SetDefaults sets the default values for each Option, skipping values that already have a value source.

UnmarshalJSON implements json.Unmarshaler for OptionSets. Options have an interface Value type that cannot handle unmarshalling because the types cannot be inferred. Since it is a slice, instantiating the Options first does not help.

However, we typically do instantiate the slice to have the correct types. So this unmarshaller will attempt to find the named option in the existing set, if it cannot, the value is discarded. If the option exists, the value is unmarshalled into the existing option, and replaces the existing option.

The value is discarded if it's type cannot be inferred. This behavior just feels "safer", although it should never happen if the correct option set is passed in. The situation where this could occur is if a client and server are on different versions with different options.

UnmarshalYAML converts the given YAML node into the option set. It is isomorphic with ToYAML.

func (r *Regexp) MarshalYAML() (interface{}, error)

StringArray is a slice of strings that implements pflag.Value and pflag.SliceValue.

type Struct[T any] struct {
	Value T
}

Struct is a special value type that encodes an arbitrary struct. It implements the flag.Value interface, but in general these values should only be accepted via config for ergonomics.

The string encoding type is YAML.

func (s *Struct[T]) MarshalYAML() (interface{}, error)

nolint:revive

func (u *URL) MarshalYAML() (interface{}, error)

Validator is a wrapper around a pflag.Value that allows for validation of the value after or before it has been set.

func (i *Validator[T]) MarshalYAML() (interface{}, error)
const (
	ValueSourceNone    ValueSource = ""
	ValueSourceFlag    ValueSource = "flag"
	ValueSourceEnv     ValueSource = "env"
	ValueSourceYAML    ValueSource = "yaml"
	ValueSourceDefault ValueSource = "default"
)

YAMLConfigPath is a special value type that encodes a path to a YAML configuration file where options are read from.