Documentation
¶
Overview ¶
Package cli provides support for posix style cli flag parsing and supports simple command resolution.
Most of existing flag packages requires adding flags at runtime by calling methods during program initialization, we simply find that annoying as we believe the flag parsing should be straightforward and customizable.
This package decouples flag declaration and indexing, making it easy to implement both fully static and highly dynamic flag processing with minimum overhead.
For simple cli applications, you can create a static flag indexing func by switching among constant flag names, for example:
var globalFooFlag = cli.String{ ... } func IndexMyFlags(name string, _ int) Flag { switch name { case "foo", "f": return &globalFooFlag default: return nil } }
Index ¶
- Constants
- func HandleCmdErrorByPrintingHelp(c *Cmd, copts *CmdOptions, err error) (ignore bool)
- func ParseFlags(flags FlagIndexer, args []string, opts *ParseOptions) (nParsed, posDoubleDash int, posArgs []string, err error)
- func ParseFlagsLowLevel(flags FlagIndexer, args []string, opts *ParseOptions, ...) (nParsed, posDoubleDash int, posArgs []string, err error)
- type Bool
- type BoolParser
- type BoolSlice
- type Cmd
- type CmdErrorHandleFunc
- type CmdHelp
- type CmdOptions
- type Duration
- type DurationParser
- type DurationSlice
- type DurationSum
- type ExplicitFlag
- type Flag
- type FlagErrorHandleFunc
- type FlagHelp
- type FlagIndexer
- type FlagMark
- type Float32
- type Float32Slice
- type Float32Sum
- type Float64
- type Float64Slice
- type Float64Sum
- type FloatParser
- type FuncIndexer
- type Helper
- type ImplicitFlag
- type Int
- type Int16
- type Int16Slice
- type Int16Sum
- type Int32
- type Int32Slice
- type Int32Sum
- type Int64
- type Int64Slice
- type Int64Sum
- type Int8
- type Int8Slice
- type Int8Sum
- type IntParser
- type IntSlice
- type IntSum
- type MapIndexer
- type ParseOptions
- type RegExp
- type RegExpNoCase
- type RegExpNoCaseParser
- type RegExpParser
- type RegexpNoCaseSlice
- type RegexpSlice
- type Size
- type SizeParser
- type SizeSlice
- type SizeSum
- type SliceParser
- type String
- type StringParser
- type StringSlice
- type SumParser
- type Time
- type TimeParser
- type TimeSlice
- type Uint
- type Uint16
- type Uint16Slice
- type Uint16Sum
- type Uint32
- type Uint32Slice
- type Uint32Sum
- type Uint64
- type Uint64Slice
- type Uint64Sum
- type Uint8
- type Uint8Slice
- type Uint8Sum
- type UintSlice
- type UintSum
- type Uintptr
- type UintptrSlice
- type UintptrSum
- type UnixMilli
- type UnixMilliParser
- type UnixMilliSlice
- type UnixNano
- type UnixNanoParser
- type UnixNanoSlice
- type UnixTimestamp
- type UnixTimestampParser
- type UnixTimestampSlice
- type ValueParser
Constants ¶
const ( ErrEmptyArgName errhelper.ErrString = "arg name empty" ErrUndefinedFlag errhelper.ErrString = "undefined flag" ErrBadFlag errhelper.ErrString = "bad flag" ErrValueMissing errhelper.ErrString = "missing value" ErrValueOverflow errhelper.ErrString = "value overflow" ErrInvalidValue errhelper.ErrString = "invalid value" )
Variables ¶
This section is empty.
Functions ¶
func HandleCmdErrorByPrintingHelp ¶
func HandleCmdErrorByPrintingHelp(c *Cmd, copts *CmdOptions, err error) (ignore bool)
HandleCmdErrorByPrintingHelp trys to cast Cmd.Extra and Flag.Ext() as Helper to print help text to stderr.
func ParseFlags ¶
func ParseFlags( flags FlagIndexer, args []string, opts *ParseOptions, ) (nParsed, posDoubleDash int, posArgs []string, err error)
ParseFlags parses args with options, where args is usually the os.Args[1:].
Double dash (`--`, no prefix or suffix) is treated as the indicator of the start of arbitrary number of positional args, these args will not be in the return value posArgs, instead, caller should check the return value posDoubleDash, a non negative posDoubleDash can be used to index the double dash from the args argument.
func ParseFlagsLowLevel ¶
func ParseFlagsLowLevel( flags FlagIndexer, args []string, opts *ParseOptions, discardPosArgs, stopOnFirstNonDashArg bool, ) (nParsed, posDoubleDash int, posArgs []string, err error)
ParseFlagsLowLevel is the low-level version of ParseFlags with two more options to control flag parsing.
discardPosArgs when set to true, this function will silently discard all positional args by not appending them to the posArgs (which could be backed by opts.PosArgsBuffer).
stopOnFirstNonDashArg tells this function to return on reaching the first arg without dash prefix.
Set both discardPosArgs and stopOnFirstPosArg to false unless you know what you are doing.
Types ¶
type BoolParser ¶
type BoolParser[T ~bool] struct{}
BoolParser parses an arg string to a bool value.
func (BoolParser[T]) ParseValue ¶
func (BoolParser[T]) ParseValue(opts *ParseOptions, arg string, out *T) (err error)
type BoolSlice ¶
type BoolSlice = ImplicitFlag[[]bool, SliceParser[bool, BoolParser[bool]]]
slice flags
type Cmd ¶
type Cmd struct { // Name is the command name, it is used for matching sub-command in args. Name string // Flags are flags accessible from both the Cmd itself and all its // children. Flags FlagIndexer // LocalFlags are flags only accepted by this command, they are preferred // to Flags during the flag parsing process. LocalFlags FlagIndexer // PreRun is the function always being called for all matching Cmds when // looking up the target Cmd. // // Not all args are parsed at the time it being called, check the // unparsedArgs and call Parse if necessary. // // NOTE: args in unparsedArgs are supposed to be valid for all flags // accessible from the Cmd c. PreRun func(c *Cmd, copts *CmdOptions, popts *ParseOptions, unparsedArgs []string) error // Run is called when the Cmd is the target Cmd to be run. // // posArgs are all positional args appeared before the double dash (`--`), // argsAfterDD are all args after the double dash. Run func(c *Cmd, copts *CmdOptions, posArgs, argsAfterDD []string) error // PostRun is called right after Run. // // runErr is the error returned by Run and can ONLY be non-nil for the // first PostRun handling the non-nil error returned by Run, which belongs // not necessarily to the same Cmd had its Run called. // // Return nil to continue current execution flow and run parent's PostRun, // otherwise a non-nil err cancels all subsequent PostRun and will be the // error for Exec caller. PostRun func(c, from *Cmd, copts *CmdOptions, runErr error) error // Extra stores extra data for application specific usage, it is designed // to be used to reduce context wrapping and closure usage. Extra any // NOTE: Parent and Children are exported for static initialization. // Be careful when setting these fields manually. Parent *Cmd Children []*Cmd }
Cmd is a function caller for a serial of args.
func (*Cmd) Exec ¶
func (c *Cmd) Exec(copts *CmdOptions, popts *ParseOptions, args []string) (err error)
Exec trys to find and run the longest matching Cmd in tree indicated by args.
During the lookup, it calls all intermediate Cmds' PreRun function if that's not nil, it passes all args behind the Cmd indicating arg (the sub command), and these args are unparsed at the time of calling.
func (*Cmd) FormatCmdPath ¶
func (c *Cmd) FormatCmdPath(w io.StringWriter) (n int, err error)
FormatCmdPath writes the command leading to this Cmd, using space as the separator.
func (*Cmd) LinkChildren ¶
LinkChildren sets this Cmd as the parent of all its children.
If recursive is true, this operation is repeated for all referenced Cmd in this tree.
Common use case of this function is being called in a main package init() function to link all statically declared Cmds together.
func (*Cmd) SearchFlag ¶
SearchFlag implements FlagIndexer.
type CmdErrorHandleFunc ¶
type CmdErrorHandleFunc = func(c *Cmd, copts *CmdOptions, cmdErr error) (err error)
CmdErrorHandleFunc handles resolution errors.
Return nil to ignore the error.
type CmdHelp ¶
type CmdHelp struct { // Pattern is a one-line usage pattern of the command, not including // the command itself. // // Recommended syntax: // // - `[ ]` to define an optional argument. // - `...` to allow multiple values for the previous arg. // - `|` to provide mutually exclusive options. // - `{ }` to define a set of mutually exclusive args. // // Example: add [-F file | -D dir]... [-f format] profile Pattern string // Deprecation is the deprecation message of the command. // // Only use this message to note the reason of deprecation, and DO NOT // include prefix like `DEPRECATED: ` Deprecation string // Short is the brief description of the command. Short string // Example lists some typical use cases of the command. Example string // Long is the detailed description of the command. Long string // Changelog should contain upgrade notice of the command. Changelog string }
CmdHelp contains commonly used metadata for a cli command.
To produce consistent content, all values SHOULD NOT contain leading or trailling whitespaces.
Hint: use Cmd.Extra to hold CmdHelp for documentation purpose.
func (*CmdHelp) WriteHelp ¶
func (m *CmdHelp) WriteHelp(c *Cmd, copts *CmdOptions, out io.StringWriter)
WriteHelp implements Helper.
type CmdOptions ¶
type CmdOptions struct { // Stdin is the stdin of the cmd, it is up to application code to handle // nil value. Stdin io.Reader // Stdout is the stdout of the cmd, it is up to application code to // handle nil value. Stdout io.Writer // Stderr is the stderr of the cmd, it is up to application code to handle // nil value. Stderr io.Writer // HandleError is the function get called to handle Cmd resolution errors. HandleError CmdErrorHandleFunc }
CmdOptions are options to run a Cmd.
type Duration ¶
type Duration = ExplicitFlag[time.Duration, DurationParser[time.Duration]]
basic type flags
type DurationParser ¶
type DurationParser[T ~int64] struct{}
func (DurationParser[T]) ParseValue ¶
func (DurationParser[T]) ParseValue(opts *ParseOptions, arg string, out *T) (err error)
type DurationSlice ¶
type DurationSlice = ExplicitFlag[[]time.Duration, SliceParser[time.Duration, DurationParser[time.Duration]]]
slice flags
type DurationSum ¶
type DurationSum = ImplicitFlag[time.Duration, SumParser[time.Duration, DurationParser[time.Duration]]]
sum flags
type ExplicitFlag ¶
type ExplicitFlag[T any, P ValueParser[T]] struct { ValueOut *T Marks FlagMark // Extra can be used to store custom data for this flag. Extra any }
ExplicitFlag is a flag whose value must be set explicitly.
This usage pattern is widely adopted by flags for string values.
func (*ExplicitFlag[T, P]) Changed ¶
func (f *ExplicitFlag[T, P]) Changed() bool
Changed returns true when the value is set
func (*ExplicitFlag[T, P]) Decode ¶
func (f *ExplicitFlag[T, P]) Decode(ctx *ParseOptions, arg string) error
Parse implements Flag.
func (*ExplicitFlag[T, P]) Ext ¶
func (f *ExplicitFlag[T, P]) Ext() any
func (*ExplicitFlag[T, P]) ValueImplied ¶
func (*ExplicitFlag[T, P]) ValueImplied(opts *ParseOptions, set bool) bool
ValueImplied implements Flag.
type Flag ¶
type Flag interface { // ValueImplied returns true if the value can be implied by the presence // of the flag. // // Argument set is true when the caller intends to set the value with the // implied value. ValueImplied(opts *ParseOptions, set bool) bool // Decode an arg value for the flag. Decode(opts *ParseOptions, arg string) error // Ext returns an arbitrary value. Ext() any }
Flag by its core use case is just a string value converter for text based information exchange.
type FlagErrorHandleFunc ¶
type FlagErrorHandleFunc = func(opts *ParseOptions, args []string, i int, argErr error) (err error)
FlagErrorHandleFunc handles the error for parsing args[i].
Return nil to ignore the error and continue parsing.
type FlagHelp ¶
type FlagHelp struct { // Name is the name of the flag without the `--` prefix. Name string // Shorthand is the shorthand of the flag without the `-` prefix. Shorthand string // Usage is the breif usage of the flag. Usage string // Deprecation is the deprecation message of the flag. // // Only use this message to note the reason of deprecation, and DO NOT // include prefix like `DEPRECATED: ` Deprecation string // ValidValues is a function to return a list of all valid values of the // flag ValidValues func(c *Cmd) []string // Changelog should contain upgrade notice of the flag. Changelog string }
FlagHelp defines commonly used flag metadata
Hint: use {Explicit,Implicit}Flag.Extra to hold FlagHelp for documentation purpose.
func (*FlagHelp) WriteHelp ¶
func (h *FlagHelp) WriteHelp(c *Cmd, copts *CmdOptions, out io.StringWriter)
WriteHelp implements Helper
type FlagIndexer ¶
type FlagIndexer interface { // SearchFlag returns a flag by name. // // Return nil when the flag is undefined. SearchFlag(name string) Flag // IndexFlag returns a flag for the index i. // // A serial of indexing call always starts with i = 0, and it's safe // to assume i >= 0. // // Return nil to indicate no more flag available. IndexFlag(i int) Flag }
FlagIndexer defines the interface for looking up flags.
type FlagMark ¶
type FlagMark uint32
FlagMark is the bit set for a cli flag.
const ( // FlagMark_Changed marks the Value of the flag is set. // // This mark SHOULD not be set manually and SHOULD be set by the Parse // function. FlagMark_Changed FlagMark = 1 << iota // FlagMark_Required marks the flag MUST present FlagMark_Required // FlagMark_Hidden marks the flag hidden FlagMark_Hidden )
type Float32Slice ¶
type Float32Slice = ExplicitFlag[[]float32, SliceParser[float32, FloatParser[float32]]]
slice flags
type Float32Sum ¶
type Float32Sum = ImplicitFlag[float32, SumParser[float32, FloatParser[float32]]]
sum flags
type Float64Slice ¶
type Float64Slice = ExplicitFlag[[]float64, SliceParser[float64, FloatParser[float64]]]
slice flags
type Float64Sum ¶
type Float64Sum = ImplicitFlag[float64, SumParser[float64, FloatParser[float64]]]
sum flags
type FloatParser ¶
FloatParser parses an arg string to a floating-point value.
func (FloatParser[T]) ParseValue ¶
func (FloatParser[T]) ParseValue(opts *ParseOptions, arg string, out *T) (err error)
type FuncIndexer ¶
FuncIndexer
when index < 0, search by name, otherwise, search by index.
func (FuncIndexer) IndexFlag ¶
func (f FuncIndexer) IndexFlag(i int) Flag
IndexFlags implements FlagIndexer.
func (FuncIndexer) SearchFlag ¶
func (f FuncIndexer) SearchFlag(name string) Flag
SearchFlag implements FlagIndexer.
type Helper ¶
type Helper interface {
WriteHelp(c *Cmd, copts *CmdOptions, w io.StringWriter)
}
type ImplicitFlag ¶
type ImplicitFlag[T any, P ValueParser[T]] ExplicitFlag[T, P]
ImplicitFlag is a flag whose value can be implied by the presence of the flag.
- For integer and float values, the implicit arg value is "1".
- For bool values, the implicit arg value is "true".
- For all other values, the implicit arg value is "" (empty string).
func (*ImplicitFlag[T, P]) Changed ¶
func (f *ImplicitFlag[T, P]) Changed() bool
Changed returns true when the value is set.
func (*ImplicitFlag[T, P]) Decode ¶
func (f *ImplicitFlag[T, P]) Decode(ctx *ParseOptions, arg string) error
Parse implements Flag.
func (*ImplicitFlag[T, P]) Ext ¶
func (f *ImplicitFlag[T, P]) Ext() any
func (*ImplicitFlag[T, P]) ValueImplied ¶
func (f *ImplicitFlag[T, P]) ValueImplied(ctx *ParseOptions, set bool) bool
ValueImplied implements Flag
type Int16Slice ¶
type Int16Slice = ExplicitFlag[[]int16, SliceParser[int16, IntParser[int16]]]
slice flags
type Int32Slice ¶
type Int32Slice = ExplicitFlag[[]int32, SliceParser[int32, IntParser[int32]]]
slice flags
type Int64Slice ¶
type Int64Slice = ExplicitFlag[[]int64, SliceParser[int64, IntParser[int64]]]
slice flags
type Int8Slice ¶
type Int8Slice = ExplicitFlag[[]int8, SliceParser[int8, IntParser[int8]]]
slice flags
type IntParser ¶
IntParser parses an arg string to an integer value.
func (IntParser[T]) ParseValue ¶
func (IntParser[T]) ParseValue(opts *ParseOptions, arg string, out *T) (err error)
type MapIndexer ¶
type MapIndexer struct {
// contains filtered or unexported fields
}
func (*MapIndexer) Add ¶
func (m *MapIndexer) Add(flag Flag, names ...string) *MapIndexer
Add adds a flag.
It panics when name is empty or there is already flag with same name or same shorthand.
func (*MapIndexer) IndexFlag ¶
func (m *MapIndexer) IndexFlag(i int) Flag
IndexFlags implements FlagIndexer.
func (*MapIndexer) SearchFlag ¶
func (m *MapIndexer) SearchFlag(name string) Flag
SearchFlag implements FlagIndexer.
type ParseOptions ¶
type ParseOptions struct { // StartTime is the time the parsing stated. StartTime time.Time // DryRun defines whether the parsing process should skip setting flag // value. DryRun bool // PosArgsBuffer serves as the buffer for appending positional args found // during parsing. // // Make sure its length is zero to avoid unexpected positional args being // used. PosArgsBuffer []string // HandleError is the function get called to handle flag parsing errors. HandleError FlagErrorHandleFunc }
type RegExp ¶
type RegExp = ExplicitFlag[regexp.Regexp, RegExpParser[regexp.Regexp]]
RegExp for a single regular expression
type RegExpNoCase ¶
type RegExpNoCase = ExplicitFlag[regexp.Regexp, RegExpNoCaseParser[regexp.Regexp]]
RegExpNoCase for case-insensitive regular expression
type RegExpNoCaseParser ¶
RegExpNoCaseParser parses an arg string to a case-insensitive regexp.Regexp.
func (RegExpNoCaseParser[T]) ParseValue ¶
func (RegExpNoCaseParser[T]) ParseValue(opts *ParseOptions, arg string, out *T) (err error)
type RegExpParser ¶
RegExpParser parses an arg string to a regexp.Regexp.
func (RegExpParser[T]) ParseValue ¶
func (RegExpParser[T]) ParseValue(opts *ParseOptions, arg string, out *T) (err error)
type RegexpNoCaseSlice ¶
type RegexpNoCaseSlice = ExplicitFlag[[]regexp.Regexp, SliceParser[regexp.Regexp, RegExpNoCaseParser[regexp.Regexp]]]
slice flags
type RegexpSlice ¶
type RegexpSlice = ExplicitFlag[[]regexp.Regexp, SliceParser[regexp.Regexp, RegExpParser[regexp.Regexp]]]
slice flags
type SizeParser ¶
SizeParser parses size strings with suffix like:
b, k, KB, g, GB, ..., PB
parsed value is the size in bytes, size overflow will cause error
func (SizeParser[T]) ParseValue ¶
func (SizeParser[T]) ParseValue(opts *ParseOptions, arg string, out *T) (err error)
type SizeSlice ¶
type SizeSlice = ExplicitFlag[[]int64, SliceParser[int64, SizeParser[int64]]]
slice flags
type SliceParser ¶
type SliceParser[T any, P ValueParser[T]] struct{}
SliceParser parses a slice of T
func (SliceParser[T, P]) ParseValue ¶
func (SliceParser[T, P]) ParseValue(opts *ParseOptions, arg string, out *[]T) (err error)
type StringParser ¶
type StringParser[T ~string] struct{}
StringParser converts an arg string to T string.
func (StringParser[T]) ParseValue ¶
func (StringParser[T]) ParseValue(opts *ParseOptions, arg string, out *T) error
type StringSlice ¶
type StringSlice = ExplicitFlag[[]string, SliceParser[string, StringParser[string]]]
slice flags
type SumParser ¶
type SumParser[T numhelper.Number, P ValueParser[T]] struct{}
SumParser sums all parsed value into the target
func (SumParser[T, P]) ParseValue ¶
func (SumParser[T, P]) ParseValue(opts *ParseOptions, arg string, out *T) (err error)
type TimeParser ¶
func (TimeParser[T]) ParseValue ¶
func (TimeParser[T]) ParseValue(opts *ParseOptions, arg string, out *T) (err error)
type TimeSlice ¶
type TimeSlice = ExplicitFlag[[]time.Time, SliceParser[time.Time, TimeParser[time.Time]]]
slice flags
type Uint16Slice ¶
type Uint16Slice = ExplicitFlag[[]uint16, SliceParser[uint16, IntParser[uint16]]]
slice flags
type Uint32Slice ¶
type Uint32Slice = ExplicitFlag[[]uint32, SliceParser[uint32, IntParser[uint32]]]
slice flags
type Uint64Slice ¶
type Uint64Slice = ExplicitFlag[[]uint64, SliceParser[uint64, IntParser[uint64]]]
slice flags
type Uint8Slice ¶
type Uint8Slice = ExplicitFlag[[]uint8, SliceParser[uint8, IntParser[uint8]]]
slice flags
type UintSlice ¶
type UintSlice = ExplicitFlag[[]uint, SliceParser[uint, IntParser[uint]]]
slice flags
type UintptrSlice ¶
type UintptrSlice = ExplicitFlag[[]uintptr, SliceParser[uintptr, IntParser[uintptr]]]
slice flags
type UintptrSum ¶
sum flags
type UnixMilli ¶
type UnixMilli = ExplicitFlag[int64, UnixMilliParser[int64]]
UnixMilli is like UnixTimestamp but for milliseconds since the unix epoch.
type UnixMilliParser ¶
type UnixMilliParser[T ~int64] struct{}
func (UnixMilliParser[T]) ParseValue ¶
func (UnixMilliParser[T]) ParseValue(opts *ParseOptions, arg string, out *T) (err error)
type UnixMilliSlice ¶
type UnixMilliSlice = ExplicitFlag[[]int64, SliceParser[int64, UnixMilliParser[int64]]]
slice flags
type UnixNano ¶
type UnixNano = ExplicitFlag[int64, UnixNanoParser[int64]]
UnixNano is like UnixTimestamp but for nanoseconds since the unix epoch.
type UnixNanoParser ¶
type UnixNanoParser[T ~int64] struct{}
func (UnixNanoParser[T]) ParseValue ¶
func (UnixNanoParser[T]) ParseValue(opts *ParseOptions, arg string, out *T) (err error)
type UnixNanoSlice ¶
type UnixNanoSlice = ExplicitFlag[[]int64, SliceParser[int64, UnixNanoParser[int64]]]
slice flags
type UnixTimestamp ¶
type UnixTimestamp = ExplicitFlag[int64, UnixTimestampParser[int64]]
UnixTimestamp is like Time but stores a int64 of the corresponding unix timestamp (seconds since the unix epoch).
type UnixTimestampParser ¶
type UnixTimestampParser[T ~int64] struct{}
func (UnixTimestampParser[T]) ParseValue ¶
func (UnixTimestampParser[T]) ParseValue(opts *ParseOptions, arg string, out *T) (err error)
type UnixTimestampSlice ¶
type UnixTimestampSlice = ExplicitFlag[[]int64, SliceParser[int64, UnixTimestampParser[int64]]]
slice flags
type ValueParser ¶
type ValueParser[T any] interface { // ParseValue parses a string arg into out // // NOTE: Implementation MUST handle nil opts correctly ParseValue(opts *ParseOptions, arg string, out *T) error }
ValueParser
NOTE: This package expects all ValueParser implementations to be stateless and zero size, external values should be put into ParseOptions.