Path: blob/main/vendor/github.com/spf13/pflag/flag.go
2875 views
// Copyright 2009 The Go Authors. All rights reserved.1// Use of this source code is governed by a BSD-style2// license that can be found in the LICENSE file.34/*5Package pflag is a drop-in replacement for Go's flag package, implementing6POSIX/GNU-style --flags.78pflag is compatible with the GNU extensions to the POSIX recommendations9for command-line options. See10http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html1112Usage:1314pflag is a drop-in replacement of Go's native flag package. If you import15pflag under the name "flag" then all code should continue to function16with no changes.1718import flag "github.com/spf13/pflag"1920There is one exception to this: if you directly instantiate the Flag struct21there is one more field "Shorthand" that you will need to set.22Most code never instantiates this struct directly, and instead uses23functions such as String(), BoolVar(), and Var(), and is therefore24unaffected.2526Define flags using flag.String(), Bool(), Int(), etc.2728This declares an integer flag, -flagname, stored in the pointer ip, with type *int.2930var ip = flag.Int("flagname", 1234, "help message for flagname")3132If you like, you can bind the flag to a variable using the Var() functions.3334var flagvar int35func init() {36flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")37}3839Or you can create custom flags that satisfy the Value interface (with40pointer receivers) and couple them to flag parsing by4142flag.Var(&flagVal, "name", "help message for flagname")4344For such flags, the default value is just the initial value of the variable.4546After all flags are defined, call4748flag.Parse()4950to parse the command line into the defined flags.5152Flags may then be used directly. If you're using the flags themselves,53they are all pointers; if you bind to variables, they're values.5455fmt.Println("ip has value ", *ip)56fmt.Println("flagvar has value ", flagvar)5758After parsing, the arguments after the flag are available as the59slice flag.Args() or individually as flag.Arg(i).60The arguments are indexed from 0 through flag.NArg()-1.6162The pflag package also defines some new functions that are not in flag,63that give one-letter shorthands for flags. You can use these by appending64'P' to the name of any function that defines a flag.6566var ip = flag.IntP("flagname", "f", 1234, "help message")67var flagvar bool68func init() {69flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")70}71flag.VarP(&flagval, "varname", "v", "help message")7273Shorthand letters can be used with single dashes on the command line.74Boolean shorthand flags can be combined with other shorthand flags.7576Command line flag syntax:7778--flag // boolean flags only79--flag=x8081Unlike the flag package, a single dash before an option means something82different than a double dash. Single dashes signify a series of shorthand83letters for flags. All but the last shorthand letter must be boolean flags.8485// boolean flags86-f87-abc88// non-boolean flags89-n 123490-Ifile91// mixed92-abcs "hello"93-abcn12349495Flag parsing stops after the terminator "--". Unlike the flag package,96flags can be interspersed with arguments anywhere on the command line97before this terminator.9899Integer flags accept 1234, 0664, 0x1234 and may be negative.100Boolean flags (in their long form) accept 1, 0, t, f, true, false,101TRUE, FALSE, True, False.102Duration flags accept any input valid for time.ParseDuration.103104The default set of command-line flags is controlled by105top-level functions. The FlagSet type allows one to define106independent sets of flags, such as to implement subcommands107in a command-line interface. The methods of FlagSet are108analogous to the top-level functions for the command-line109flag set.110*/111package pflag112113import (114"bytes"115"errors"116goflag "flag"117"fmt"118"io"119"os"120"sort"121"strings"122)123124// ErrHelp is the error returned if the flag -help is invoked but no such flag is defined.125var ErrHelp = errors.New("pflag: help requested")126127// ErrorHandling defines how to handle flag parsing errors.128type ErrorHandling int129130const (131// ContinueOnError will return an err from Parse() if an error is found132ContinueOnError ErrorHandling = iota133// ExitOnError will call os.Exit(2) if an error is found when parsing134ExitOnError135// PanicOnError will panic() if an error is found when parsing flags136PanicOnError137)138139// ParseErrorsAllowlist defines the parsing errors that can be ignored140type ParseErrorsAllowlist struct {141// UnknownFlags will ignore unknown flags errors and continue parsing rest of the flags142UnknownFlags bool143}144145// ParseErrorsWhitelist defines the parsing errors that can be ignored.146//147// Deprecated: use [ParseErrorsAllowlist] instead. This type will be removed in a future release.148type ParseErrorsWhitelist = ParseErrorsAllowlist149150// NormalizedName is a flag name that has been normalized according to rules151// for the FlagSet (e.g. making '-' and '_' equivalent).152type NormalizedName string153154// A FlagSet represents a set of defined flags.155type FlagSet struct {156// Usage is the function called when an error occurs while parsing flags.157// The field is a function (not a method) that may be changed to point to158// a custom error handler.159Usage func()160161// SortFlags is used to indicate, if user wants to have sorted flags in162// help/usage messages.163SortFlags bool164165// ParseErrorsAllowlist is used to configure an allowlist of errors166ParseErrorsAllowlist ParseErrorsAllowlist167168// ParseErrorsAllowlist is used to configure an allowlist of errors.169//170// Deprecated: use [FlagSet.ParseErrorsAllowlist] instead. This field will be removed in a future release.171ParseErrorsWhitelist ParseErrorsAllowlist172173name string174parsed bool175actual map[NormalizedName]*Flag176orderedActual []*Flag177sortedActual []*Flag178formal map[NormalizedName]*Flag179orderedFormal []*Flag180sortedFormal []*Flag181shorthands map[byte]*Flag182args []string // arguments after flags183argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no --184errorHandling ErrorHandling185output io.Writer // nil means stderr; use Output() accessor186interspersed bool // allow interspersed option/non-option args187normalizeNameFunc func(f *FlagSet, name string) NormalizedName188189addedGoFlagSets []*goflag.FlagSet190}191192// A Flag represents the state of a flag.193type Flag struct {194Name string // name as it appears on command line195Shorthand string // one-letter abbreviated flag196Usage string // help message197Value Value // value as set198DefValue string // default value (as text); for usage message199Changed bool // If the user set the value (or if left to default)200NoOptDefVal string // default value (as text); if the flag is on the command line without any options201Deprecated string // If this flag is deprecated, this string is the new or now thing to use202Hidden bool // used by cobra.Command to allow flags to be hidden from help/usage text203ShorthandDeprecated string // If the shorthand of this flag is deprecated, this string is the new or now thing to use204Annotations map[string][]string // used by cobra.Command bash autocomple code205}206207// Value is the interface to the dynamic value stored in a flag.208// (The default value is represented as a string.)209type Value interface {210String() string211Set(string) error212Type() string213}214215// SliceValue is a secondary interface to all flags which hold a list216// of values. This allows full control over the value of list flags,217// and avoids complicated marshalling and unmarshalling to csv.218type SliceValue interface {219// Append adds the specified value to the end of the flag value list.220Append(string) error221// Replace will fully overwrite any data currently in the flag value list.222Replace([]string) error223// GetSlice returns the flag value list as an array of strings.224GetSlice() []string225}226227// sortFlags returns the flags as a slice in lexicographical sorted order.228func sortFlags(flags map[NormalizedName]*Flag) []*Flag {229list := make(sort.StringSlice, len(flags))230i := 0231for k := range flags {232list[i] = string(k)233i++234}235list.Sort()236result := make([]*Flag, len(list))237for i, name := range list {238result[i] = flags[NormalizedName(name)]239}240return result241}242243// SetNormalizeFunc allows you to add a function which can translate flag names.244// Flags added to the FlagSet will be translated and then when anything tries to245// look up the flag that will also be translated. So it would be possible to create246// a flag named "getURL" and have it translated to "geturl". A user could then pass247// "--getUrl" which may also be translated to "geturl" and everything will work.248func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) {249f.normalizeNameFunc = n250f.sortedFormal = f.sortedFormal[:0]251for fname, flag := range f.formal {252nname := f.normalizeFlagName(flag.Name)253if fname == nname {254continue255}256flag.Name = string(nname)257delete(f.formal, fname)258f.formal[nname] = flag259if _, set := f.actual[fname]; set {260delete(f.actual, fname)261f.actual[nname] = flag262}263}264}265266// GetNormalizeFunc returns the previously set NormalizeFunc of a function which267// does no translation, if not set previously.268func (f *FlagSet) GetNormalizeFunc() func(f *FlagSet, name string) NormalizedName {269if f.normalizeNameFunc != nil {270return f.normalizeNameFunc271}272return func(f *FlagSet, name string) NormalizedName { return NormalizedName(name) }273}274275func (f *FlagSet) normalizeFlagName(name string) NormalizedName {276n := f.GetNormalizeFunc()277return n(f, name)278}279280// Output returns the destination for usage and error messages. os.Stderr is returned if281// output was not set or was set to nil.282func (f *FlagSet) Output() io.Writer {283if f.output == nil {284return os.Stderr285}286return f.output287}288289// Name returns the name of the flag set.290func (f *FlagSet) Name() string {291return f.name292}293294// SetOutput sets the destination for usage and error messages.295// If output is nil, os.Stderr is used.296func (f *FlagSet) SetOutput(output io.Writer) {297f.output = output298}299300// VisitAll visits the flags in lexicographical order or301// in primordial order if f.SortFlags is false, calling fn for each.302// It visits all flags, even those not set.303func (f *FlagSet) VisitAll(fn func(*Flag)) {304if len(f.formal) == 0 {305return306}307308var flags []*Flag309if f.SortFlags {310if len(f.formal) != len(f.sortedFormal) {311f.sortedFormal = sortFlags(f.formal)312}313flags = f.sortedFormal314} else {315flags = f.orderedFormal316}317318for _, flag := range flags {319fn(flag)320}321}322323// HasFlags returns a bool to indicate if the FlagSet has any flags defined.324func (f *FlagSet) HasFlags() bool {325return len(f.formal) > 0326}327328// HasAvailableFlags returns a bool to indicate if the FlagSet has any flags329// that are not hidden.330func (f *FlagSet) HasAvailableFlags() bool {331for _, flag := range f.formal {332if !flag.Hidden {333return true334}335}336return false337}338339// VisitAll visits the command-line flags in lexicographical order or340// in primordial order if f.SortFlags is false, calling fn for each.341// It visits all flags, even those not set.342func VisitAll(fn func(*Flag)) {343CommandLine.VisitAll(fn)344}345346// Visit visits the flags in lexicographical order or347// in primordial order if f.SortFlags is false, calling fn for each.348// It visits only those flags that have been set.349func (f *FlagSet) Visit(fn func(*Flag)) {350if len(f.actual) == 0 {351return352}353354var flags []*Flag355if f.SortFlags {356if len(f.actual) != len(f.sortedActual) {357f.sortedActual = sortFlags(f.actual)358}359flags = f.sortedActual360} else {361flags = f.orderedActual362}363364for _, flag := range flags {365fn(flag)366}367}368369// Visit visits the command-line flags in lexicographical order or370// in primordial order if f.SortFlags is false, calling fn for each.371// It visits only those flags that have been set.372func Visit(fn func(*Flag)) {373CommandLine.Visit(fn)374}375376// Lookup returns the Flag structure of the named flag, returning nil if none exists.377func (f *FlagSet) Lookup(name string) *Flag {378return f.lookup(f.normalizeFlagName(name))379}380381// ShorthandLookup returns the Flag structure of the short handed flag,382// returning nil if none exists.383// It panics, if len(name) > 1.384func (f *FlagSet) ShorthandLookup(name string) *Flag {385if name == "" {386return nil387}388if len(name) > 1 {389msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name)390fmt.Fprintf(f.Output(), msg)391panic(msg)392}393c := name[0]394return f.shorthands[c]395}396397// lookup returns the Flag structure of the named flag, returning nil if none exists.398func (f *FlagSet) lookup(name NormalizedName) *Flag {399return f.formal[name]400}401402// func to return a given type for a given flag name403func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval string) (interface{}, error)) (interface{}, error) {404flag := f.Lookup(name)405if flag == nil {406err := &NotExistError{name: name, messageType: flagNotDefinedMessage}407return nil, err408}409410if flag.Value.Type() != ftype {411err := fmt.Errorf("trying to get %s value of flag of type %s", ftype, flag.Value.Type())412return nil, err413}414415sval := flag.Value.String()416result, err := convFunc(sval)417if err != nil {418return nil, err419}420return result, nil421}422423// ArgsLenAtDash will return the length of f.Args at the moment when a -- was424// found during arg parsing. This allows your program to know which args were425// before the -- and which came after.426func (f *FlagSet) ArgsLenAtDash() int {427return f.argsLenAtDash428}429430// MarkDeprecated indicated that a flag is deprecated in your program. It will431// continue to function but will not show up in help or usage messages. Using432// this flag will also print the given usageMessage.433func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {434flag := f.Lookup(name)435if flag == nil {436return &NotExistError{name: name, messageType: flagNotExistMessage}437}438if usageMessage == "" {439return fmt.Errorf("deprecated message for flag %q must be set", name)440}441flag.Deprecated = usageMessage442flag.Hidden = true443return nil444}445446// MarkShorthandDeprecated will mark the shorthand of a flag deprecated in your447// program. It will continue to function but will not show up in help or usage448// messages. Using this flag will also print the given usageMessage.449func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) error {450flag := f.Lookup(name)451if flag == nil {452return &NotExistError{name: name, messageType: flagNotExistMessage}453}454if usageMessage == "" {455return fmt.Errorf("deprecated message for flag %q must be set", name)456}457flag.ShorthandDeprecated = usageMessage458return nil459}460461// MarkHidden sets a flag to 'hidden' in your program. It will continue to462// function but will not show up in help or usage messages.463func (f *FlagSet) MarkHidden(name string) error {464flag := f.Lookup(name)465if flag == nil {466return &NotExistError{name: name, messageType: flagNotExistMessage}467}468flag.Hidden = true469return nil470}471472// Lookup returns the Flag structure of the named command-line flag,473// returning nil if none exists.474func Lookup(name string) *Flag {475return CommandLine.Lookup(name)476}477478// ShorthandLookup returns the Flag structure of the short handed flag,479// returning nil if none exists.480func ShorthandLookup(name string) *Flag {481return CommandLine.ShorthandLookup(name)482}483484// Set sets the value of the named flag.485func (f *FlagSet) Set(name, value string) error {486normalName := f.normalizeFlagName(name)487flag, ok := f.formal[normalName]488if !ok {489return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}490}491492err := flag.Value.Set(value)493if err != nil {494return &InvalidValueError{495flag: flag,496value: value,497cause: err,498}499}500501if !flag.Changed {502if f.actual == nil {503f.actual = make(map[NormalizedName]*Flag)504}505f.actual[normalName] = flag506f.orderedActual = append(f.orderedActual, flag)507508flag.Changed = true509}510511if flag.Deprecated != "" {512fmt.Fprintf(f.Output(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)513}514return nil515}516517// SetAnnotation allows one to set arbitrary annotations on a flag in the FlagSet.518// This is sometimes used by spf13/cobra programs which want to generate additional519// bash completion information.520func (f *FlagSet) SetAnnotation(name, key string, values []string) error {521normalName := f.normalizeFlagName(name)522flag, ok := f.formal[normalName]523if !ok {524return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}525}526if flag.Annotations == nil {527flag.Annotations = map[string][]string{}528}529flag.Annotations[key] = values530return nil531}532533// Changed returns true if the flag was explicitly set during Parse() and false534// otherwise535func (f *FlagSet) Changed(name string) bool {536flag := f.Lookup(name)537// If a flag doesn't exist, it wasn't changed....538if flag == nil {539return false540}541return flag.Changed542}543544// Set sets the value of the named command-line flag.545func Set(name, value string) error {546return CommandLine.Set(name, value)547}548549// PrintDefaults prints, to standard error unless configured550// otherwise, the default values of all defined flags in the set.551func (f *FlagSet) PrintDefaults() {552usages := f.FlagUsages()553fmt.Fprint(f.Output(), usages)554}555556// defaultIsZeroValue returns true if the default value for this flag represents557// a zero value.558func (f *Flag) defaultIsZeroValue() bool {559switch f.Value.(type) {560case boolFlag:561return f.DefValue == "false" || f.DefValue == ""562case *durationValue:563// Beginning in Go 1.7, duration zero values are "0s"564return f.DefValue == "0" || f.DefValue == "0s"565case *intValue, *int8Value, *int32Value, *int64Value, *uintValue, *uint8Value, *uint16Value, *uint32Value, *uint64Value, *countValue, *float32Value, *float64Value:566return f.DefValue == "0"567case *stringValue:568return f.DefValue == ""569case *ipValue, *ipMaskValue, *ipNetValue:570return f.DefValue == "<nil>"571case *intSliceValue, *stringSliceValue, *stringArrayValue:572return f.DefValue == "[]"573default:574switch f.DefValue {575case "false":576return true577case "<nil>":578return true579case "":580return true581case "0":582return true583}584return false585}586}587588// UnquoteUsage extracts a back-quoted name from the usage589// string for a flag and returns it and the un-quoted usage.590// Given "a `name` to show" it returns ("name", "a name to show").591// If there are no back quotes, the name is an educated guess of the592// type of the flag's value, or the empty string if the flag is boolean.593func UnquoteUsage(flag *Flag) (name string, usage string) {594// Look for a back-quoted name, but avoid the strings package.595usage = flag.Usage596for i := 0; i < len(usage); i++ {597if usage[i] == '`' {598for j := i + 1; j < len(usage); j++ {599if usage[j] == '`' {600name = usage[i+1 : j]601usage = usage[:i] + name + usage[j+1:]602return name, usage603}604}605break // Only one back quote; use type name.606}607}608609name = flag.Value.Type()610switch name {611case "bool", "boolfunc":612name = ""613case "func":614name = "value"615case "float64":616name = "float"617case "int64":618name = "int"619case "uint64":620name = "uint"621case "stringSlice":622name = "strings"623case "intSlice":624name = "ints"625case "uintSlice":626name = "uints"627case "boolSlice":628name = "bools"629}630631return632}633634// Splits the string `s` on whitespace into an initial substring up to635// `i` runes in length and the remainder. Will go `slop` over `i` if636// that encompasses the entire string (which allows the caller to637// avoid short orphan words on the final line).638func wrapN(i, slop int, s string) (string, string) {639if i+slop > len(s) {640return s, ""641}642643w := strings.LastIndexAny(s[:i], " \t\n")644if w <= 0 {645return s, ""646}647nlPos := strings.LastIndex(s[:i], "\n")648if nlPos > 0 && nlPos < w {649return s[:nlPos], s[nlPos+1:]650}651return s[:w], s[w+1:]652}653654// Wraps the string `s` to a maximum width `w` with leading indent655// `i`. The first line is not indented (this is assumed to be done by656// caller). Pass `w` == 0 to do no wrapping657func wrap(i, w int, s string) string {658if w == 0 {659return strings.Replace(s, "\n", "\n"+strings.Repeat(" ", i), -1)660}661662// space between indent i and end of line width w into which663// we should wrap the text.664wrap := w - i665666var r, l string667668// Not enough space for sensible wrapping. Wrap as a block on669// the next line instead.670if wrap < 24 {671i = 16672wrap = w - i673r += "\n" + strings.Repeat(" ", i)674}675// If still not enough space then don't even try to wrap.676if wrap < 24 {677return strings.Replace(s, "\n", r, -1)678}679680// Try to avoid short orphan words on the final line, by681// allowing wrapN to go a bit over if that would fit in the682// remainder of the line.683slop := 5684wrap = wrap - slop685686// Handle first line, which is indented by the caller (or the687// special case above)688l, s = wrapN(wrap, slop, s)689r = r + strings.Replace(l, "\n", "\n"+strings.Repeat(" ", i), -1)690691// Now wrap the rest692for s != "" {693var t string694695t, s = wrapN(wrap, slop, s)696r = r + "\n" + strings.Repeat(" ", i) + strings.Replace(t, "\n", "\n"+strings.Repeat(" ", i), -1)697}698699return r700701}702703// FlagUsagesWrapped returns a string containing the usage information704// for all flags in the FlagSet. Wrapped to `cols` columns (0 for no705// wrapping)706func (f *FlagSet) FlagUsagesWrapped(cols int) string {707buf := new(bytes.Buffer)708709lines := make([]string, 0, len(f.formal))710711maxlen := 0712f.VisitAll(func(flag *Flag) {713if flag.Hidden {714return715}716717line := ""718if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {719line = fmt.Sprintf(" -%s, --%s", flag.Shorthand, flag.Name)720} else {721line = fmt.Sprintf(" --%s", flag.Name)722}723724varname, usage := UnquoteUsage(flag)725if varname != "" {726line += " " + varname727}728if flag.NoOptDefVal != "" {729switch flag.Value.Type() {730case "string":731line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal)732case "bool", "boolfunc":733if flag.NoOptDefVal != "true" {734line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)735}736case "count":737if flag.NoOptDefVal != "+1" {738line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)739}740default:741line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)742}743}744745// This special character will be replaced with spacing once the746// correct alignment is calculated747line += "\x00"748if len(line) > maxlen {749maxlen = len(line)750}751752line += usage753if !flag.defaultIsZeroValue() {754if flag.Value.Type() == "string" {755line += fmt.Sprintf(" (default %q)", flag.DefValue)756} else {757line += fmt.Sprintf(" (default %s)", flag.DefValue)758}759}760if len(flag.Deprecated) != 0 {761line += fmt.Sprintf(" (DEPRECATED: %s)", flag.Deprecated)762}763764lines = append(lines, line)765})766767for _, line := range lines {768sidx := strings.Index(line, "\x00")769spacing := strings.Repeat(" ", maxlen-sidx)770// maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx771fmt.Fprintln(buf, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:]))772}773774return buf.String()775}776777// FlagUsages returns a string containing the usage information for all flags in778// the FlagSet779func (f *FlagSet) FlagUsages() string {780return f.FlagUsagesWrapped(0)781}782783// PrintDefaults prints to standard error the default values of all defined command-line flags.784func PrintDefaults() {785CommandLine.PrintDefaults()786}787788// defaultUsage is the default function to print a usage message.789func defaultUsage(f *FlagSet) {790fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name)791f.PrintDefaults()792}793794// NOTE: Usage is not just defaultUsage(CommandLine)795// because it serves (via godoc flag Usage) as the example796// for how to write your own usage function.797798// Usage prints to standard error a usage message documenting all defined command-line flags.799// The function is a variable that may be changed to point to a custom function.800// By default it prints a simple header and calls PrintDefaults; for details about the801// format of the output and how to control it, see the documentation for PrintDefaults.802var Usage = func() {803fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])804PrintDefaults()805}806807// NFlag returns the number of flags that have been set.808func (f *FlagSet) NFlag() int { return len(f.actual) }809810// NFlag returns the number of command-line flags that have been set.811func NFlag() int { return len(CommandLine.actual) }812813// Arg returns the i'th argument. Arg(0) is the first remaining argument814// after flags have been processed.815func (f *FlagSet) Arg(i int) string {816if i < 0 || i >= len(f.args) {817return ""818}819return f.args[i]820}821822// Arg returns the i'th command-line argument. Arg(0) is the first remaining argument823// after flags have been processed.824func Arg(i int) string {825return CommandLine.Arg(i)826}827828// NArg is the number of arguments remaining after flags have been processed.829func (f *FlagSet) NArg() int { return len(f.args) }830831// NArg is the number of arguments remaining after flags have been processed.832func NArg() int { return len(CommandLine.args) }833834// Args returns the non-flag arguments.835func (f *FlagSet) Args() []string { return f.args }836837// Args returns the non-flag command-line arguments.838func Args() []string { return CommandLine.args }839840// Var defines a flag with the specified name and usage string. The type and841// value of the flag are represented by the first argument, of type Value, which842// typically holds a user-defined implementation of Value. For instance, the843// caller could create a flag that turns a comma-separated string into a slice844// of strings by giving the slice the methods of Value; in particular, Set would845// decompose the comma-separated string into the slice.846func (f *FlagSet) Var(value Value, name string, usage string) {847f.VarP(value, name, "", usage)848}849850// VarPF is like VarP, but returns the flag created851func (f *FlagSet) VarPF(value Value, name, shorthand, usage string) *Flag {852// Remember the default value as a string; it won't change.853flag := &Flag{854Name: name,855Shorthand: shorthand,856Usage: usage,857Value: value,858DefValue: value.String(),859}860f.AddFlag(flag)861return flag862}863864// VarP is like Var, but accepts a shorthand letter that can be used after a single dash.865func (f *FlagSet) VarP(value Value, name, shorthand, usage string) {866f.VarPF(value, name, shorthand, usage)867}868869// AddFlag will add the flag to the FlagSet870func (f *FlagSet) AddFlag(flag *Flag) {871normalizedFlagName := f.normalizeFlagName(flag.Name)872873_, alreadyThere := f.formal[normalizedFlagName]874if alreadyThere {875msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name)876fmt.Fprintln(f.Output(), msg)877panic(msg) // Happens only if flags are declared with identical names878}879if f.formal == nil {880f.formal = make(map[NormalizedName]*Flag)881}882883flag.Name = string(normalizedFlagName)884f.formal[normalizedFlagName] = flag885f.orderedFormal = append(f.orderedFormal, flag)886887if flag.Shorthand == "" {888return889}890if len(flag.Shorthand) > 1 {891msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand)892fmt.Fprintf(f.Output(), msg)893panic(msg)894}895if f.shorthands == nil {896f.shorthands = make(map[byte]*Flag)897}898c := flag.Shorthand[0]899used, alreadyThere := f.shorthands[c]900if alreadyThere {901msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name)902fmt.Fprintf(f.Output(), msg)903panic(msg)904}905f.shorthands[c] = flag906}907908// AddFlagSet adds one FlagSet to another. If a flag is already present in f909// the flag from newSet will be ignored.910func (f *FlagSet) AddFlagSet(newSet *FlagSet) {911if newSet == nil {912return913}914newSet.VisitAll(func(flag *Flag) {915if f.Lookup(flag.Name) == nil {916f.AddFlag(flag)917}918})919}920921// Var defines a flag with the specified name and usage string. The type and922// value of the flag are represented by the first argument, of type Value, which923// typically holds a user-defined implementation of Value. For instance, the924// caller could create a flag that turns a comma-separated string into a slice925// of strings by giving the slice the methods of Value; in particular, Set would926// decompose the comma-separated string into the slice.927func Var(value Value, name string, usage string) {928CommandLine.VarP(value, name, "", usage)929}930931// VarP is like Var, but accepts a shorthand letter that can be used after a single dash.932func VarP(value Value, name, shorthand, usage string) {933CommandLine.VarP(value, name, shorthand, usage)934}935936// fail prints an error message and usage message to standard error and937// returns the error.938func (f *FlagSet) fail(err error) error {939if f.errorHandling != ContinueOnError {940f.usage()941}942return err943}944945// usage calls the Usage method for the flag set, or the usage function if946// the flag set is CommandLine.947func (f *FlagSet) usage() {948if f == CommandLine {949Usage()950} else if f.Usage == nil {951defaultUsage(f)952} else {953f.Usage()954}955}956957// --unknown (args will be empty)958// --unknown --next-flag ... (args will be --next-flag ...)959// --unknown arg ... (args will be arg ...)960func stripUnknownFlagValue(args []string) []string {961if len(args) == 0 {962//--unknown963return args964}965966first := args[0]967if len(first) > 0 && first[0] == '-' {968//--unknown --next-flag ...969return args970}971972//--unknown arg ... (args will be arg ...)973if len(args) > 1 {974return args[1:]975}976return nil977}978979func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {980a = args981name := s[2:]982if len(name) == 0 || name[0] == '-' || name[0] == '=' {983err = f.fail(&InvalidSyntaxError{specifiedFlag: s})984return985}986987split := strings.SplitN(name, "=", 2)988name = split[0]989flag, exists := f.formal[f.normalizeFlagName(name)]990991if !exists {992switch {993case name == "help":994f.usage()995return a, ErrHelp996case f.ParseErrorsWhitelist.UnknownFlags:997fallthrough998case f.ParseErrorsAllowlist.UnknownFlags:999// --unknown=unknownval arg ...1000// we do not want to lose arg in this case1001if len(split) >= 2 {1002return a, nil1003}10041005return stripUnknownFlagValue(a), nil1006default:1007err = f.fail(&NotExistError{name: name, messageType: flagUnknownFlagMessage})1008return1009}1010}10111012var value string1013if len(split) == 2 {1014// '--flag=arg'1015value = split[1]1016} else if flag.NoOptDefVal != "" {1017// '--flag' (arg was optional)1018value = flag.NoOptDefVal1019} else if len(a) > 0 {1020// '--flag arg'1021value = a[0]1022a = a[1:]1023} else {1024// '--flag' (arg was required)1025err = f.fail(&ValueRequiredError{1026flag: flag,1027specifiedName: name,1028})1029return1030}10311032err = fn(flag, value)1033if err != nil {1034f.fail(err)1035}1036return1037}10381039func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {1040outArgs = args10411042if isGotestShorthandFlag(shorthands) {1043return1044}10451046outShorts = shorthands[1:]1047c := shorthands[0]10481049flag, exists := f.shorthands[c]1050if !exists {1051switch {1052case c == 'h':1053f.usage()1054err = ErrHelp1055return1056case f.ParseErrorsWhitelist.UnknownFlags:1057fallthrough1058case f.ParseErrorsAllowlist.UnknownFlags:1059// '-f=arg arg ...'1060// we do not want to lose arg in this case1061if len(shorthands) > 2 && shorthands[1] == '=' {1062outShorts = ""1063return1064}10651066outArgs = stripUnknownFlagValue(outArgs)1067return1068default:1069err = f.fail(&NotExistError{1070name: string(c),1071specifiedShorthands: shorthands,1072messageType: flagUnknownShorthandFlagMessage,1073})1074return1075}1076}10771078var value string1079if len(shorthands) > 2 && shorthands[1] == '=' {1080// '-f=arg'1081value = shorthands[2:]1082outShorts = ""1083} else if flag.NoOptDefVal != "" {1084// '-f' (arg was optional)1085value = flag.NoOptDefVal1086} else if len(shorthands) > 1 {1087// '-farg'1088value = shorthands[1:]1089outShorts = ""1090} else if len(args) > 0 {1091// '-f arg'1092value = args[0]1093outArgs = args[1:]1094} else {1095// '-f' (arg was required)1096err = f.fail(&ValueRequiredError{1097flag: flag,1098specifiedName: string(c),1099specifiedShorthands: shorthands,1100})1101return1102}11031104if flag.ShorthandDeprecated != "" {1105fmt.Fprintf(f.Output(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)1106}11071108err = fn(flag, value)1109if err != nil {1110f.fail(err)1111}1112return1113}11141115func (f *FlagSet) parseShortArg(s string, args []string, fn parseFunc) (a []string, err error) {1116a = args1117shorthands := s[1:]11181119// "shorthands" can be a series of shorthand letters of flags (e.g. "-vvv").1120for len(shorthands) > 0 {1121shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn)1122if err != nil {1123return1124}1125}11261127return1128}11291130func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) {1131for len(args) > 0 {1132s := args[0]1133args = args[1:]1134if len(s) == 0 || s[0] != '-' || len(s) == 1 {1135if !f.interspersed {1136f.args = append(f.args, s)1137f.args = append(f.args, args...)1138return nil1139}1140f.args = append(f.args, s)1141continue1142}11431144if s[1] == '-' {1145if len(s) == 2 { // "--" terminates the flags1146f.argsLenAtDash = len(f.args)1147f.args = append(f.args, args...)1148break1149}1150args, err = f.parseLongArg(s, args, fn)1151} else {1152args, err = f.parseShortArg(s, args, fn)1153}1154if err != nil {1155return1156}1157}1158return1159}11601161// Parse parses flag definitions from the argument list, which should not1162// include the command name. Must be called after all flags in the FlagSet1163// are defined and before flags are accessed by the program.1164// The return value will be ErrHelp if -help was set but not defined.1165func (f *FlagSet) Parse(arguments []string) error {1166if f.addedGoFlagSets != nil {1167for _, goFlagSet := range f.addedGoFlagSets {1168goFlagSet.Parse(nil)1169}1170}1171f.parsed = true11721173f.args = make([]string, 0, len(arguments))11741175if len(arguments) == 0 {1176return nil1177}11781179set := func(flag *Flag, value string) error {1180return f.Set(flag.Name, value)1181}11821183err := f.parseArgs(arguments, set)1184if err != nil {1185switch f.errorHandling {1186case ContinueOnError:1187return err1188case ExitOnError:1189if err == ErrHelp {1190os.Exit(0)1191}1192fmt.Fprintln(f.Output(), err)1193os.Exit(2)1194case PanicOnError:1195panic(err)1196}1197}1198return nil1199}12001201type parseFunc func(flag *Flag, value string) error12021203// ParseAll parses flag definitions from the argument list, which should not1204// include the command name. The arguments for fn are flag and value. Must be1205// called after all flags in the FlagSet are defined and before flags are1206// accessed by the program. The return value will be ErrHelp if -help was set1207// but not defined.1208func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string) error) error {1209f.parsed = true1210f.args = make([]string, 0, len(arguments))12111212err := f.parseArgs(arguments, fn)1213if err != nil {1214switch f.errorHandling {1215case ContinueOnError:1216return err1217case ExitOnError:1218if err == ErrHelp {1219os.Exit(0)1220}1221fmt.Fprintln(f.Output(), err)1222os.Exit(2)1223case PanicOnError:1224panic(err)1225}1226}1227return nil1228}12291230// Parsed reports whether f.Parse has been called.1231func (f *FlagSet) Parsed() bool {1232return f.parsed1233}12341235// Parse parses the command-line flags from os.Args[1:]. Must be called1236// after all flags are defined and before flags are accessed by the program.1237func Parse() {1238// Ignore errors; CommandLine is set for ExitOnError.1239CommandLine.Parse(os.Args[1:])1240}12411242// ParseAll parses the command-line flags from os.Args[1:] and called fn for each.1243// The arguments for fn are flag and value. Must be called after all flags are1244// defined and before flags are accessed by the program.1245func ParseAll(fn func(flag *Flag, value string) error) {1246// Ignore errors; CommandLine is set for ExitOnError.1247CommandLine.ParseAll(os.Args[1:], fn)1248}12491250// SetInterspersed sets whether to support interspersed option/non-option arguments.1251func SetInterspersed(interspersed bool) {1252CommandLine.SetInterspersed(interspersed)1253}12541255// Parsed returns true if the command-line flags have been parsed.1256func Parsed() bool {1257return CommandLine.Parsed()1258}12591260// CommandLine is the default set of command-line flags, parsed from os.Args.1261var CommandLine = NewFlagSet(os.Args[0], ExitOnError)12621263// NewFlagSet returns a new, empty flag set with the specified name,1264// error handling property and SortFlags set to true.1265func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {1266f := &FlagSet{1267name: name,1268errorHandling: errorHandling,1269argsLenAtDash: -1,1270interspersed: true,1271SortFlags: true,1272}1273return f1274}12751276// SetInterspersed sets whether to support interspersed option/non-option arguments.1277func (f *FlagSet) SetInterspersed(interspersed bool) {1278f.interspersed = interspersed1279}12801281// Init sets the name and error handling property for a flag set.1282// By default, the zero FlagSet uses an empty name and the1283// ContinueOnError error handling policy.1284func (f *FlagSet) Init(name string, errorHandling ErrorHandling) {1285f.name = name1286f.errorHandling = errorHandling1287f.argsLenAtDash = -11288}128912901291