Documentation ¶
Overview ¶
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.
Index ¶
- Constants
- Variables
- func DefaultCompletionHandler(inv *Invocation) []string
- type Annotations
- type Bool
- type Command
- type CompletionHandlerFunc
- type Duration
- type Enum
- type EnumArray
- type EnvVar
- type Environ
- type Float64
- type Group
- type HandlerFunc
- type HostPort
- func (hp *HostPort) MarshalJSON() ([]byte, error)
- func (hp *HostPort) MarshalYAML() (interface{}, error)
- func (hp *HostPort) Set(v string) error
- func (hp *HostPort) String() string
- func (*HostPort) Type() string
- func (hp *HostPort) UnmarshalJSON(b []byte) error
- func (hp *HostPort) UnmarshalYAML(n *yaml.Node) error
- type Int64
- type Invocation
- func (inv *Invocation) Context() context.Context
- func (inv *Invocation) CurWords() (prev string, cur string)
- func (inv *Invocation) IsCompletionMode() bool
- func (inv *Invocation) ParsedFlags() *pflag.FlagSet
- func (inv *Invocation) Run() (err error)
- func (inv *Invocation) SignalNotifyContext(parent context.Context, signals ...os.Signal) (ctx context.Context, stop context.CancelFunc)
- func (inv *Invocation) WithContext(ctx context.Context) *Invocation
- func (inv *Invocation) WithOS() *Invocation
- func (inv *Invocation) WithTestParsedFlags(_ testing.TB, parsedFlags *pflag.FlagSet) *Invocation
- func (inv *Invocation) WithTestSignalNotifyContext(_ testing.TB, ...) *Invocation
- type MiddlewareFunc
- type Net
- type NoOptDefValuer
- type Option
- type OptionSet
- func (optSet *OptionSet) Add(opts ...Option)
- func (optSet OptionSet) ByFlag(flag string) *Option
- func (optSet OptionSet) ByName(name string) *Option
- func (optSet OptionSet) Filter(filter func(opt Option) bool) OptionSet
- func (optSet *OptionSet) FlagSet() *pflag.FlagSet
- func (optSet *OptionSet) MarshalYAML() (any, error)
- func (optSet *OptionSet) ParseEnv(vs []EnvVar) error
- func (optSet *OptionSet) SetDefaults() error
- func (optSet *OptionSet) UnmarshalJSON(data []byte) error
- func (optSet *OptionSet) UnmarshalYAML(rootNode *yaml.Node) error
- type Regexp
- func (r *Regexp) MarshalJSON() ([]byte, error)
- func (r *Regexp) MarshalYAML() (interface{}, error)
- func (r *Regexp) Set(v string) error
- func (r Regexp) String() string
- func (Regexp) Type() string
- func (r *Regexp) UnmarshalJSON(data []byte) error
- func (r *Regexp) UnmarshalYAML(n *yaml.Node) error
- func (r *Regexp) Value() *regexp.Regexp
- type RunCommandError
- type String
- type StringArray
- type Struct
- func (s *Struct[T]) MarshalJSON() ([]byte, error)
- func (s *Struct[T]) MarshalYAML() (interface{}, error)
- func (s *Struct[T]) Set(v string) error
- func (s *Struct[T]) String() string
- func (s *Struct[T]) Type() string
- func (s *Struct[T]) UnmarshalJSON(b []byte) error
- func (s *Struct[T]) UnmarshalYAML(n *yaml.Node) error
- type URL
- func (u *URL) MarshalJSON() ([]byte, error)
- func (u *URL) MarshalYAML() (interface{}, error)
- func (u *URL) Set(v string) error
- func (u *URL) String() string
- func (*URL) Type() string
- func (u *URL) UnmarshalJSON(b []byte) error
- func (u *URL) UnmarshalYAML(n *yaml.Node) error
- func (u *URL) Value() *url.URL
- type UnknownSubcommandError
- type Validator
- func (i *Validator[T]) MarshalJSON() ([]byte, error)
- func (i *Validator[T]) MarshalYAML() (interface{}, error)
- func (i *Validator[T]) Set(input string) error
- func (i *Validator[T]) String() string
- func (i *Validator[T]) Type() string
- func (i *Validator[T]) Underlying() pflag.Value
- func (i *Validator[T]) UnmarshalJSON(b []byte) error
- func (i *Validator[T]) UnmarshalYAML(n *yaml.Node) error
- type ValueSource
- type YAMLConfigPath
Constants ¶
const CompletionModeEnv = "COMPLETION_MODE"
CompletionModeEnv is a special environment variable that is set when the command is being run in completion mode.
Variables ¶
var DiscardValue discardValue
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.
Functions ¶
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.
Types ¶
type Annotations ¶
Annotations is an arbitrary key-mapping used to extend the Option and Command types. Its methods won't panic if the map is nil.
func (Annotations) Get ¶
func (a Annotations) Get(key string) (string, bool)
Get retrieves a key from the map, returning false if the key is not found or the map is nil.
func (Annotations) IsSet ¶
func (a Annotations) IsSet(key string) bool
IsSet returns true if the key is set in the annotations map.
func (Annotations) Mark ¶
func (a Annotations) Mark(key string, value string) Annotations
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.
type Command ¶ added in v0.5.0
type Command struct { // Parent is the direct parent of the command. // // It is set automatically when an invokation runs. Parent *Command // Children is a list of direct descendants. Children []*Command // Use is provided in form "command [flags] [args...]". Use string // Aliases is a list of alternative names for the command. Aliases []string // Short is a one-line description of the command. Short string // Hidden determines whether the command should be hidden from help. Hidden bool // Deprecated indicates whether this command is deprecated. // If empty, the command is not deprecated. // If set, the value is used as the deprecation message. Deprecated string `json:"deprecated,omitempty"` // RawArgs determines whether the command should receive unparsed arguments. // No flags are parsed when set, and the command is responsible for parsing // its own flags. RawArgs bool // Long is a detailed description of the command, // presented on its help page. It may contain examples. Long string Options OptionSet Annotations Annotations // Middleware is called before the Handler. // Use Chain() to combine multiple middlewares. Middleware MiddlewareFunc Handler HandlerFunc HelpHandler HandlerFunc // CompletionHandler is called when the command is run in completion // mode. If nil, only the default completion handler is used. // // Flag and option parsing is best-effort in this mode, so even if an Option // is "required" it may not be set. CompletionHandler CompletionHandlerFunc }
Command describes an executable command.
func (*Command) AddSubcommands ¶ added in v0.5.0
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
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
func (c *Command) Invoke(args ...string) *Invocation
Invoke creates a new invocation of the command, with stdio discarded.
The returned invocation is not live until Run() is called.
type CompletionHandlerFunc ¶ added in v0.8.0
type CompletionHandlerFunc func(i *Invocation) []string
type EnumArray ¶ added in v0.8.0
func EnumArrayOf ¶ added in v0.8.0
type Environ ¶
type Environ []EnvVar
func ParseEnviron ¶
ParseEnviron returns all environment variables starting with prefix without said prefix.
type Group ¶
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.
type HandlerFunc ¶
type HandlerFunc func(i *Invocation) error
HandlerFunc handles an Invocation of a command.
func DefaultHelpFn ¶ added in v0.8.0
func DefaultHelpFn() HandlerFunc
DefaultHelpFn returns a function that generates usage (help) output for a given command.
type HostPort ¶
HostPort is a host:port pair.
func (*HostPort) MarshalJSON ¶
func (*HostPort) MarshalYAML ¶
func (*HostPort) UnmarshalJSON ¶
func (*HostPort) UnmarshalYAML ¶
type Invocation ¶
type Invocation struct { Command *Command // Args is reduced into the remaining arguments after parsing flags // during Run. Args []string // Environ is a list of environment variables. Use EnvsWithPrefix to parse // os.Environ. Environ Environ Stdout io.Writer Stderr io.Writer Stdin io.Reader // Deprecated Logger slog.Logger // Deprecated Net Net // contains filtered or unexported fields }
Invocation represents an instance of a command being executed.
func (*Invocation) Context ¶
func (inv *Invocation) Context() context.Context
func (*Invocation) CurWords ¶ added in v0.8.0
func (inv *Invocation) CurWords() (prev string, cur string)
func (*Invocation) IsCompletionMode ¶ added in v0.8.0
func (inv *Invocation) IsCompletionMode() bool
IsCompletionMode returns true if the command is being run in completion mode.
func (*Invocation) ParsedFlags ¶
func (inv *Invocation) ParsedFlags() *pflag.FlagSet
func (*Invocation) Run ¶
func (inv *Invocation) Run() (err error)
Run executes the command. If two command share a flag name, the first command wins.
func (*Invocation) SignalNotifyContext ¶
func (inv *Invocation) SignalNotifyContext(parent context.Context, signals ...os.Signal) (ctx context.Context, stop context.CancelFunc)
SignalNotifyContext is equivalent to signal.NotifyContext, but supports being overridden in tests.
func (*Invocation) WithContext ¶
func (inv *Invocation) WithContext(ctx context.Context) *Invocation
WithContext returns a copy of the Invocation with the given context.
func (*Invocation) WithOS ¶
func (inv *Invocation) WithOS() *Invocation
WithOS returns the invocation as a main package, filling in the invocation's unset fields with OS defaults.
func (*Invocation) WithTestParsedFlags ¶
func (inv *Invocation) WithTestParsedFlags( _ testing.TB, parsedFlags *pflag.FlagSet, ) *Invocation
func (*Invocation) WithTestSignalNotifyContext ¶
func (inv *Invocation) WithTestSignalNotifyContext( _ testing.TB, f func(parent context.Context, signals ...os.Signal) (ctx context.Context, stop context.CancelFunc), ) *Invocation
WithTestSignalNotifyContext allows overriding the default implementation of SignalNotifyContext. This should only be used in testing.
type MiddlewareFunc ¶
type MiddlewareFunc func(next HandlerFunc) HandlerFunc
MiddlewareFunc returns the next handler in the chain, or nil if there are no more.
func Chain ¶
func Chain(ms ...MiddlewareFunc) MiddlewareFunc
Chain returns a Handler that first calls middleware in order.
func RequireNArgs ¶
func RequireNArgs(want int) MiddlewareFunc
func RequireRangeArgs ¶
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.
type Net ¶
type Net interface { // Listen has the same semantics as `net.Listen` but also supports `udp` Listen(network, address string) (net.Listener, error) }
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 ¶
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 ¶
type Option struct { Name string `json:"name,omitempty"` Description string `json:"description,omitempty"` // Required means this value must be set by some means. It requires // `ValueSource != ValueSourceNone` // If `Default` is set, then `Required` is ignored. Required bool `json:"required,omitempty"` // Flag is the long name of the flag used to configure this option. If unset, // flag configuring is disabled. Flag string `json:"flag,omitempty"` // FlagShorthand is the one-character shorthand for the flag. If unset, no // shorthand is used. FlagShorthand string `json:"flag_shorthand,omitempty"` // Env is the environment variable used to configure this option. If unset, // environment configuring is disabled. Env string `json:"env,omitempty"` // YAML is the YAML key used to configure this option. If unset, YAML // configuring is disabled. YAML string `json:"yaml,omitempty"` // Default is parsed into Value if set. Default string `json:"default,omitempty"` // Value includes the types listed in values.go. Value pflag.Value `json:"value,omitempty"` // Annotations enable extensions to serpent higher up in the stack. It's useful for // help formatting and documentation generation. Annotations Annotations `json:"annotations,omitempty"` // Group is a group hierarchy that helps organize this option in help, configs // and other documentation. Group *Group `json:"group,omitempty"` // UseInstead is a list of options that should be used instead of this one. // The field is used to generate a deprecation warning. 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.
func (*Option) UnmarshalJSON ¶
type OptionSet ¶
type OptionSet []Option
OptionSet is a group of options that can be applied to a command.
func (OptionSet) ByName ¶
ByName returns the Option with the given name, or nil if no such option exists.
func (OptionSet) Filter ¶
Filter will only return options that match the given filter. (return true)
func (*OptionSet) MarshalYAML ¶
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 (*OptionSet) ParseEnv ¶
ParseEnv parses the given environment variables into the OptionSet. Use EnvsWithPrefix to filter out prefixes.
func (*OptionSet) SetDefaults ¶
SetDefaults sets the default values for each Option, skipping values that already have a value source.
func (*OptionSet) UnmarshalJSON ¶
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.
func (*OptionSet) UnmarshalYAML ¶
UnmarshalYAML converts the given YAML node into the option set. It is isomorphic with ToYAML.
type Regexp ¶
func (*Regexp) MarshalJSON ¶
func (*Regexp) MarshalYAML ¶
func (*Regexp) UnmarshalJSON ¶
func (*Regexp) UnmarshalYAML ¶
type RunCommandError ¶
func (*RunCommandError) Error ¶
func (e *RunCommandError) Error() string
func (*RunCommandError) Unwrap ¶
func (e *RunCommandError) Unwrap() error
type StringArray ¶
type StringArray []string
StringArray is a slice of strings that implements pflag.Value and pflag.SliceValue.
func StringArrayOf ¶
func StringArrayOf(ss *[]string) *StringArray
func (*StringArray) Append ¶
func (s *StringArray) Append(v string) error
func (*StringArray) GetSlice ¶
func (s *StringArray) GetSlice() []string
func (*StringArray) Replace ¶
func (s *StringArray) Replace(vals []string) error
func (*StringArray) Set ¶
func (s *StringArray) Set(v string) error
func (StringArray) String ¶
func (s StringArray) String() string
func (StringArray) Type ¶
func (StringArray) Type() string
func (StringArray) Value ¶
func (s StringArray) Value() []string
type Struct ¶
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 (*Struct[T]) MarshalYAML ¶
nolint:revive
func (*Struct[T]) UnmarshalYAML ¶
nolint:revive
type URL ¶
func (*URL) MarshalJSON ¶
func (*URL) MarshalYAML ¶
func (*URL) UnmarshalJSON ¶
func (*URL) UnmarshalYAML ¶
type UnknownSubcommandError ¶ added in v0.8.0
type UnknownSubcommandError struct {
Args []string
}
func (*UnknownSubcommandError) Error ¶ added in v0.8.0
func (e *UnknownSubcommandError) Error() string
type Validator ¶
Validator is a wrapper around a pflag.Value that allows for validation of the value after or before it has been set.
func (*Validator[T]) MarshalJSON ¶
func (*Validator[T]) MarshalYAML ¶
func (*Validator[T]) Underlying ¶
func (*Validator[T]) UnmarshalJSON ¶
func (*Validator[T]) UnmarshalYAML ¶
type ValueSource ¶
type ValueSource string
const ( ValueSourceNone ValueSource = "" ValueSourceFlag ValueSource = "flag" ValueSourceEnv ValueSource = "env" ValueSourceYAML ValueSource = "yaml" ValueSourceDefault ValueSource = "default" )
type YAMLConfigPath ¶
type YAMLConfigPath string
YAMLConfigPath is a special value type that encodes a path to a YAML configuration file where options are read from.
func (*YAMLConfigPath) Set ¶
func (p *YAMLConfigPath) Set(v string) error
func (*YAMLConfigPath) String ¶
func (p *YAMLConfigPath) String() string
func (*YAMLConfigPath) Type ¶
func (*YAMLConfigPath) Type() string