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