| // Copyright 2009 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| /* | |
| Package pflag is a drop-in replacement for Go's flag package, implementing | |
| POSIX/GNU-style --flags. | |
| pflag is compatible with the GNU extensions to the POSIX recommendations | |
| for command-line options. See | |
| http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html | |
| Usage: | |
| pflag is a drop-in replacement of Go's native flag package. If you import | |
| pflag under the name "flag" then all code should continue to function | |
| with no changes. | |
| import flag "github.com/spf13/pflag" | |
| There is one exception to this: if you directly instantiate the Flag struct | |
| there is one more field "Shorthand" that you will need to set. | |
| Most code never instantiates this struct directly, and instead uses | |
| functions such as String(), BoolVar(), and Var(), and is therefore | |
| unaffected. | |
| Define flags using flag.String(), Bool(), Int(), etc. | |
| This declares an integer flag, -flagname, stored in the pointer ip, with type *int. | |
| var ip = flag.Int("flagname", 1234, "help message for flagname") | |
| If you like, you can bind the flag to a variable using the Var() functions. | |
| var flagvar int | |
| func init() { | |
| flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname") | |
| } | |
| Or you can create custom flags that satisfy the Value interface (with | |
| pointer receivers) and couple them to flag parsing by | |
| flag.Var(&flagVal, "name", "help message for flagname") | |
| For such flags, the default value is just the initial value of the variable. | |
| After all flags are defined, call | |
| flag.Parse() | |
| to parse the command line into the defined flags. | |
| Flags may then be used directly. If you're using the flags themselves, | |
| they are all pointers; if you bind to variables, they're values. | |
| fmt.Println("ip has value ", *ip) | |
| fmt.Println("flagvar has value ", flagvar) | |
| After parsing, the arguments after the flag are available as the | |
| slice flag.Args() or individually as flag.Arg(i). | |
| The arguments are indexed from 0 through flag.NArg()-1. | |
| The pflag package also defines some new functions that are not in flag, | |
| that give one-letter shorthands for flags. You can use these by appending | |
| 'P' to the name of any function that defines a flag. | |
| var ip = flag.IntP("flagname", "f", 1234, "help message") | |
| var flagvar bool | |
| func init() { | |
| flag.BoolVarP(&flagvar, "boolname", "b", true, "help message") | |
| } | |
| flag.VarP(&flagval, "varname", "v", "help message") | |
| Shorthand letters can be used with single dashes on the command line. | |
| Boolean shorthand flags can be combined with other shorthand flags. | |
| Command line flag syntax: | |
| --flag // boolean flags only | |
| --flag=x | |
| Unlike the flag package, a single dash before an option means something | |
| different than a double dash. Single dashes signify a series of shorthand | |
| letters for flags. All but the last shorthand letter must be boolean flags. | |
| // boolean flags | |
| -f | |
| -abc | |
| // non-boolean flags | |
| -n 1234 | |
| -Ifile | |
| // mixed | |
| -abcs "hello" | |
| -abcn1234 | |
| Flag parsing stops after the terminator "--". Unlike the flag package, | |
| flags can be interspersed with arguments anywhere on the command line | |
| before this terminator. | |
| Integer flags accept 1234, 0664, 0x1234 and may be negative. | |
| Boolean flags (in their long form) accept 1, 0, t, f, true, false, | |
| TRUE, FALSE, True, False. | |
| Duration flags accept any input valid for time.ParseDuration. | |
| The default set of command-line flags is controlled by | |
| top-level functions. The FlagSet type allows one to define | |
| independent sets of flags, such as to implement subcommands | |
| in a command-line interface. The methods of FlagSet are | |
| analogous to the top-level functions for the command-line | |
| flag set. | |
| */ | |
| package pflag | |
| import ( | |
| "bytes" | |
| "errors" | |
| goflag "flag" | |
| "fmt" | |
| "io" | |
| "os" | |
| "sort" | |
| "strings" | |
| ) | |
| // ErrHelp is the error returned if the flag -help is invoked but no such flag is defined. | |
| var ErrHelp = errors.New("pflag: help requested") | |
| // ErrorHandling defines how to handle flag parsing errors. | |
| type ErrorHandling int | |
| const ( | |
| // ContinueOnError will return an err from Parse() if an error is found | |
| ContinueOnError ErrorHandling = iota | |
| // ExitOnError will call os.Exit(2) if an error is found when parsing | |
| ExitOnError | |
| // PanicOnError will panic() if an error is found when parsing flags | |
| PanicOnError | |
| ) | |
| // ParseErrorsWhitelist defines the parsing errors that can be ignored | |
| type ParseErrorsWhitelist struct { | |
| // UnknownFlags will ignore unknown flags errors and continue parsing rest of the flags | |
| UnknownFlags bool | |
| } | |
| // NormalizedName is a flag name that has been normalized according to rules | |
| // for the FlagSet (e.g. making '-' and '_' equivalent). | |
| type NormalizedName string | |
| // A FlagSet represents a set of defined flags. | |
| type FlagSet struct { | |
| // Usage is the function called when an error occurs while parsing flags. | |
| // The field is a function (not a method) that may be changed to point to | |
| // a custom error handler. | |
| Usage func() | |
| // SortFlags is used to indicate, if user wants to have sorted flags in | |
| // help/usage messages. | |
| SortFlags bool | |
| // ParseErrorsWhitelist is used to configure a whitelist of errors | |
| ParseErrorsWhitelist ParseErrorsWhitelist | |
| name string | |
| parsed bool | |
| actual map[NormalizedName]*Flag | |
| orderedActual []*Flag | |
| sortedActual []*Flag | |
| formal map[NormalizedName]*Flag | |
| orderedFormal []*Flag | |
| sortedFormal []*Flag | |
| shorthands map[byte]*Flag | |
| args []string // arguments after flags | |
| argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no -- | |
| errorHandling ErrorHandling | |
| output io.Writer // nil means stderr; use out() accessor | |
| interspersed bool // allow interspersed option/non-option args | |
| normalizeNameFunc func(f *FlagSet, name string) NormalizedName | |
| addedGoFlagSets []*goflag.FlagSet | |
| } | |
| // A Flag represents the state of a flag. | |
| type Flag struct { | |
| Name string // name as it appears on command line | |
| Shorthand string // one-letter abbreviated flag | |
| Usage string // help message | |
| Value Value // value as set | |
| DefValue string // default value (as text); for usage message | |
| Changed bool // If the user set the value (or if left to default) | |
| NoOptDefVal string // default value (as text); if the flag is on the command line without any options | |
| Deprecated string // If this flag is deprecated, this string is the new or now thing to use | |
| Hidden bool // used by cobra.Command to allow flags to be hidden from help/usage text | |
| ShorthandDeprecated string // If the shorthand of this flag is deprecated, this string is the new or now thing to use | |
| Annotations map[string][]string // used by cobra.Command bash autocomple code | |
| } | |
| // Value is the interface to the dynamic value stored in a flag. | |
| // (The default value is represented as a string.) | |
| type Value interface { | |
| String() string | |
| Set(string) error | |
| Type() string | |
| } | |
| // SliceValue is a secondary interface to all flags which hold a list | |
| // of values. This allows full control over the value of list flags, | |
| // and avoids complicated marshalling and unmarshalling to csv. | |
| type SliceValue interface { | |
| // Append adds the specified value to the end of the flag value list. | |
| Append(string) error | |
| // Replace will fully overwrite any data currently in the flag value list. | |
| Replace([]string) error | |
| // GetSlice returns the flag value list as an array of strings. | |
| GetSlice() []string | |
| } | |
| // sortFlags returns the flags as a slice in lexicographical sorted order. | |
| func sortFlags(flags map[NormalizedName]*Flag) []*Flag { | |
| list := make(sort.StringSlice, len(flags)) | |
| i := 0 | |
| for k := range flags { | |
| list[i] = string(k) | |
| i++ | |
| } | |
| list.Sort() | |
| result := make([]*Flag, len(list)) | |
| for i, name := range list { | |
| result[i] = flags[NormalizedName(name)] | |
| } | |
| return result | |
| } | |
| // SetNormalizeFunc allows you to add a function which can translate flag names. | |
| // Flags added to the FlagSet will be translated and then when anything tries to | |
| // look up the flag that will also be translated. So it would be possible to create | |
| // a flag named "getURL" and have it translated to "geturl". A user could then pass | |
| // "--getUrl" which may also be translated to "geturl" and everything will work. | |
| func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) { | |
| f.normalizeNameFunc = n | |
| f.sortedFormal = f.sortedFormal[:0] | |
| for fname, flag := range f.formal { | |
| nname := f.normalizeFlagName(flag.Name) | |
| if fname == nname { | |
| continue | |
| } | |
| flag.Name = string(nname) | |
| delete(f.formal, fname) | |
| f.formal[nname] = flag | |
| if _, set := f.actual[fname]; set { | |
| delete(f.actual, fname) | |
| f.actual[nname] = flag | |
| } | |
| } | |
| } | |
| // GetNormalizeFunc returns the previously set NormalizeFunc of a function which | |
| // does no translation, if not set previously. | |
| func (f *FlagSet) GetNormalizeFunc() func(f *FlagSet, name string) NormalizedName { | |
| if f.normalizeNameFunc != nil { | |
| return f.normalizeNameFunc | |
| } | |
| return func(f *FlagSet, name string) NormalizedName { return NormalizedName(name) } | |
| } | |
| func (f *FlagSet) normalizeFlagName(name string) NormalizedName { | |
| n := f.GetNormalizeFunc() | |
| return n(f, name) | |
| } | |
| func (f *FlagSet) out() io.Writer { | |
| if f.output == nil { | |
| return os.Stderr | |
| } | |
| return f.output | |
| } | |
| // SetOutput sets the destination for usage and error messages. | |
| // If output is nil, os.Stderr is used. | |
| func (f *FlagSet) SetOutput(output io.Writer) { | |
| f.output = output | |
| } | |
| // VisitAll visits the flags in lexicographical order or | |
| // in primordial order if f.SortFlags is false, calling fn for each. | |
| // It visits all flags, even those not set. | |
| func (f *FlagSet) VisitAll(fn func(*Flag)) { | |
| if len(f.formal) == 0 { | |
| return | |
| } | |
| var flags []*Flag | |
| if f.SortFlags { | |
| if len(f.formal) != len(f.sortedFormal) { | |
| f.sortedFormal = sortFlags(f.formal) | |
| } | |
| flags = f.sortedFormal | |
| } else { | |
| flags = f.orderedFormal | |
| } | |
| for _, flag := range flags { | |
| fn(flag) | |
| } | |
| } | |
| // HasFlags returns a bool to indicate if the FlagSet has any flags defined. | |
| func (f *FlagSet) HasFlags() bool { | |
| return len(f.formal) > 0 | |
| } | |
| // HasAvailableFlags returns a bool to indicate if the FlagSet has any flags | |
| // that are not hidden. | |
| func (f *FlagSet) HasAvailableFlags() bool { | |
| for _, flag := range f.formal { | |
| if !flag.Hidden { | |
| return true | |
| } | |
| } | |
| return false | |
| } | |
| // VisitAll visits the command-line flags in lexicographical order or | |
| // in primordial order if f.SortFlags is false, calling fn for each. | |
| // It visits all flags, even those not set. | |
| func VisitAll(fn func(*Flag)) { | |
| CommandLine.VisitAll(fn) | |
| } | |
| // Visit visits the flags in lexicographical order or | |
| // in primordial order if f.SortFlags is false, calling fn for each. | |
| // It visits only those flags that have been set. | |
| func (f *FlagSet) Visit(fn func(*Flag)) { | |
| if len(f.actual) == 0 { | |
| return | |
| } | |
| var flags []*Flag | |
| if f.SortFlags { | |
| if len(f.actual) != len(f.sortedActual) { | |
| f.sortedActual = sortFlags(f.actual) | |
| } | |
| flags = f.sortedActual | |
| } else { | |
| flags = f.orderedActual | |
| } | |
| for _, flag := range flags { | |
| fn(flag) | |
| } | |
| } | |
| // Visit visits the command-line flags in lexicographical order or | |
| // in primordial order if f.SortFlags is false, calling fn for each. | |
| // It visits only those flags that have been set. | |
| func Visit(fn func(*Flag)) { | |
| CommandLine.Visit(fn) | |
| } | |
| // Lookup returns the Flag structure of the named flag, returning nil if none exists. | |
| func (f *FlagSet) Lookup(name string) *Flag { | |
| return f.lookup(f.normalizeFlagName(name)) | |
| } | |
| // ShorthandLookup returns the Flag structure of the short handed flag, | |
| // returning nil if none exists. | |
| // It panics, if len(name) > 1. | |
| func (f *FlagSet) ShorthandLookup(name string) *Flag { | |
| if name == "" { | |
| return nil | |
| } | |
| if len(name) > 1 { | |
| msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name) | |
| fmt.Fprintf(f.out(), msg) | |
| panic(msg) | |
| } | |
| c := name[0] | |
| return f.shorthands[c] | |
| } | |
| // lookup returns the Flag structure of the named flag, returning nil if none exists. | |
| func (f *FlagSet) lookup(name NormalizedName) *Flag { | |
| return f.formal[name] | |
| } | |
| // func to return a given type for a given flag name | |
| func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval string) (interface{}, error)) (interface{}, error) { | |
| flag := f.Lookup(name) | |
| if flag == nil { | |
| err := fmt.Errorf("flag accessed but not defined: %s", name) | |
| return nil, err | |
| } | |
| if flag.Value.Type() != ftype { | |
| err := fmt.Errorf("trying to get %s value of flag of type %s", ftype, flag.Value.Type()) | |
| return nil, err | |
| } | |
| sval := flag.Value.String() | |
| result, err := convFunc(sval) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return result, nil | |
| } | |
| // ArgsLenAtDash will return the length of f.Args at the moment when a -- was | |
| // found during arg parsing. This allows your program to know which args were | |
| // before the -- and which came after. | |
| func (f *FlagSet) ArgsLenAtDash() int { | |
| return f.argsLenAtDash | |
| } | |
| // MarkDeprecated indicated that a flag is deprecated in your program. It will | |
| // continue to function but will not show up in help or usage messages. Using | |
| // this flag will also print the given usageMessage. | |
| func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error { | |
| flag := f.Lookup(name) | |
| if flag == nil { | |
| return fmt.Errorf("flag %q does not exist", name) | |
| } | |
| if usageMessage == "" { | |
| return fmt.Errorf("deprecated message for flag %q must be set", name) | |
| } | |
| flag.Deprecated = usageMessage | |
| flag.Hidden = true | |
| return nil | |
| } | |
| // MarkShorthandDeprecated will mark the shorthand of a flag deprecated in your | |
| // program. It will continue to function but will not show up in help or usage | |
| // messages. Using this flag will also print the given usageMessage. | |
| func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) error { | |
| flag := f.Lookup(name) | |
| if flag == nil { | |
| return fmt.Errorf("flag %q does not exist", name) | |
| } | |
| if usageMessage == "" { | |
| return fmt.Errorf("deprecated message for flag %q must be set", name) | |
| } | |
| flag.ShorthandDeprecated = usageMessage | |
| return nil | |
| } | |
| // MarkHidden sets a flag to 'hidden' in your program. It will continue to | |
| // function but will not show up in help or usage messages. | |
| func (f *FlagSet) MarkHidden(name string) error { | |
| flag := f.Lookup(name) | |
| if flag == nil { | |
| return fmt.Errorf("flag %q does not exist", name) | |
| } | |
| flag.Hidden = true | |
| return nil | |
| } | |
| // Lookup returns the Flag structure of the named command-line flag, | |
| // returning nil if none exists. | |
| func Lookup(name string) *Flag { | |
| return CommandLine.Lookup(name) | |
| } | |
| // ShorthandLookup returns the Flag structure of the short handed flag, | |
| // returning nil if none exists. | |
| func ShorthandLookup(name string) *Flag { | |
| return CommandLine.ShorthandLookup(name) | |
| } | |
| // Set sets the value of the named flag. | |
| func (f *FlagSet) Set(name, value string) error { | |
| normalName := f.normalizeFlagName(name) | |
| flag, ok := f.formal[normalName] | |
| if !ok { | |
| return fmt.Errorf("no such flag -%v", name) | |
| } | |
| err := flag.Value.Set(value) | |
| if err != nil { | |
| var flagName string | |
| if flag.Shorthand != "" && flag.ShorthandDeprecated == "" { | |
| flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name) | |
| } else { | |
| flagName = fmt.Sprintf("--%s", flag.Name) | |
| } | |
| return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err) | |
| } | |
| if !flag.Changed { | |
| if f.actual == nil { | |
| f.actual = make(map[NormalizedName]*Flag) | |
| } | |
| f.actual[normalName] = flag | |
| f.orderedActual = append(f.orderedActual, flag) | |
| flag.Changed = true | |
| } | |
| if flag.Deprecated != "" { | |
| fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) | |
| } | |
| return nil | |
| } | |
| // SetAnnotation allows one to set arbitrary annotations on a flag in the FlagSet. | |
| // This is sometimes used by spf13/cobra programs which want to generate additional | |
| // bash completion information. | |
| func (f *FlagSet) SetAnnotation(name, key string, values []string) error { | |
| normalName := f.normalizeFlagName(name) | |
| flag, ok := f.formal[normalName] | |
| if !ok { | |
| return fmt.Errorf("no such flag -%v", name) | |
| } | |
| if flag.Annotations == nil { | |
| flag.Annotations = map[string][]string{} | |
| } | |
| flag.Annotations[key] = values | |
| return nil | |
| } | |
| // Changed returns true if the flag was explicitly set during Parse() and false | |
| // otherwise | |
| func (f *FlagSet) Changed(name string) bool { | |
| flag := f.Lookup(name) | |
| // If a flag doesn't exist, it wasn't changed.... | |
| if flag == nil { | |
| return false | |
| } | |
| return flag.Changed | |
| } | |
| // Set sets the value of the named command-line flag. | |
| func Set(name, value string) error { | |
| return CommandLine.Set(name, value) | |
| } | |
| // PrintDefaults prints, to standard error unless configured | |
| // otherwise, the default values of all defined flags in the set. | |
| func (f *FlagSet) PrintDefaults() { | |
| usages := f.FlagUsages() | |
| fmt.Fprint(f.out(), usages) | |
| } | |
| // defaultIsZeroValue returns true if the default value for this flag represents | |
| // a zero value. | |
| func (f *Flag) defaultIsZeroValue() bool { | |
| switch f.Value.(type) { | |
| case boolFlag: | |
| return f.DefValue == "false" | |
| case *durationValue: | |
| // Beginning in Go 1.7, duration zero values are "0s" | |
| return f.DefValue == "0" || f.DefValue == "0s" | |
| case *intValue, *int8Value, *int32Value, *int64Value, *uintValue, *uint8Value, *uint16Value, *uint32Value, *uint64Value, *countValue, *float32Value, *float64Value: | |
| return f.DefValue == "0" | |
| case *stringValue: | |
| return f.DefValue == "" | |
| case *ipValue, *ipMaskValue, *ipNetValue: | |
| return f.DefValue == "<nil>" | |
| case *intSliceValue, *stringSliceValue, *stringArrayValue: | |
| return f.DefValue == "[]" | |
| default: | |
| switch f.Value.String() { | |
| case "false": | |
| return true | |
| case "<nil>": | |
| return true | |
| case "": | |
| return true | |
| case "0": | |
| return true | |
| } | |
| return false | |
| } | |
| } | |
| // UnquoteUsage extracts a back-quoted name from the usage | |
| // string for a flag and returns it and the un-quoted usage. | |
| // Given "a `name` to show" it returns ("name", "a name to show"). | |
| // If there are no back quotes, the name is an educated guess of the | |
| // type of the flag's value, or the empty string if the flag is boolean. | |
| func UnquoteUsage(flag *Flag) (name string, usage string) { | |
| // Look for a back-quoted name, but avoid the strings package. | |
| usage = flag.Usage | |
| for i := 0; i < len(usage); i++ { | |
| if usage[i] == '`' { | |
| for j := i + 1; j < len(usage); j++ { | |
| if usage[j] == '`' { | |
| name = usage[i+1 : j] | |
| usage = usage[:i] + name + usage[j+1:] | |
| return name, usage | |
| } | |
| } | |
| break // Only one back quote; use type name. | |
| } | |
| } | |
| name = flag.Value.Type() | |
| switch name { | |
| case "bool": | |
| name = "" | |
| case "float64": | |
| name = "float" | |
| case "int64": | |
| name = "int" | |
| case "uint64": | |
| name = "uint" | |
| case "stringSlice": | |
| name = "strings" | |
| case "intSlice": | |
| name = "ints" | |
| case "uintSlice": | |
| name = "uints" | |
| case "boolSlice": | |
| name = "bools" | |
| } | |
| return | |
| } | |
| // Splits the string `s` on whitespace into an initial substring up to | |
| // `i` runes in length and the remainder. Will go `slop` over `i` if | |
| // that encompasses the entire string (which allows the caller to | |
| // avoid short orphan words on the final line). | |
| func wrapN(i, slop int, s string) (string, string) { | |
| if i+slop > len(s) { | |
| return s, "" | |
| } | |
| w := strings.LastIndexAny(s[:i], " \t\n") | |
| if w <= 0 { | |
| return s, "" | |
| } | |
| nlPos := strings.LastIndex(s[:i], "\n") | |
| if nlPos > 0 && nlPos < w { | |
| return s[:nlPos], s[nlPos+1:] | |
| } | |
| return s[:w], s[w+1:] | |
| } | |
| // Wraps the string `s` to a maximum width `w` with leading indent | |
| // `i`. The first line is not indented (this is assumed to be done by | |
| // caller). Pass `w` == 0 to do no wrapping | |
| func wrap(i, w int, s string) string { | |
| if w == 0 { | |
| return strings.Replace(s, "\n", "\n"+strings.Repeat(" ", i), -1) | |
| } | |
| // space between indent i and end of line width w into which | |
| // we should wrap the text. | |
| wrap := w - i | |
| var r, l string | |
| // Not enough space for sensible wrapping. Wrap as a block on | |
| // the next line instead. | |
| if wrap < 24 { | |
| i = 16 | |
| wrap = w - i | |
| r += "\n" + strings.Repeat(" ", i) | |
| } | |
| // If still not enough space then don't even try to wrap. | |
| if wrap < 24 { | |
| return strings.Replace(s, "\n", r, -1) | |
| } | |
| // Try to avoid short orphan words on the final line, by | |
| // allowing wrapN to go a bit over if that would fit in the | |
| // remainder of the line. | |
| slop := 5 | |
| wrap = wrap - slop | |
| // Handle first line, which is indented by the caller (or the | |
| // special case above) | |
| l, s = wrapN(wrap, slop, s) | |
| r = r + strings.Replace(l, "\n", "\n"+strings.Repeat(" ", i), -1) | |
| // Now wrap the rest | |
| for s != "" { | |
| var t string | |
| t, s = wrapN(wrap, slop, s) | |
| r = r + "\n" + strings.Repeat(" ", i) + strings.Replace(t, "\n", "\n"+strings.Repeat(" ", i), -1) | |
| } | |
| return r | |
| } | |
| // FlagUsagesWrapped returns a string containing the usage information | |
| // for all flags in the FlagSet. Wrapped to `cols` columns (0 for no | |
| // wrapping) | |
| func (f *FlagSet) FlagUsagesWrapped(cols int) string { | |
| buf := new(bytes.Buffer) | |
| lines := make([]string, 0, len(f.formal)) | |
| maxlen := 0 | |
| f.VisitAll(func(flag *Flag) { | |
| if flag.Hidden { | |
| return | |
| } | |
| line := "" | |
| if flag.Shorthand != "" && flag.ShorthandDeprecated == "" { | |
| line = fmt.Sprintf(" -%s, --%s", flag.Shorthand, flag.Name) | |
| } else { | |
| line = fmt.Sprintf(" --%s", flag.Name) | |
| } | |
| varname, usage := UnquoteUsage(flag) | |
| if varname != "" { | |
| line += " " + varname | |
| } | |
| if flag.NoOptDefVal != "" { | |
| switch flag.Value.Type() { | |
| case "string": | |
| line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal) | |
| case "bool": | |
| if flag.NoOptDefVal != "true" { | |
| line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) | |
| } | |
| case "count": | |
| if flag.NoOptDefVal != "+1" { | |
| line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) | |
| } | |
| default: | |
| line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) | |
| } | |
| } | |
| // This special character will be replaced with spacing once the | |
| // correct alignment is calculated | |
| line += "\x00" | |
| if len(line) > maxlen { | |
| maxlen = len(line) | |
| } | |
| line += usage | |
| if !flag.defaultIsZeroValue() { | |
| if flag.Value.Type() == "string" { | |
| line += fmt.Sprintf(" (default %q)", flag.DefValue) | |
| } else { | |
| line += fmt.Sprintf(" (default %s)", flag.DefValue) | |
| } | |
| } | |
| if len(flag.Deprecated) != 0 { | |
| line += fmt.Sprintf(" (DEPRECATED: %s)", flag.Deprecated) | |
| } | |
| lines = append(lines, line) | |
| }) | |
| for _, line := range lines { | |
| sidx := strings.Index(line, "\x00") | |
| spacing := strings.Repeat(" ", maxlen-sidx) | |
| // maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx | |
| fmt.Fprintln(buf, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:])) | |
| } | |
| return buf.String() | |
| } | |
| // FlagUsages returns a string containing the usage information for all flags in | |
| // the FlagSet | |
| func (f *FlagSet) FlagUsages() string { | |
| return f.FlagUsagesWrapped(0) | |
| } | |
| // PrintDefaults prints to standard error the default values of all defined command-line flags. | |
| func PrintDefaults() { | |
| CommandLine.PrintDefaults() | |
| } | |
| // defaultUsage is the default function to print a usage message. | |
| func defaultUsage(f *FlagSet) { | |
| fmt.Fprintf(f.out(), "Usage of %s:\n", f.name) | |
| f.PrintDefaults() | |
| } | |
| // NOTE: Usage is not just defaultUsage(CommandLine) | |
| // because it serves (via godoc flag Usage) as the example | |
| // for how to write your own usage function. | |
| // Usage prints to standard error a usage message documenting all defined command-line flags. | |
| // The function is a variable that may be changed to point to a custom function. | |
| // By default it prints a simple header and calls PrintDefaults; for details about the | |
| // format of the output and how to control it, see the documentation for PrintDefaults. | |
| var Usage = func() { | |
| fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) | |
| PrintDefaults() | |
| } | |
| // NFlag returns the number of flags that have been set. | |
| func (f *FlagSet) NFlag() int { return len(f.actual) } | |
| // NFlag returns the number of command-line flags that have been set. | |
| func NFlag() int { return len(CommandLine.actual) } | |
| // Arg returns the i'th argument. Arg(0) is the first remaining argument | |
| // after flags have been processed. | |
| func (f *FlagSet) Arg(i int) string { | |
| if i < 0 || i >= len(f.args) { | |
| return "" | |
| } | |
| return f.args[i] | |
| } | |
| // Arg returns the i'th command-line argument. Arg(0) is the first remaining argument | |
| // after flags have been processed. | |
| func Arg(i int) string { | |
| return CommandLine.Arg(i) | |
| } | |
| // NArg is the number of arguments remaining after flags have been processed. | |
| func (f *FlagSet) NArg() int { return len(f.args) } | |
| // NArg is the number of arguments remaining after flags have been processed. | |
| func NArg() int { return len(CommandLine.args) } | |
| // Args returns the non-flag arguments. | |
| func (f *FlagSet) Args() []string { return f.args } | |
| // Args returns the non-flag command-line arguments. | |
| func Args() []string { return CommandLine.args } | |
| // Var defines a flag with the specified name and usage string. The type and | |
| // value of the flag are represented by the first argument, of type Value, which | |
| // typically holds a user-defined implementation of Value. For instance, the | |
| // caller could create a flag that turns a comma-separated string into a slice | |
| // of strings by giving the slice the methods of Value; in particular, Set would | |
| // decompose the comma-separated string into the slice. | |
| func (f *FlagSet) Var(value Value, name string, usage string) { | |
| f.VarP(value, name, "", usage) | |
| } | |
| // VarPF is like VarP, but returns the flag created | |
| func (f *FlagSet) VarPF(value Value, name, shorthand, usage string) *Flag { | |
| // Remember the default value as a string; it won't change. | |
| flag := &Flag{ | |
| Name: name, | |
| Shorthand: shorthand, | |
| Usage: usage, | |
| Value: value, | |
| DefValue: value.String(), | |
| } | |
| f.AddFlag(flag) | |
| return flag | |
| } | |
| // VarP is like Var, but accepts a shorthand letter that can be used after a single dash. | |
| func (f *FlagSet) VarP(value Value, name, shorthand, usage string) { | |
| f.VarPF(value, name, shorthand, usage) | |
| } | |
| // AddFlag will add the flag to the FlagSet | |
| func (f *FlagSet) AddFlag(flag *Flag) { | |
| normalizedFlagName := f.normalizeFlagName(flag.Name) | |
| _, alreadyThere := f.formal[normalizedFlagName] | |
| if alreadyThere { | |
| msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name) | |
| fmt.Fprintln(f.out(), msg) | |
| panic(msg) // Happens only if flags are declared with identical names | |
| } | |
| if f.formal == nil { | |
| f.formal = make(map[NormalizedName]*Flag) | |
| } | |
| flag.Name = string(normalizedFlagName) | |
| f.formal[normalizedFlagName] = flag | |
| f.orderedFormal = append(f.orderedFormal, flag) | |
| if flag.Shorthand == "" { | |
| return | |
| } | |
| if len(flag.Shorthand) > 1 { | |
| msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand) | |
| fmt.Fprintf(f.out(), msg) | |
| panic(msg) | |
| } | |
| if f.shorthands == nil { | |
| f.shorthands = make(map[byte]*Flag) | |
| } | |
| c := flag.Shorthand[0] | |
| used, alreadyThere := f.shorthands[c] | |
| if alreadyThere { | |
| msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name) | |
| fmt.Fprintf(f.out(), msg) | |
| panic(msg) | |
| } | |
| f.shorthands[c] = flag | |
| } | |
| // AddFlagSet adds one FlagSet to another. If a flag is already present in f | |
| // the flag from newSet will be ignored. | |
| func (f *FlagSet) AddFlagSet(newSet *FlagSet) { | |
| if newSet == nil { | |
| return | |
| } | |
| newSet.VisitAll(func(flag *Flag) { | |
| if f.Lookup(flag.Name) == nil { | |
| f.AddFlag(flag) | |
| } | |
| }) | |
| } | |
| // Var defines a flag with the specified name and usage string. The type and | |
| // value of the flag are represented by the first argument, of type Value, which | |
| // typically holds a user-defined implementation of Value. For instance, the | |
| // caller could create a flag that turns a comma-separated string into a slice | |
| // of strings by giving the slice the methods of Value; in particular, Set would | |
| // decompose the comma-separated string into the slice. | |
| func Var(value Value, name string, usage string) { | |
| CommandLine.VarP(value, name, "", usage) | |
| } | |
| // VarP is like Var, but accepts a shorthand letter that can be used after a single dash. | |
| func VarP(value Value, name, shorthand, usage string) { | |
| CommandLine.VarP(value, name, shorthand, usage) | |
| } | |
| // failf prints to standard error a formatted error and usage message and | |
| // returns the error. | |
| func (f *FlagSet) failf(format string, a ...interface{}) error { | |
| err := fmt.Errorf(format, a...) | |
| if f.errorHandling != ContinueOnError { | |
| fmt.Fprintln(f.out(), err) | |
| f.usage() | |
| } | |
| return err | |
| } | |
| // usage calls the Usage method for the flag set, or the usage function if | |
| // the flag set is CommandLine. | |
| func (f *FlagSet) usage() { | |
| if f == CommandLine { | |
| Usage() | |
| } else if f.Usage == nil { | |
| defaultUsage(f) | |
| } else { | |
| f.Usage() | |
| } | |
| } | |
| //--unknown (args will be empty) | |
| //--unknown --next-flag ... (args will be --next-flag ...) | |
| //--unknown arg ... (args will be arg ...) | |
| func stripUnknownFlagValue(args []string) []string { | |
| if len(args) == 0 { | |
| //--unknown | |
| return args | |
| } | |
| first := args[0] | |
| if len(first) > 0 && first[0] == '-' { | |
| //--unknown --next-flag ... | |
| return args | |
| } | |
| //--unknown arg ... (args will be arg ...) | |
| if len(args) > 1 { | |
| return args[1:] | |
| } | |
| return nil | |
| } | |
| func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) { | |
| a = args | |
| name := s[2:] | |
| if len(name) == 0 || name[0] == '-' || name[0] == '=' { | |
| err = f.failf("bad flag syntax: %s", s) | |
| return | |
| } | |
| split := strings.SplitN(name, "=", 2) | |
| name = split[0] | |
| flag, exists := f.formal[f.normalizeFlagName(name)] | |
| if !exists { | |
| switch { | |
| case name == "help": | |
| f.usage() | |
| return a, ErrHelp | |
| case f.ParseErrorsWhitelist.UnknownFlags: | |
| // --unknown=unknownval arg ... | |
| // we do not want to lose arg in this case | |
| if len(split) >= 2 { | |
| return a, nil | |
| } | |
| return stripUnknownFlagValue(a), nil | |
| default: | |
| err = f.failf("unknown flag: --%s", name) | |
| return | |
| } | |
| } | |
| var value string | |
| if len(split) == 2 { | |
| // '--flag=arg' | |
| value = split[1] | |
| } else if flag.NoOptDefVal != "" { | |
| // '--flag' (arg was optional) | |
| value = flag.NoOptDefVal | |
| } else if len(a) > 0 { | |
| // '--flag arg' | |
| value = a[0] | |
| a = a[1:] | |
| } else { | |
| // '--flag' (arg was required) | |
| err = f.failf("flag needs an argument: %s", s) | |
| return | |
| } | |
| err = fn(flag, value) | |
| if err != nil { | |
| f.failf(err.Error()) | |
| } | |
| return | |
| } | |
| func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) { | |
| outArgs = args | |
| if strings.HasPrefix(shorthands, "test.") { | |
| return | |
| } | |
| outShorts = shorthands[1:] | |
| c := shorthands[0] | |
| flag, exists := f.shorthands[c] | |
| if !exists { | |
| switch { | |
| case c == 'h': | |
| f.usage() | |
| err = ErrHelp | |
| return | |
| case f.ParseErrorsWhitelist.UnknownFlags: | |
| // '-f=arg arg ...' | |
| // we do not want to lose arg in this case | |
| if len(shorthands) > 2 && shorthands[1] == '=' { | |
| outShorts = "" | |
| return | |
| } | |
| outArgs = stripUnknownFlagValue(outArgs) | |
| return | |
| default: | |
| err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands) | |
| return | |
| } | |
| } | |
| var value string | |
| if len(shorthands) > 2 && shorthands[1] == '=' { | |
| // '-f=arg' | |
| value = shorthands[2:] | |
| outShorts = "" | |
| } else if flag.NoOptDefVal != "" { | |
| // '-f' (arg was optional) | |
| value = flag.NoOptDefVal | |
| } else if len(shorthands) > 1 { | |
| // '-farg' | |
| value = shorthands[1:] | |
| outShorts = "" | |
| } else if len(args) > 0 { | |
| // '-f arg' | |
| value = args[0] | |
| outArgs = args[1:] | |
| } else { | |
| // '-f' (arg was required) | |
| err = f.failf("flag needs an argument: %q in -%s", c, shorthands) | |
| return | |
| } | |
| if flag.ShorthandDeprecated != "" { | |
| fmt.Fprintf(f.out(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated) | |
| } | |
| err = fn(flag, value) | |
| if err != nil { | |
| f.failf(err.Error()) | |
| } | |
| return | |
| } | |
| func (f *FlagSet) parseShortArg(s string, args []string, fn parseFunc) (a []string, err error) { | |
| a = args | |
| shorthands := s[1:] | |
| // "shorthands" can be a series of shorthand letters of flags (e.g. "-vvv"). | |
| for len(shorthands) > 0 { | |
| shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn) | |
| if err != nil { | |
| return | |
| } | |
| } | |
| return | |
| } | |
| func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) { | |
| for len(args) > 0 { | |
| s := args[0] | |
| args = args[1:] | |
| if len(s) == 0 || s[0] != '-' || len(s) == 1 { | |
| if !f.interspersed { | |
| f.args = append(f.args, s) | |
| f.args = append(f.args, args...) | |
| return nil | |
| } | |
| f.args = append(f.args, s) | |
| continue | |
| } | |
| if s[1] == '-' { | |
| if len(s) == 2 { // "--" terminates the flags | |
| f.argsLenAtDash = len(f.args) | |
| f.args = append(f.args, args...) | |
| break | |
| } | |
| args, err = f.parseLongArg(s, args, fn) | |
| } else { | |
| args, err = f.parseShortArg(s, args, fn) | |
| } | |
| if err != nil { | |
| return | |
| } | |
| } | |
| return | |
| } | |
| // Parse parses flag definitions from the argument list, which should not | |
| // include the command name. Must be called after all flags in the FlagSet | |
| // are defined and before flags are accessed by the program. | |
| // The return value will be ErrHelp if -help was set but not defined. | |
| func (f *FlagSet) Parse(arguments []string) error { | |
| if f.addedGoFlagSets != nil { | |
| for _, goFlagSet := range f.addedGoFlagSets { | |
| goFlagSet.Parse(nil) | |
| } | |
| } | |
| f.parsed = true | |
| if len(arguments) < 0 { | |
| return nil | |
| } | |
| f.args = make([]string, 0, len(arguments)) | |
| set := func(flag *Flag, value string) error { | |
| return f.Set(flag.Name, value) | |
| } | |
| err := f.parseArgs(arguments, set) | |
| if err != nil { | |
| switch f.errorHandling { | |
| case ContinueOnError: | |
| return err | |
| case ExitOnError: | |
| fmt.Println(err) | |
| os.Exit(2) | |
| case PanicOnError: | |
| panic(err) | |
| } | |
| } | |
| return nil | |
| } | |
| type parseFunc func(flag *Flag, value string) error | |
| // ParseAll parses flag definitions from the argument list, which should not | |
| // include the command name. The arguments for fn are flag and value. Must be | |
| // called after all flags in the FlagSet are defined and before flags are | |
| // accessed by the program. The return value will be ErrHelp if -help was set | |
| // but not defined. | |
| func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string) error) error { | |
| f.parsed = true | |
| f.args = make([]string, 0, len(arguments)) | |
| err := f.parseArgs(arguments, fn) | |
| if err != nil { | |
| switch f.errorHandling { | |
| case ContinueOnError: | |
| return err | |
| case ExitOnError: | |
| os.Exit(2) | |
| case PanicOnError: | |
| panic(err) | |
| } | |
| } | |
| return nil | |
| } | |
| // Parsed reports whether f.Parse has been called. | |
| func (f *FlagSet) Parsed() bool { | |
| return f.parsed | |
| } | |
| // Parse parses the command-line flags from os.Args[1:]. Must be called | |
| // after all flags are defined and before flags are accessed by the program. | |
| func Parse() { | |
| // Ignore errors; CommandLine is set for ExitOnError. | |
| CommandLine.Parse(os.Args[1:]) | |
| } | |
| // ParseAll parses the command-line flags from os.Args[1:] and called fn for each. | |
| // The arguments for fn are flag and value. Must be called after all flags are | |
| // defined and before flags are accessed by the program. | |
| func ParseAll(fn func(flag *Flag, value string) error) { | |
| // Ignore errors; CommandLine is set for ExitOnError. | |
| CommandLine.ParseAll(os.Args[1:], fn) | |
| } | |
| // SetInterspersed sets whether to support interspersed option/non-option arguments. | |
| func SetInterspersed(interspersed bool) { | |
| CommandLine.SetInterspersed(interspersed) | |
| } | |
| // Parsed returns true if the command-line flags have been parsed. | |
| func Parsed() bool { | |
| return CommandLine.Parsed() | |
| } | |
| // CommandLine is the default set of command-line flags, parsed from os.Args. | |
| var CommandLine = NewFlagSet(os.Args[0], ExitOnError) | |
| // NewFlagSet returns a new, empty flag set with the specified name, | |
| // error handling property and SortFlags set to true. | |
| func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet { | |
| f := &FlagSet{ | |
| name: name, | |
| errorHandling: errorHandling, | |
| argsLenAtDash: -1, | |
| interspersed: true, | |
| SortFlags: true, | |
| } | |
| return f | |
| } | |
| // SetInterspersed sets whether to support interspersed option/non-option arguments. | |
| func (f *FlagSet) SetInterspersed(interspersed bool) { | |
| f.interspersed = interspersed | |
| } | |
| // Init sets the name and error handling property for a flag set. | |
| // By default, the zero FlagSet uses an empty name and the | |
| // ContinueOnError error handling policy. | |
| func (f *FlagSet) Init(name string, errorHandling ErrorHandling) { | |
| f.name = name | |
| f.errorHandling = errorHandling | |
| f.argsLenAtDash = -1 | |
| } |