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