1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 5 /*
6 Package pflag is a drop-in replacement for Go's flag package, implementing
7 POSIX/GNU-style --flags.
8 9 pflag is compatible with the GNU extensions to the POSIX recommendations
10 for command-line options. See
11 http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
12 13 Usage:
14 15 pflag is a drop-in replacement of Go's native flag package. If you import
16 pflag under the name "flag" then all code should continue to function
17 with no changes.
18 19 import flag "github.com/spf13/pflag"
20 21 There is one exception to this: if you directly instantiate the Flag struct
22 there is one more field "Shorthand" that you will need to set.
23 Most code never instantiates this struct directly, and instead uses
24 functions such as String(), BoolVar(), and Var(), and is therefore
25 unaffected.
26 27 Define flags using flag.String(), Bool(), Int(), etc.
28 29 This declares an integer flag, -flagname, stored in the pointer ip, with type *int.
30 31 var ip = flag.Int("flagname", 1234, "help message for flagname")
32 33 If you like, you can bind the flag to a variable using the Var() functions.
34 35 var flagvar int
36 func init() {
37 flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
38 }
39 40 Or you can create custom flags that satisfy the Value interface (with
41 pointer receivers) and couple them to flag parsing by
42 43 flag.Var(&flagVal, "name", "help message for flagname")
44 45 For such flags, the default value is just the initial value of the variable.
46 47 After all flags are defined, call
48 49 flag.Parse()
50 51 to parse the command line into the defined flags.
52 53 Flags may then be used directly. If you're using the flags themselves,
54 they are all pointers; if you bind to variables, they're values.
55 56 fmt.Println("ip has value ", *ip)
57 fmt.Println("flagvar has value ", flagvar)
58 59 After parsing, the arguments after the flag are available as the
60 slice flag.Args() or individually as flag.Arg(i).
61 The arguments are indexed from 0 through flag.NArg()-1.
62 63 The pflag package also defines some new functions that are not in flag,
64 that give one-letter shorthands for flags. You can use these by appending
65 'P' to the name of any function that defines a flag.
66 67 var ip = flag.IntP("flagname", "f", 1234, "help message")
68 var flagvar bool
69 func init() {
70 flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
71 }
72 flag.VarP(&flagval, "varname", "v", "help message")
73 74 Shorthand letters can be used with single dashes on the command line.
75 Boolean shorthand flags can be combined with other shorthand flags.
76 77 Command line flag syntax:
78 79 --flag // boolean flags only
80 --flag=x
81 82 Unlike the flag package, a single dash before an option means something
83 different than a double dash. Single dashes signify a series of shorthand
84 letters for flags. All but the last shorthand letter must be boolean flags.
85 86 // boolean flags
87 -f
88 -abc
89 // non-boolean flags
90 -n 1234
91 -Ifile
92 // mixed
93 -abcs "hello"
94 -abcn1234
95 96 Flag parsing stops after the terminator "--". Unlike the flag package,
97 flags can be interspersed with arguments anywhere on the command line
98 before this terminator.
99 100 Integer flags accept 1234, 0664, 0x1234 and may be negative.
101 Boolean flags (in their long form) accept 1, 0, t, f, true, false,
102 TRUE, FALSE, True, False.
103 Duration flags accept any input valid for time.ParseDuration.
104 105 The default set of command-line flags is controlled by
106 top-level functions. The FlagSet type allows one to define
107 independent sets of flags, such as to implement subcommands
108 in a command-line interface. The methods of FlagSet are
109 analogous to the top-level functions for the command-line
110 flag set.
111 */
112 package pflag
113 114 import (
115 "bytes"
116 "errors"
117 goflag "flag"
118 "fmt"
119 "io"
120 "os"
121 "sort"
122 "strings"
123 )
124 125 // ErrHelp is the error returned if the flag -help is invoked but no such flag is defined.
126 var ErrHelp = errors.New("pflag: help requested")
127 128 // ErrorHandling defines how to handle flag parsing errors.
129 type ErrorHandling int
130 131 const (
132 // ContinueOnError will return an err from Parse() if an error is found
133 ContinueOnError ErrorHandling = iota
134 // ExitOnError will call os.Exit(2) if an error is found when parsing
135 ExitOnError
136 // PanicOnError will panic() if an error is found when parsing flags
137 PanicOnError
138 )
139 140 // ParseErrorsWhitelist defines the parsing errors that can be ignored
141 type ParseErrorsWhitelist struct {
142 // UnknownFlags will ignore unknown flags errors and continue parsing rest of the flags
143 UnknownFlags bool
144 }
145 146 // NormalizedName is a flag name that has been normalized according to rules
147 // for the FlagSet (e.g. making '-' and '_' equivalent).
148 type NormalizedName string
149 150 // A FlagSet represents a set of defined flags.
151 type FlagSet struct {
152 // Usage is the function called when an error occurs while parsing flags.
153 // The field is a function (not a method) that may be changed to point to
154 // a custom error handler.
155 Usage func()
156 157 // SortFlags is used to indicate, if user wants to have sorted flags in
158 // help/usage messages.
159 SortFlags bool
160 161 // ParseErrorsWhitelist is used to configure a whitelist of errors
162 ParseErrorsWhitelist ParseErrorsWhitelist
163 164 name string
165 parsed bool
166 actual map[NormalizedName]*Flag
167 orderedActual []*Flag
168 sortedActual []*Flag
169 formal map[NormalizedName]*Flag
170 orderedFormal []*Flag
171 sortedFormal []*Flag
172 shorthands map[byte]*Flag
173 args []string // arguments after flags
174 argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no --
175 errorHandling ErrorHandling
176 output io.Writer // nil means stderr; use Output() accessor
177 interspersed bool // allow interspersed option/non-option args
178 normalizeNameFunc func(f *FlagSet, name string) NormalizedName
179 180 addedGoFlagSets []*goflag.FlagSet
181 }
182 183 // A Flag represents the state of a flag.
184 type Flag struct {
185 Name string // name as it appears on command line
186 Shorthand string // one-letter abbreviated flag
187 Usage string // help message
188 Value Value // value as set
189 DefValue string // default value (as text); for usage message
190 Changed bool // If the user set the value (or if left to default)
191 NoOptDefVal string // default value (as text); if the flag is on the command line without any options
192 Deprecated string // If this flag is deprecated, this string is the new or now thing to use
193 Hidden bool // used by cobra.Command to allow flags to be hidden from help/usage text
194 ShorthandDeprecated string // If the shorthand of this flag is deprecated, this string is the new or now thing to use
195 Annotations map[string][]string // used by cobra.Command bash autocomple code
196 }
197 198 // Value is the interface to the dynamic value stored in a flag.
199 // (The default value is represented as a string.)
200 type Value interface {
201 String() string
202 Set(string) error
203 Type() string
204 }
205 206 // SliceValue is a secondary interface to all flags which hold a list
207 // of values. This allows full control over the value of list flags,
208 // and avoids complicated marshalling and unmarshalling to csv.
209 type SliceValue interface {
210 // Append adds the specified value to the end of the flag value list.
211 Append(string) error
212 // Replace will fully overwrite any data currently in the flag value list.
213 Replace([]string) error
214 // GetSlice returns the flag value list as an array of strings.
215 GetSlice() []string
216 }
217 218 // sortFlags returns the flags as a slice in lexicographical sorted order.
219 func sortFlags(flags map[NormalizedName]*Flag) []*Flag {
220 list := make(sort.StringSlice, len(flags))
221 i := 0
222 for k := range flags {
223 list[i] = string(k)
224 i++
225 }
226 list.Sort()
227 result := make([]*Flag, len(list))
228 for i, name := range list {
229 result[i] = flags[NormalizedName(name)]
230 }
231 return result
232 }
233 234 // SetNormalizeFunc allows you to add a function which can translate flag names.
235 // Flags added to the FlagSet will be translated and then when anything tries to
236 // look up the flag that will also be translated. So it would be possible to create
237 // a flag named "getURL" and have it translated to "geturl". A user could then pass
238 // "--getUrl" which may also be translated to "geturl" and everything will work.
239 func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) {
240 f.normalizeNameFunc = n
241 f.sortedFormal = f.sortedFormal[:0]
242 for fname, flag := range f.formal {
243 nname := f.normalizeFlagName(flag.Name)
244 if fname == nname {
245 continue
246 }
247 flag.Name = string(nname)
248 delete(f.formal, fname)
249 f.formal[nname] = flag
250 if _, set := f.actual[fname]; set {
251 delete(f.actual, fname)
252 f.actual[nname] = flag
253 }
254 }
255 }
256 257 // GetNormalizeFunc returns the previously set NormalizeFunc of a function which
258 // does no translation, if not set previously.
259 func (f *FlagSet) GetNormalizeFunc() func(f *FlagSet, name string) NormalizedName {
260 if f.normalizeNameFunc != nil {
261 return f.normalizeNameFunc
262 }
263 return func(f *FlagSet, name string) NormalizedName { return NormalizedName(name) }
264 }
265 266 func (f *FlagSet) normalizeFlagName(name string) NormalizedName {
267 n := f.GetNormalizeFunc()
268 return n(f, name)
269 }
270 271 // Output returns the destination for usage and error messages. os.Stderr is returned if
272 // output was not set or was set to nil.
273 func (f *FlagSet) Output() io.Writer {
274 if f.output == nil {
275 return os.Stderr
276 }
277 return f.output
278 }
279 280 // Name returns the name of the flag set.
281 func (f *FlagSet) Name() string {
282 return f.name
283 }
284 285 // SetOutput sets the destination for usage and error messages.
286 // If output is nil, os.Stderr is used.
287 func (f *FlagSet) SetOutput(output io.Writer) {
288 f.output = output
289 }
290 291 // VisitAll visits the flags in lexicographical order or
292 // in primordial order if f.SortFlags is false, calling fn for each.
293 // It visits all flags, even those not set.
294 func (f *FlagSet) VisitAll(fn func(*Flag)) {
295 if len(f.formal) == 0 {
296 return
297 }
298 299 var flags []*Flag
300 if f.SortFlags {
301 if len(f.formal) != len(f.sortedFormal) {
302 f.sortedFormal = sortFlags(f.formal)
303 }
304 flags = f.sortedFormal
305 } else {
306 flags = f.orderedFormal
307 }
308 309 for _, flag := range flags {
310 fn(flag)
311 }
312 }
313 314 // HasFlags returns a bool to indicate if the FlagSet has any flags defined.
315 func (f *FlagSet) HasFlags() bool {
316 return len(f.formal) > 0
317 }
318 319 // HasAvailableFlags returns a bool to indicate if the FlagSet has any flags
320 // that are not hidden.
321 func (f *FlagSet) HasAvailableFlags() bool {
322 for _, flag := range f.formal {
323 if !flag.Hidden {
324 return true
325 }
326 }
327 return false
328 }
329 330 // VisitAll visits the command-line flags in lexicographical order or
331 // in primordial order if f.SortFlags is false, calling fn for each.
332 // It visits all flags, even those not set.
333 func VisitAll(fn func(*Flag)) {
334 CommandLine.VisitAll(fn)
335 }
336 337 // Visit visits the flags in lexicographical order or
338 // in primordial order if f.SortFlags is false, calling fn for each.
339 // It visits only those flags that have been set.
340 func (f *FlagSet) Visit(fn func(*Flag)) {
341 if len(f.actual) == 0 {
342 return
343 }
344 345 var flags []*Flag
346 if f.SortFlags {
347 if len(f.actual) != len(f.sortedActual) {
348 f.sortedActual = sortFlags(f.actual)
349 }
350 flags = f.sortedActual
351 } else {
352 flags = f.orderedActual
353 }
354 355 for _, flag := range flags {
356 fn(flag)
357 }
358 }
359 360 // Visit visits the command-line flags in lexicographical order or
361 // in primordial order if f.SortFlags is false, calling fn for each.
362 // It visits only those flags that have been set.
363 func Visit(fn func(*Flag)) {
364 CommandLine.Visit(fn)
365 }
366 367 // Lookup returns the Flag structure of the named flag, returning nil if none exists.
368 func (f *FlagSet) Lookup(name string) *Flag {
369 return f.lookup(f.normalizeFlagName(name))
370 }
371 372 // ShorthandLookup returns the Flag structure of the short handed flag,
373 // returning nil if none exists.
374 // It panics, if len(name) > 1.
375 func (f *FlagSet) ShorthandLookup(name string) *Flag {
376 if name == "" {
377 return nil
378 }
379 if len(name) > 1 {
380 msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name)
381 fmt.Fprintf(f.Output(), msg)
382 panic(msg)
383 }
384 c := name[0]
385 return f.shorthands[c]
386 }
387 388 // lookup returns the Flag structure of the named flag, returning nil if none exists.
389 func (f *FlagSet) lookup(name NormalizedName) *Flag {
390 return f.formal[name]
391 }
392 393 // func to return a given type for a given flag name
394 func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval string) (interface{}, error)) (interface{}, error) {
395 flag := f.Lookup(name)
396 if flag == nil {
397 err := &NotExistError{name: name, messageType: flagNotDefinedMessage}
398 return nil, err
399 }
400 401 if flag.Value.Type() != ftype {
402 err := fmt.Errorf("trying to get %s value of flag of type %s", ftype, flag.Value.Type())
403 return nil, err
404 }
405 406 sval := flag.Value.String()
407 result, err := convFunc(sval)
408 if err != nil {
409 return nil, err
410 }
411 return result, nil
412 }
413 414 // ArgsLenAtDash will return the length of f.Args at the moment when a -- was
415 // found during arg parsing. This allows your program to know which args were
416 // before the -- and which came after.
417 func (f *FlagSet) ArgsLenAtDash() int {
418 return f.argsLenAtDash
419 }
420 421 // MarkDeprecated indicated that a flag is deprecated in your program. It will
422 // continue to function but will not show up in help or usage messages. Using
423 // this flag will also print the given usageMessage.
424 func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
425 flag := f.Lookup(name)
426 if flag == nil {
427 return &NotExistError{name: name, messageType: flagNotExistMessage}
428 }
429 if usageMessage == "" {
430 return fmt.Errorf("deprecated message for flag %q must be set", name)
431 }
432 flag.Deprecated = usageMessage
433 flag.Hidden = true
434 return nil
435 }
436 437 // MarkShorthandDeprecated will mark the shorthand of a flag deprecated in your
438 // program. It will continue to function but will not show up in help or usage
439 // messages. Using this flag will also print the given usageMessage.
440 func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) error {
441 flag := f.Lookup(name)
442 if flag == nil {
443 return &NotExistError{name: name, messageType: flagNotExistMessage}
444 }
445 if usageMessage == "" {
446 return fmt.Errorf("deprecated message for flag %q must be set", name)
447 }
448 flag.ShorthandDeprecated = usageMessage
449 return nil
450 }
451 452 // MarkHidden sets a flag to 'hidden' in your program. It will continue to
453 // function but will not show up in help or usage messages.
454 func (f *FlagSet) MarkHidden(name string) error {
455 flag := f.Lookup(name)
456 if flag == nil {
457 return &NotExistError{name: name, messageType: flagNotExistMessage}
458 }
459 flag.Hidden = true
460 return nil
461 }
462 463 // Lookup returns the Flag structure of the named command-line flag,
464 // returning nil if none exists.
465 func Lookup(name string) *Flag {
466 return CommandLine.Lookup(name)
467 }
468 469 // ShorthandLookup returns the Flag structure of the short handed flag,
470 // returning nil if none exists.
471 func ShorthandLookup(name string) *Flag {
472 return CommandLine.ShorthandLookup(name)
473 }
474 475 // Set sets the value of the named flag.
476 func (f *FlagSet) Set(name, value string) error {
477 normalName := f.normalizeFlagName(name)
478 flag, ok := f.formal[normalName]
479 if !ok {
480 return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}
481 }
482 483 err := flag.Value.Set(value)
484 if err != nil {
485 return &InvalidValueError{
486 flag: flag,
487 value: value,
488 cause: err,
489 }
490 }
491 492 if !flag.Changed {
493 if f.actual == nil {
494 f.actual = make(map[NormalizedName]*Flag)
495 }
496 f.actual[normalName] = flag
497 f.orderedActual = append(f.orderedActual, flag)
498 499 flag.Changed = true
500 }
501 502 if flag.Deprecated != "" {
503 fmt.Fprintf(f.Output(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
504 }
505 return nil
506 }
507 508 // SetAnnotation allows one to set arbitrary annotations on a flag in the FlagSet.
509 // This is sometimes used by spf13/cobra programs which want to generate additional
510 // bash completion information.
511 func (f *FlagSet) SetAnnotation(name, key string, values []string) error {
512 normalName := f.normalizeFlagName(name)
513 flag, ok := f.formal[normalName]
514 if !ok {
515 return &NotExistError{name: name, messageType: flagNoSuchFlagMessage}
516 }
517 if flag.Annotations == nil {
518 flag.Annotations = map[string][]string{}
519 }
520 flag.Annotations[key] = values
521 return nil
522 }
523 524 // Changed returns true if the flag was explicitly set during Parse() and false
525 // otherwise
526 func (f *FlagSet) Changed(name string) bool {
527 flag := f.Lookup(name)
528 // If a flag doesn't exist, it wasn't changed....
529 if flag == nil {
530 return false
531 }
532 return flag.Changed
533 }
534 535 // Set sets the value of the named command-line flag.
536 func Set(name, value string) error {
537 return CommandLine.Set(name, value)
538 }
539 540 // PrintDefaults prints, to standard error unless configured
541 // otherwise, the default values of all defined flags in the set.
542 func (f *FlagSet) PrintDefaults() {
543 usages := f.FlagUsages()
544 fmt.Fprint(f.Output(), usages)
545 }
546 547 // defaultIsZeroValue returns true if the default value for this flag represents
548 // a zero value.
549 func (f *Flag) defaultIsZeroValue() bool {
550 switch f.Value.(type) {
551 case boolFlag:
552 return f.DefValue == "false" || f.DefValue == ""
553 case *durationValue:
554 // Beginning in Go 1.7, duration zero values are "0s"
555 return f.DefValue == "0" || f.DefValue == "0s"
556 case *intValue, *int8Value, *int32Value, *int64Value, *uintValue, *uint8Value, *uint16Value, *uint32Value, *uint64Value, *countValue, *float32Value, *float64Value:
557 return f.DefValue == "0"
558 case *stringValue:
559 return f.DefValue == ""
560 case *ipValue, *ipMaskValue, *ipNetValue:
561 return f.DefValue == "<nil>"
562 case *intSliceValue, *stringSliceValue, *stringArrayValue:
563 return f.DefValue == "[]"
564 default:
565 switch f.DefValue {
566 case "false":
567 return true
568 case "<nil>":
569 return true
570 case "":
571 return true
572 case "0":
573 return true
574 }
575 return false
576 }
577 }
578 579 // UnquoteUsage extracts a back-quoted name from the usage
580 // string for a flag and returns it and the un-quoted usage.
581 // Given "a `name` to show" it returns ("name", "a name to show").
582 // If there are no back quotes, the name is an educated guess of the
583 // type of the flag's value, or the empty string if the flag is boolean.
584 func UnquoteUsage(flag *Flag) (name string, usage string) {
585 // Look for a back-quoted name, but avoid the strings package.
586 usage = flag.Usage
587 for i := 0; i < len(usage); i++ {
588 if usage[i] == '`' {
589 for j := i + 1; j < len(usage); j++ {
590 if usage[j] == '`' {
591 name = usage[i+1 : j]
592 usage = usage[:i] + name + usage[j+1:]
593 return name, usage
594 }
595 }
596 break // Only one back quote; use type name.
597 }
598 }
599 600 name = flag.Value.Type()
601 switch name {
602 case "bool", "boolfunc":
603 name = ""
604 case "func":
605 name = "value"
606 case "float64":
607 name = "float"
608 case "int64":
609 name = "int"
610 case "uint64":
611 name = "uint"
612 case "stringSlice":
613 name = "strings"
614 case "intSlice":
615 name = "ints"
616 case "uintSlice":
617 name = "uints"
618 case "boolSlice":
619 name = "bools"
620 }
621 622 return
623 }
624 625 // Splits the string `s` on whitespace into an initial substring up to
626 // `i` runes in length and the remainder. Will go `slop` over `i` if
627 // that encompasses the entire string (which allows the caller to
628 // avoid short orphan words on the final line).
629 func wrapN(i, slop int, s string) (string, string) {
630 if i+slop > len(s) {
631 return s, ""
632 }
633 634 w := strings.LastIndexAny(s[:i], " \t\n")
635 if w <= 0 {
636 return s, ""
637 }
638 nlPos := strings.LastIndex(s[:i], "\n")
639 if nlPos > 0 && nlPos < w {
640 return s[:nlPos], s[nlPos+1:]
641 }
642 return s[:w], s[w+1:]
643 }
644 645 // Wraps the string `s` to a maximum width `w` with leading indent
646 // `i`. The first line is not indented (this is assumed to be done by
647 // caller). Pass `w` == 0 to do no wrapping
648 func wrap(i, w int, s string) string {
649 if w == 0 {
650 return strings.Replace(s, "\n", "\n"+strings.Repeat(" ", i), -1)
651 }
652 653 // space between indent i and end of line width w into which
654 // we should wrap the text.
655 wrap := w - i
656 657 var r, l string
658 659 // Not enough space for sensible wrapping. Wrap as a block on
660 // the next line instead.
661 if wrap < 24 {
662 i = 16
663 wrap = w - i
664 r += "\n" + strings.Repeat(" ", i)
665 }
666 // If still not enough space then don't even try to wrap.
667 if wrap < 24 {
668 return strings.Replace(s, "\n", r, -1)
669 }
670 671 // Try to avoid short orphan words on the final line, by
672 // allowing wrapN to go a bit over if that would fit in the
673 // remainder of the line.
674 slop := 5
675 wrap = wrap - slop
676 677 // Handle first line, which is indented by the caller (or the
678 // special case above)
679 l, s = wrapN(wrap, slop, s)
680 r = r + strings.Replace(l, "\n", "\n"+strings.Repeat(" ", i), -1)
681 682 // Now wrap the rest
683 for s != "" {
684 var t string
685 686 t, s = wrapN(wrap, slop, s)
687 r = r + "\n" + strings.Repeat(" ", i) + strings.Replace(t, "\n", "\n"+strings.Repeat(" ", i), -1)
688 }
689 690 return r
691 692 }
693 694 // FlagUsagesWrapped returns a string containing the usage information
695 // for all flags in the FlagSet. Wrapped to `cols` columns (0 for no
696 // wrapping)
697 func (f *FlagSet) FlagUsagesWrapped(cols int) string {
698 buf := new(bytes.Buffer)
699 700 lines := make([]string, 0, len(f.formal))
701 702 maxlen := 0
703 f.VisitAll(func(flag *Flag) {
704 if flag.Hidden {
705 return
706 }
707 708 line := ""
709 if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
710 line = fmt.Sprintf(" -%s, --%s", flag.Shorthand, flag.Name)
711 } else {
712 line = fmt.Sprintf(" --%s", flag.Name)
713 }
714 715 varname, usage := UnquoteUsage(flag)
716 if varname != "" {
717 line += " " + varname
718 }
719 if flag.NoOptDefVal != "" {
720 switch flag.Value.Type() {
721 case "string":
722 line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal)
723 case "bool", "boolfunc":
724 if flag.NoOptDefVal != "true" {
725 line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
726 }
727 case "count":
728 if flag.NoOptDefVal != "+1" {
729 line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
730 }
731 default:
732 line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
733 }
734 }
735 736 // This special character will be replaced with spacing once the
737 // correct alignment is calculated
738 line += "\x00"
739 if len(line) > maxlen {
740 maxlen = len(line)
741 }
742 743 line += usage
744 if !flag.defaultIsZeroValue() {
745 if flag.Value.Type() == "string" {
746 line += fmt.Sprintf(" (default %q)", flag.DefValue)
747 } else {
748 line += fmt.Sprintf(" (default %s)", flag.DefValue)
749 }
750 }
751 if len(flag.Deprecated) != 0 {
752 line += fmt.Sprintf(" (DEPRECATED: %s)", flag.Deprecated)
753 }
754 755 lines = append(lines, line)
756 })
757 758 for _, line := range lines {
759 sidx := strings.Index(line, "\x00")
760 spacing := strings.Repeat(" ", maxlen-sidx)
761 // maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx
762 fmt.Fprintln(buf, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:]))
763 }
764 765 return buf.String()
766 }
767 768 // FlagUsages returns a string containing the usage information for all flags in
769 // the FlagSet
770 func (f *FlagSet) FlagUsages() string {
771 return f.FlagUsagesWrapped(0)
772 }
773 774 // PrintDefaults prints to standard error the default values of all defined command-line flags.
775 func PrintDefaults() {
776 CommandLine.PrintDefaults()
777 }
778 779 // defaultUsage is the default function to print a usage message.
780 func defaultUsage(f *FlagSet) {
781 fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name)
782 f.PrintDefaults()
783 }
784 785 // NOTE: Usage is not just defaultUsage(CommandLine)
786 // because it serves (via godoc flag Usage) as the example
787 // for how to write your own usage function.
788 789 // Usage prints to standard error a usage message documenting all defined command-line flags.
790 // The function is a variable that may be changed to point to a custom function.
791 // By default it prints a simple header and calls PrintDefaults; for details about the
792 // format of the output and how to control it, see the documentation for PrintDefaults.
793 var Usage = func() {
794 fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
795 PrintDefaults()
796 }
797 798 // NFlag returns the number of flags that have been set.
799 func (f *FlagSet) NFlag() int { return len(f.actual) }
800 801 // NFlag returns the number of command-line flags that have been set.
802 func NFlag() int { return len(CommandLine.actual) }
803 804 // Arg returns the i'th argument. Arg(0) is the first remaining argument
805 // after flags have been processed.
806 func (f *FlagSet) Arg(i int) string {
807 if i < 0 || i >= len(f.args) {
808 return ""
809 }
810 return f.args[i]
811 }
812 813 // Arg returns the i'th command-line argument. Arg(0) is the first remaining argument
814 // after flags have been processed.
815 func Arg(i int) string {
816 return CommandLine.Arg(i)
817 }
818 819 // NArg is the number of arguments remaining after flags have been processed.
820 func (f *FlagSet) NArg() int { return len(f.args) }
821 822 // NArg is the number of arguments remaining after flags have been processed.
823 func NArg() int { return len(CommandLine.args) }
824 825 // Args returns the non-flag arguments.
826 func (f *FlagSet) Args() []string { return f.args }
827 828 // Args returns the non-flag command-line arguments.
829 func Args() []string { return CommandLine.args }
830 831 // Var defines a flag with the specified name and usage string. The type and
832 // value of the flag are represented by the first argument, of type Value, which
833 // typically holds a user-defined implementation of Value. For instance, the
834 // caller could create a flag that turns a comma-separated string into a slice
835 // of strings by giving the slice the methods of Value; in particular, Set would
836 // decompose the comma-separated string into the slice.
837 func (f *FlagSet) Var(value Value, name string, usage string) {
838 f.VarP(value, name, "", usage)
839 }
840 841 // VarPF is like VarP, but returns the flag created
842 func (f *FlagSet) VarPF(value Value, name, shorthand, usage string) *Flag {
843 // Remember the default value as a string; it won't change.
844 flag := &Flag{
845 Name: name,
846 Shorthand: shorthand,
847 Usage: usage,
848 Value: value,
849 DefValue: value.String(),
850 }
851 f.AddFlag(flag)
852 return flag
853 }
854 855 // VarP is like Var, but accepts a shorthand letter that can be used after a single dash.
856 func (f *FlagSet) VarP(value Value, name, shorthand, usage string) {
857 f.VarPF(value, name, shorthand, usage)
858 }
859 860 // AddFlag will add the flag to the FlagSet
861 func (f *FlagSet) AddFlag(flag *Flag) {
862 normalizedFlagName := f.normalizeFlagName(flag.Name)
863 864 _, alreadyThere := f.formal[normalizedFlagName]
865 if alreadyThere {
866 msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name)
867 fmt.Fprintln(f.Output(), msg)
868 panic(msg) // Happens only if flags are declared with identical names
869 }
870 if f.formal == nil {
871 f.formal = make(map[NormalizedName]*Flag)
872 }
873 874 flag.Name = string(normalizedFlagName)
875 f.formal[normalizedFlagName] = flag
876 f.orderedFormal = append(f.orderedFormal, flag)
877 878 if flag.Shorthand == "" {
879 return
880 }
881 if len(flag.Shorthand) > 1 {
882 msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand)
883 fmt.Fprintf(f.Output(), msg)
884 panic(msg)
885 }
886 if f.shorthands == nil {
887 f.shorthands = make(map[byte]*Flag)
888 }
889 c := flag.Shorthand[0]
890 used, alreadyThere := f.shorthands[c]
891 if alreadyThere {
892 msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name)
893 fmt.Fprintf(f.Output(), msg)
894 panic(msg)
895 }
896 f.shorthands[c] = flag
897 }
898 899 // AddFlagSet adds one FlagSet to another. If a flag is already present in f
900 // the flag from newSet will be ignored.
901 func (f *FlagSet) AddFlagSet(newSet *FlagSet) {
902 if newSet == nil {
903 return
904 }
905 newSet.VisitAll(func(flag *Flag) {
906 if f.Lookup(flag.Name) == nil {
907 f.AddFlag(flag)
908 }
909 })
910 }
911 912 // Var defines a flag with the specified name and usage string. The type and
913 // value of the flag are represented by the first argument, of type Value, which
914 // typically holds a user-defined implementation of Value. For instance, the
915 // caller could create a flag that turns a comma-separated string into a slice
916 // of strings by giving the slice the methods of Value; in particular, Set would
917 // decompose the comma-separated string into the slice.
918 func Var(value Value, name string, usage string) {
919 CommandLine.VarP(value, name, "", usage)
920 }
921 922 // VarP is like Var, but accepts a shorthand letter that can be used after a single dash.
923 func VarP(value Value, name, shorthand, usage string) {
924 CommandLine.VarP(value, name, shorthand, usage)
925 }
926 927 // fail prints an error message and usage message to standard error and
928 // returns the error.
929 func (f *FlagSet) fail(err error) error {
930 if f.errorHandling != ContinueOnError {
931 fmt.Fprintln(f.Output(), err)
932 f.usage()
933 }
934 return err
935 }
936 937 // usage calls the Usage method for the flag set, or the usage function if
938 // the flag set is CommandLine.
939 func (f *FlagSet) usage() {
940 if f == CommandLine {
941 Usage()
942 } else if f.Usage == nil {
943 defaultUsage(f)
944 } else {
945 f.Usage()
946 }
947 }
948 949 // --unknown (args will be empty)
950 // --unknown --next-flag ... (args will be --next-flag ...)
951 // --unknown arg ... (args will be arg ...)
952 func stripUnknownFlagValue(args []string) []string {
953 if len(args) == 0 {
954 //--unknown
955 return args
956 }
957 958 first := args[0]
959 if len(first) > 0 && first[0] == '-' {
960 //--unknown --next-flag ...
961 return args
962 }
963 964 //--unknown arg ... (args will be arg ...)
965 if len(args) > 1 {
966 return args[1:]
967 }
968 return nil
969 }
970 971 func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
972 a = args
973 name := s[2:]
974 if len(name) == 0 || name[0] == '-' || name[0] == '=' {
975 err = f.fail(&InvalidSyntaxError{specifiedFlag: s})
976 return
977 }
978 979 split := strings.SplitN(name, "=", 2)
980 name = split[0]
981 flag, exists := f.formal[f.normalizeFlagName(name)]
982 983 if !exists {
984 switch {
985 case name == "help":
986 f.usage()
987 return a, ErrHelp
988 case f.ParseErrorsWhitelist.UnknownFlags:
989 // --unknown=unknownval arg ...
990 // we do not want to lose arg in this case
991 if len(split) >= 2 {
992 return a, nil
993 }
994 995 return stripUnknownFlagValue(a), nil
996 default:
997 err = f.fail(&NotExistError{name: name, messageType: flagUnknownFlagMessage})
998 return
999 }
1000 }
1001 1002 var value string
1003 if len(split) == 2 {
1004 // '--flag=arg'
1005 value = split[1]
1006 } else if flag.NoOptDefVal != "" {
1007 // '--flag' (arg was optional)
1008 value = flag.NoOptDefVal
1009 } else if len(a) > 0 {
1010 // '--flag arg'
1011 value = a[0]
1012 a = a[1:]
1013 } else {
1014 // '--flag' (arg was required)
1015 err = f.fail(&ValueRequiredError{
1016 flag: flag,
1017 specifiedName: name,
1018 })
1019 return
1020 }
1021 1022 err = fn(flag, value)
1023 if err != nil {
1024 f.fail(err)
1025 }
1026 return
1027 }
1028 1029 func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
1030 outArgs = args
1031 1032 if isGotestShorthandFlag(shorthands) {
1033 return
1034 }
1035 1036 outShorts = shorthands[1:]
1037 c := shorthands[0]
1038 1039 flag, exists := f.shorthands[c]
1040 if !exists {
1041 switch {
1042 case c == 'h':
1043 f.usage()
1044 err = ErrHelp
1045 return
1046 case f.ParseErrorsWhitelist.UnknownFlags:
1047 // '-f=arg arg ...'
1048 // we do not want to lose arg in this case
1049 if len(shorthands) > 2 && shorthands[1] == '=' {
1050 outShorts = ""
1051 return
1052 }
1053 1054 outArgs = stripUnknownFlagValue(outArgs)
1055 return
1056 default:
1057 err = f.fail(&NotExistError{
1058 name: string(c),
1059 specifiedShorthands: shorthands,
1060 messageType: flagUnknownShorthandFlagMessage,
1061 })
1062 return
1063 }
1064 }
1065 1066 var value string
1067 if len(shorthands) > 2 && shorthands[1] == '=' {
1068 // '-f=arg'
1069 value = shorthands[2:]
1070 outShorts = ""
1071 } else if flag.NoOptDefVal != "" {
1072 // '-f' (arg was optional)
1073 value = flag.NoOptDefVal
1074 } else if len(shorthands) > 1 {
1075 // '-farg'
1076 value = shorthands[1:]
1077 outShorts = ""
1078 } else if len(args) > 0 {
1079 // '-f arg'
1080 value = args[0]
1081 outArgs = args[1:]
1082 } else {
1083 // '-f' (arg was required)
1084 err = f.fail(&ValueRequiredError{
1085 flag: flag,
1086 specifiedName: string(c),
1087 specifiedShorthands: shorthands,
1088 })
1089 return
1090 }
1091 1092 if flag.ShorthandDeprecated != "" {
1093 fmt.Fprintf(f.Output(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
1094 }
1095 1096 err = fn(flag, value)
1097 if err != nil {
1098 f.fail(err)
1099 }
1100 return
1101 }
1102 1103 func (f *FlagSet) parseShortArg(s string, args []string, fn parseFunc) (a []string, err error) {
1104 a = args
1105 shorthands := s[1:]
1106 1107 // "shorthands" can be a series of shorthand letters of flags (e.g. "-vvv").
1108 for len(shorthands) > 0 {
1109 shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn)
1110 if err != nil {
1111 return
1112 }
1113 }
1114 1115 return
1116 }
1117 1118 func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) {
1119 for len(args) > 0 {
1120 s := args[0]
1121 args = args[1:]
1122 if len(s) == 0 || s[0] != '-' || len(s) == 1 {
1123 if !f.interspersed {
1124 f.args = append(f.args, s)
1125 f.args = append(f.args, args...)
1126 return nil
1127 }
1128 f.args = append(f.args, s)
1129 continue
1130 }
1131 1132 if s[1] == '-' {
1133 if len(s) == 2 { // "--" terminates the flags
1134 f.argsLenAtDash = len(f.args)
1135 f.args = append(f.args, args...)
1136 break
1137 }
1138 args, err = f.parseLongArg(s, args, fn)
1139 } else {
1140 args, err = f.parseShortArg(s, args, fn)
1141 }
1142 if err != nil {
1143 return
1144 }
1145 }
1146 return
1147 }
1148 1149 // Parse parses flag definitions from the argument list, which should not
1150 // include the command name. Must be called after all flags in the FlagSet
1151 // are defined and before flags are accessed by the program.
1152 // The return value will be ErrHelp if -help was set but not defined.
1153 func (f *FlagSet) Parse(arguments []string) error {
1154 if f.addedGoFlagSets != nil {
1155 for _, goFlagSet := range f.addedGoFlagSets {
1156 goFlagSet.Parse(nil)
1157 }
1158 }
1159 f.parsed = true
1160 1161 if len(arguments) == 0 {
1162 return nil
1163 }
1164 1165 f.args = make([]string, 0, len(arguments))
1166 1167 set := func(flag *Flag, value string) error {
1168 return f.Set(flag.Name, value)
1169 }
1170 1171 err := f.parseArgs(arguments, set)
1172 if err != nil {
1173 switch f.errorHandling {
1174 case ContinueOnError:
1175 return err
1176 case ExitOnError:
1177 fmt.Println(err)
1178 os.Exit(2)
1179 case PanicOnError:
1180 panic(err)
1181 }
1182 }
1183 return nil
1184 }
1185 1186 type parseFunc func(flag *Flag, value string) error
1187 1188 // ParseAll parses flag definitions from the argument list, which should not
1189 // include the command name. The arguments for fn are flag and value. Must be
1190 // called after all flags in the FlagSet are defined and before flags are
1191 // accessed by the program. The return value will be ErrHelp if -help was set
1192 // but not defined.
1193 func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string) error) error {
1194 f.parsed = true
1195 f.args = make([]string, 0, len(arguments))
1196 1197 err := f.parseArgs(arguments, fn)
1198 if err != nil {
1199 switch f.errorHandling {
1200 case ContinueOnError:
1201 return err
1202 case ExitOnError:
1203 os.Exit(2)
1204 case PanicOnError:
1205 panic(err)
1206 }
1207 }
1208 return nil
1209 }
1210 1211 // Parsed reports whether f.Parse has been called.
1212 func (f *FlagSet) Parsed() bool {
1213 return f.parsed
1214 }
1215 1216 // Parse parses the command-line flags from os.Args[1:]. Must be called
1217 // after all flags are defined and before flags are accessed by the program.
1218 func Parse() {
1219 // Ignore errors; CommandLine is set for ExitOnError.
1220 CommandLine.Parse(os.Args[1:])
1221 }
1222 1223 // ParseAll parses the command-line flags from os.Args[1:] and called fn for each.
1224 // The arguments for fn are flag and value. Must be called after all flags are
1225 // defined and before flags are accessed by the program.
1226 func ParseAll(fn func(flag *Flag, value string) error) {
1227 // Ignore errors; CommandLine is set for ExitOnError.
1228 CommandLine.ParseAll(os.Args[1:], fn)
1229 }
1230 1231 // SetInterspersed sets whether to support interspersed option/non-option arguments.
1232 func SetInterspersed(interspersed bool) {
1233 CommandLine.SetInterspersed(interspersed)
1234 }
1235 1236 // Parsed returns true if the command-line flags have been parsed.
1237 func Parsed() bool {
1238 return CommandLine.Parsed()
1239 }
1240 1241 // CommandLine is the default set of command-line flags, parsed from os.Args.
1242 var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
1243 1244 // NewFlagSet returns a new, empty flag set with the specified name,
1245 // error handling property and SortFlags set to true.
1246 func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
1247 f := &FlagSet{
1248 name: name,
1249 errorHandling: errorHandling,
1250 argsLenAtDash: -1,
1251 interspersed: true,
1252 SortFlags: true,
1253 }
1254 return f
1255 }
1256 1257 // SetInterspersed sets whether to support interspersed option/non-option arguments.
1258 func (f *FlagSet) SetInterspersed(interspersed bool) {
1259 f.interspersed = interspersed
1260 }
1261 1262 // Init sets the name and error handling property for a flag set.
1263 // By default, the zero FlagSet uses an empty name and the
1264 // ContinueOnError error handling policy.
1265 func (f *FlagSet) Init(name string, errorHandling ErrorHandling) {
1266 f.name = name
1267 f.errorHandling = errorHandling
1268 f.argsLenAtDash = -1
1269 }
1270