cli

package
v0.12.0 Latest Latest
Warning

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

Go to latest
Published: Dec 27, 2022 License: Apache-2.0 Imports: 16 Imported by: 0

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

View Source
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 Bool

type Bool = ImplicitFlag[bool, BoolParser[bool]]

basic type flags

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) IndexFlag

func (c *Cmd) IndexFlag(i int) (f Flag)

func (*Cmd) LinkChildren

func (c *Cmd) LinkChildren(recursive bool)

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

func (c *Cmd) SearchFlag(name string) (f Flag)

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

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 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
)

func (FlagMark) Changed

func (m FlagMark) Changed() bool

func (FlagMark) Hidden

func (m FlagMark) Hidden() bool

func (FlagMark) Required

func (m FlagMark) Required() bool

type Float32

basic type flags

type Float32Slice

slice flags

type Float32Sum

sum flags

type Float64

basic type flags

type Float64Slice

slice flags

type Float64Sum

sum flags

type FloatParser

type FloatParser[T numhelper.Float] struct{}

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

type FuncIndexer func(name string, index int) Flag

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 Int

type Int = ExplicitFlag[int, IntParser[int]]

basic type flags

type Int16

type Int16 = ExplicitFlag[int16, IntParser[int16]]

basic type flags

type Int16Slice

type Int16Slice = ExplicitFlag[[]int16, SliceParser[int16, IntParser[int16]]]

slice flags

type Int16Sum

sum flags

type Int32

type Int32 = ExplicitFlag[int32, IntParser[int32]]

basic type flags

type Int32Slice

type Int32Slice = ExplicitFlag[[]int32, SliceParser[int32, IntParser[int32]]]

slice flags

type Int32Sum

sum flags

type Int64

type Int64 = ExplicitFlag[int64, IntParser[int64]]

basic type flags

type Int64Slice

type Int64Slice = ExplicitFlag[[]int64, SliceParser[int64, IntParser[int64]]]

slice flags

type Int64Sum

sum flags

type Int8

type Int8 = ExplicitFlag[int8, IntParser[int8]]

basic type flags

type Int8Slice

type Int8Slice = ExplicitFlag[[]int8, SliceParser[int8, IntParser[int8]]]

slice flags

type Int8Sum

sum flags

type IntParser

type IntParser[T numhelper.Integer] struct{}

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 IntSlice

type IntSlice = ExplicitFlag[[]int, SliceParser[int, IntParser[int]]]

slice flags

type IntSum

type IntSum = ImplicitFlag[int, SumParser[int, IntParser[int]]]

sum flags

type MapIndexer

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

func NewMapIndexer

func NewMapIndexer() *MapIndexer

NewMapIndexer returns a new empty MapIndexer.

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

RegExp for a single regular expression

type RegExpNoCase

RegExpNoCase for case-insensitive regular expression

type RegExpNoCaseParser

type RegExpNoCaseParser[T regexp.Regexp] struct{}

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

type RegExpParser[T regexp.Regexp] struct{}

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 Size

basic type flags

type SizeParser

type SizeParser[T numhelper.Integer] struct{}

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

slice flags

type SizeSum

sum 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 String

basic type flags

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

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 Time

Time

type TimeParser

type TimeParser[T time.Time] struct{}

func (TimeParser[T]) ParseValue

func (TimeParser[T]) ParseValue(opts *ParseOptions, arg string, out *T) (err error)

type TimeSlice

slice flags

type Uint

type Uint = ExplicitFlag[uint, IntParser[uint]]

basic type flags

type Uint16

type Uint16 = ExplicitFlag[uint16, IntParser[uint16]]

basic type flags

type Uint16Slice

slice flags

type Uint16Sum

sum flags

type Uint32

type Uint32 = ExplicitFlag[uint32, IntParser[uint32]]

basic type flags

type Uint32Slice

slice flags

type Uint32Sum

sum flags

type Uint64

type Uint64 = ExplicitFlag[uint64, IntParser[uint64]]

basic type flags

type Uint64Slice

slice flags

type Uint64Sum

sum flags

type Uint8

type Uint8 = ExplicitFlag[uint8, IntParser[uint8]]

basic type flags

type Uint8Slice

type Uint8Slice = ExplicitFlag[[]uint8, SliceParser[uint8, IntParser[uint8]]]

slice flags

type Uint8Sum

sum flags

type UintSlice

type UintSlice = ExplicitFlag[[]uint, SliceParser[uint, IntParser[uint]]]

slice flags

type UintSum

sum flags

type Uintptr

basic type flags

type UintptrSlice

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.

Jump to

Keyboard shortcuts

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