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