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/ogier/pflag" 20 21 There 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 name string 138 parsed bool 139 actual map[NormalizedName]*Flag 140 formal map[NormalizedName]*Flag 141 shorthands map[byte]*Flag 142 args []string // arguments after flags 143 argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no -- 144 exitOnError bool // does the program exit if there's an error? 145 errorHandling ErrorHandling 146 output io.Writer // nil means stderr; use out() accessor 147 interspersed bool // allow interspersed option/non-option args 148 normalizeNameFunc func(f *FlagSet, name string) NormalizedName 149} 150 151// A Flag represents the state of a flag. 152type Flag struct { 153 Name string // name as it appears on command line 154 Shorthand string // one-letter abbreviated flag 155 Usage string // help message 156 Value Value // value as set 157 DefValue string // default value (as text); for usage message 158 Changed bool // If the user set the value (or if left to default) 159 NoOptDefVal string //default value (as text); if the flag is on the command line without any options 160 Deprecated string // If this flag is deprecated, this string is the new or now thing to use 161 Hidden bool // used by cobra.Command to allow flags to be hidden from help/usage text 162 ShorthandDeprecated string // If the shorthand of this flag is deprecated, this string is the new or now thing to use 163 Annotations map[string][]string // used by cobra.Command bash autocomple code 164} 165 166// Value is the interface to the dynamic value stored in a flag. 167// (The default value is represented as a string.) 168type Value interface { 169 String() string 170 Set(string) error 171 Type() string 172} 173 174// sortFlags returns the flags as a slice in lexicographical sorted order. 175func sortFlags(flags map[NormalizedName]*Flag) []*Flag { 176 list := make(sort.StringSlice, len(flags)) 177 i := 0 178 for k := range flags { 179 list[i] = string(k) 180 i++ 181 } 182 list.Sort() 183 result := make([]*Flag, len(list)) 184 for i, name := range list { 185 result[i] = flags[NormalizedName(name)] 186 } 187 return result 188} 189 190// SetNormalizeFunc allows you to add a function which can translate flag names. 191// Flags added to the FlagSet will be translated and then when anything tries to 192// look up the flag that will also be translated. So it would be possible to create 193// a flag named "getURL" and have it translated to "geturl". A user could then pass 194// "--getUrl" which may also be translated to "geturl" and everything will work. 195func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) { 196 f.normalizeNameFunc = n 197 for k, v := range f.formal { 198 delete(f.formal, k) 199 nname := f.normalizeFlagName(string(k)) 200 f.formal[nname] = v 201 v.Name = string(nname) 202 } 203} 204 205// GetNormalizeFunc returns the previously set NormalizeFunc of a function which 206// does no translation, if not set previously. 207func (f *FlagSet) GetNormalizeFunc() func(f *FlagSet, name string) NormalizedName { 208 if f.normalizeNameFunc != nil { 209 return f.normalizeNameFunc 210 } 211 return func(f *FlagSet, name string) NormalizedName { return NormalizedName(name) } 212} 213 214func (f *FlagSet) normalizeFlagName(name string) NormalizedName { 215 n := f.GetNormalizeFunc() 216 return n(f, name) 217} 218 219func (f *FlagSet) out() io.Writer { 220 if f.output == nil { 221 return os.Stderr 222 } 223 return f.output 224} 225 226// SetOutput sets the destination for usage and error messages. 227// If output is nil, os.Stderr is used. 228func (f *FlagSet) SetOutput(output io.Writer) { 229 f.output = output 230} 231 232// VisitAll visits the flags in lexicographical order, calling fn for each. 233// It visits all flags, even those not set. 234func (f *FlagSet) VisitAll(fn func(*Flag)) { 235 for _, flag := range sortFlags(f.formal) { 236 fn(flag) 237 } 238} 239 240// HasFlags returns a bool to indicate if the FlagSet has any flags definied. 241func (f *FlagSet) HasFlags() bool { 242 return len(f.formal) > 0 243} 244 245// VisitAll visits the command-line flags in lexicographical order, calling 246// fn for each. It visits all flags, even those not set. 247func VisitAll(fn func(*Flag)) { 248 CommandLine.VisitAll(fn) 249} 250 251// Visit visits the flags in lexicographical order, calling fn for each. 252// It visits only those flags that have been set. 253func (f *FlagSet) Visit(fn func(*Flag)) { 254 for _, flag := range sortFlags(f.actual) { 255 fn(flag) 256 } 257} 258 259// Visit visits the command-line flags in lexicographical order, calling fn 260// for each. It visits only those flags that have been set. 261func Visit(fn func(*Flag)) { 262 CommandLine.Visit(fn) 263} 264 265// Lookup returns the Flag structure of the named flag, returning nil if none exists. 266func (f *FlagSet) Lookup(name string) *Flag { 267 return f.lookup(f.normalizeFlagName(name)) 268} 269 270// lookup returns the Flag structure of the named flag, returning nil if none exists. 271func (f *FlagSet) lookup(name NormalizedName) *Flag { 272 return f.formal[name] 273} 274 275// func to return a given type for a given flag name 276func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval string) (interface{}, error)) (interface{}, error) { 277 flag := f.Lookup(name) 278 if flag == nil { 279 err := fmt.Errorf("flag accessed but not defined: %s", name) 280 return nil, err 281 } 282 283 if flag.Value.Type() != ftype { 284 err := fmt.Errorf("trying to get %s value of flag of type %s", ftype, flag.Value.Type()) 285 return nil, err 286 } 287 288 sval := flag.Value.String() 289 result, err := convFunc(sval) 290 if err != nil { 291 return nil, err 292 } 293 return result, nil 294} 295 296// ArgsLenAtDash will return the length of f.Args at the moment when a -- was 297// found during arg parsing. This allows your program to know which args were 298// before the -- and which came after. 299func (f *FlagSet) ArgsLenAtDash() int { 300 return f.argsLenAtDash 301} 302 303// MarkDeprecated indicated that a flag is deprecated in your program. It will 304// continue to function but will not show up in help or usage messages. Using 305// this flag will also print the given usageMessage. 306func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error { 307 flag := f.Lookup(name) 308 if flag == nil { 309 return fmt.Errorf("flag %q does not exist", name) 310 } 311 if len(usageMessage) == 0 { 312 return fmt.Errorf("deprecated message for flag %q must be set", name) 313 } 314 flag.Deprecated = usageMessage 315 return nil 316} 317 318// MarkShorthandDeprecated will mark the shorthand of a flag deprecated in your 319// program. It will continue to function but will not show up in help or usage 320// messages. Using this flag will also print the given usageMessage. 321func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) error { 322 flag := f.Lookup(name) 323 if flag == nil { 324 return fmt.Errorf("flag %q does not exist", name) 325 } 326 if len(usageMessage) == 0 { 327 return fmt.Errorf("deprecated message for flag %q must be set", name) 328 } 329 flag.ShorthandDeprecated = usageMessage 330 return nil 331} 332 333// MarkHidden sets a flag to 'hidden' in your program. It will continue to 334// function but will not show up in help or usage messages. 335func (f *FlagSet) MarkHidden(name string) error { 336 flag := f.Lookup(name) 337 if flag == nil { 338 return fmt.Errorf("flag %q does not exist", name) 339 } 340 flag.Hidden = true 341 return nil 342} 343 344// Lookup returns the Flag structure of the named command-line flag, 345// returning nil if none exists. 346func Lookup(name string) *Flag { 347 return CommandLine.Lookup(name) 348} 349 350// Set sets the value of the named flag. 351func (f *FlagSet) Set(name, value string) error { 352 normalName := f.normalizeFlagName(name) 353 flag, ok := f.formal[normalName] 354 if !ok { 355 return fmt.Errorf("no such flag -%v", name) 356 } 357 err := flag.Value.Set(value) 358 if err != nil { 359 return err 360 } 361 if f.actual == nil { 362 f.actual = make(map[NormalizedName]*Flag) 363 } 364 f.actual[normalName] = flag 365 flag.Changed = true 366 if len(flag.Deprecated) > 0 { 367 fmt.Fprintf(os.Stderr, "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) 368 } 369 return nil 370} 371 372// SetAnnotation allows one to set arbitrary annotations on a flag in the FlagSet. 373// This is sometimes used by spf13/cobra programs which want to generate additional 374// bash completion information. 375func (f *FlagSet) SetAnnotation(name, key string, values []string) error { 376 normalName := f.normalizeFlagName(name) 377 flag, ok := f.formal[normalName] 378 if !ok { 379 return fmt.Errorf("no such flag -%v", name) 380 } 381 if flag.Annotations == nil { 382 flag.Annotations = map[string][]string{} 383 } 384 flag.Annotations[key] = values 385 return nil 386} 387 388// Changed returns true if the flag was explicitly set during Parse() and false 389// otherwise 390func (f *FlagSet) Changed(name string) bool { 391 flag := f.Lookup(name) 392 // If a flag doesn't exist, it wasn't changed.... 393 if flag == nil { 394 return false 395 } 396 return flag.Changed 397} 398 399// Set sets the value of the named command-line flag. 400func Set(name, value string) error { 401 return CommandLine.Set(name, value) 402} 403 404// PrintDefaults prints, to standard error unless configured 405// otherwise, the default values of all defined flags in the set. 406func (f *FlagSet) PrintDefaults() { 407 usages := f.FlagUsages() 408 fmt.Fprintf(f.out(), "%s", usages) 409} 410 411// FlagUsages Returns a string containing the usage information for all flags in 412// the FlagSet 413func (f *FlagSet) FlagUsages() string { 414 x := new(bytes.Buffer) 415 416 f.VisitAll(func(flag *Flag) { 417 if len(flag.Deprecated) > 0 || flag.Hidden { 418 return 419 } 420 format := "" 421 if len(flag.Shorthand) > 0 && len(flag.ShorthandDeprecated) == 0 { 422 format = " -%s, --%s" 423 } else { 424 format = " %s --%s" 425 } 426 if len(flag.NoOptDefVal) > 0 { 427 format = format + "[" 428 } 429 if flag.Value.Type() == "string" { 430 // put quotes on the value 431 format = format + "=%q" 432 } else { 433 format = format + "=%s" 434 } 435 if len(flag.NoOptDefVal) > 0 { 436 format = format + "]" 437 } 438 format = format + ": %s\n" 439 shorthand := flag.Shorthand 440 if len(flag.ShorthandDeprecated) > 0 { 441 shorthand = "" 442 } 443 fmt.Fprintf(x, format, shorthand, flag.Name, flag.DefValue, flag.Usage) 444 }) 445 446 return x.String() 447} 448 449// PrintDefaults prints to standard error the default values of all defined command-line flags. 450func PrintDefaults() { 451 CommandLine.PrintDefaults() 452} 453 454// defaultUsage is the default function to print a usage message. 455func defaultUsage(f *FlagSet) { 456 fmt.Fprintf(f.out(), "Usage of %s:\n", f.name) 457 f.PrintDefaults() 458} 459 460// NOTE: Usage is not just defaultUsage(CommandLine) 461// because it serves (via godoc flag Usage) as the example 462// for how to write your own usage function. 463 464// Usage prints to standard error a usage message documenting all defined command-line flags. 465// The function is a variable that may be changed to point to a custom function. 466var Usage = func() { 467 fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) 468 PrintDefaults() 469} 470 471// NFlag returns the number of flags that have been set. 472func (f *FlagSet) NFlag() int { return len(f.actual) } 473 474// NFlag returns the number of command-line flags that have been set. 475func NFlag() int { return len(CommandLine.actual) } 476 477// Arg returns the i'th argument. Arg(0) is the first remaining argument 478// after flags have been processed. 479func (f *FlagSet) Arg(i int) string { 480 if i < 0 || i >= len(f.args) { 481 return "" 482 } 483 return f.args[i] 484} 485 486// Arg returns the i'th command-line argument. Arg(0) is the first remaining argument 487// after flags have been processed. 488func Arg(i int) string { 489 return CommandLine.Arg(i) 490} 491 492// NArg is the number of arguments remaining after flags have been processed. 493func (f *FlagSet) NArg() int { return len(f.args) } 494 495// NArg is the number of arguments remaining after flags have been processed. 496func NArg() int { return len(CommandLine.args) } 497 498// Args returns the non-flag arguments. 499func (f *FlagSet) Args() []string { return f.args } 500 501// Args returns the non-flag command-line arguments. 502func Args() []string { return CommandLine.args } 503 504// Var defines a flag with the specified name and usage string. The type and 505// value of the flag are represented by the first argument, of type Value, which 506// typically holds a user-defined implementation of Value. For instance, the 507// caller could create a flag that turns a comma-separated string into a slice 508// of strings by giving the slice the methods of Value; in particular, Set would 509// decompose the comma-separated string into the slice. 510func (f *FlagSet) Var(value Value, name string, usage string) { 511 f.VarP(value, name, "", usage) 512} 513 514// VarPF is like VarP, but returns the flag created 515func (f *FlagSet) VarPF(value Value, name, shorthand, usage string) *Flag { 516 // Remember the default value as a string; it won't change. 517 flag := &Flag{ 518 Name: name, 519 Shorthand: shorthand, 520 Usage: usage, 521 Value: value, 522 DefValue: value.String(), 523 } 524 f.AddFlag(flag) 525 return flag 526} 527 528// VarP is like Var, but accepts a shorthand letter that can be used after a single dash. 529func (f *FlagSet) VarP(value Value, name, shorthand, usage string) { 530 _ = f.VarPF(value, name, shorthand, usage) 531} 532 533// AddFlag will add the flag to the FlagSet 534func (f *FlagSet) AddFlag(flag *Flag) { 535 // Call normalizeFlagName function only once 536 normalizedFlagName := f.normalizeFlagName(flag.Name) 537 538 _, alreadythere := f.formal[normalizedFlagName] 539 if alreadythere { 540 msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name) 541 fmt.Fprintln(f.out(), msg) 542 panic(msg) // Happens only if flags are declared with identical names 543 } 544 if f.formal == nil { 545 f.formal = make(map[NormalizedName]*Flag) 546 } 547 548 flag.Name = string(normalizedFlagName) 549 f.formal[normalizedFlagName] = flag 550 551 if len(flag.Shorthand) == 0 { 552 return 553 } 554 if len(flag.Shorthand) > 1 { 555 fmt.Fprintf(f.out(), "%s shorthand more than ASCII character: %s\n", f.name, flag.Shorthand) 556 panic("shorthand is more than one character") 557 } 558 if f.shorthands == nil { 559 f.shorthands = make(map[byte]*Flag) 560 } 561 c := flag.Shorthand[0] 562 old, alreadythere := f.shorthands[c] 563 if alreadythere { 564 fmt.Fprintf(f.out(), "%s shorthand reused: %q for %s already used for %s\n", f.name, c, flag.Name, old.Name) 565 panic("shorthand redefinition") 566 } 567 f.shorthands[c] = flag 568} 569 570// AddFlagSet adds one FlagSet to another. If a flag is already present in f 571// the flag from newSet will be ignored 572func (f *FlagSet) AddFlagSet(newSet *FlagSet) { 573 if newSet == nil { 574 return 575 } 576 newSet.VisitAll(func(flag *Flag) { 577 if f.Lookup(flag.Name) == nil { 578 f.AddFlag(flag) 579 } 580 }) 581} 582 583// Var defines a flag with the specified name and usage string. The type and 584// value of the flag are represented by the first argument, of type Value, which 585// typically holds a user-defined implementation of Value. For instance, the 586// caller could create a flag that turns a comma-separated string into a slice 587// of strings by giving the slice the methods of Value; in particular, Set would 588// decompose the comma-separated string into the slice. 589func Var(value Value, name string, usage string) { 590 CommandLine.VarP(value, name, "", usage) 591} 592 593// VarP is like Var, but accepts a shorthand letter that can be used after a single dash. 594func VarP(value Value, name, shorthand, usage string) { 595 CommandLine.VarP(value, name, shorthand, usage) 596} 597 598// failf prints to standard error a formatted error and usage message and 599// returns the error. 600func (f *FlagSet) failf(format string, a ...interface{}) error { 601 err := fmt.Errorf(format, a...) 602 fmt.Fprintln(f.out(), err) 603 f.usage() 604 return err 605} 606 607// usage calls the Usage method for the flag set, or the usage function if 608// the flag set is CommandLine. 609func (f *FlagSet) usage() { 610 if f == CommandLine { 611 Usage() 612 } else if f.Usage == nil { 613 defaultUsage(f) 614 } else { 615 f.Usage() 616 } 617} 618 619func (f *FlagSet) setFlag(flag *Flag, value string, origArg string) error { 620 if err := flag.Value.Set(value); err != nil { 621 return f.failf("invalid argument %q for %s: %v", value, origArg, err) 622 } 623 // mark as visited for Visit() 624 if f.actual == nil { 625 f.actual = make(map[NormalizedName]*Flag) 626 } 627 f.actual[f.normalizeFlagName(flag.Name)] = flag 628 flag.Changed = true 629 if len(flag.Deprecated) > 0 { 630 fmt.Fprintf(os.Stderr, "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) 631 } 632 if len(flag.ShorthandDeprecated) > 0 && containsShorthand(origArg, flag.Shorthand) { 633 fmt.Fprintf(os.Stderr, "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated) 634 } 635 return nil 636} 637 638func containsShorthand(arg, shorthand string) bool { 639 // filter out flags --<flag_name> 640 if strings.HasPrefix(arg, "-") { 641 return false 642 } 643 arg = strings.SplitN(arg, "=", 2)[0] 644 return strings.Contains(arg, shorthand) 645} 646 647func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error) { 648 a = args 649 name := s[2:] 650 if len(name) == 0 || name[0] == '-' || name[0] == '=' { 651 err = f.failf("bad flag syntax: %s", s) 652 return 653 } 654 split := strings.SplitN(name, "=", 2) 655 name = split[0] 656 flag, alreadythere := f.formal[f.normalizeFlagName(name)] 657 if !alreadythere { 658 if name == "help" { // special case for nice help message. 659 f.usage() 660 return a, ErrHelp 661 } 662 err = f.failf("unknown flag: --%s", name) 663 return 664 } 665 var value string 666 if len(split) == 2 { 667 // '--flag=arg' 668 value = split[1] 669 } else if len(flag.NoOptDefVal) > 0 { 670 // '--flag' (arg was optional) 671 value = flag.NoOptDefVal 672 } else if len(a) > 0 { 673 // '--flag arg' 674 value = a[0] 675 a = a[1:] 676 } else { 677 // '--flag' (arg was required) 678 err = f.failf("flag needs an argument: %s", s) 679 return 680 } 681 err = f.setFlag(flag, value, s) 682 return 683} 684 685func (f *FlagSet) parseSingleShortArg(shorthands string, args []string) (outShorts string, outArgs []string, err error) { 686 outArgs = args 687 outShorts = shorthands[1:] 688 c := shorthands[0] 689 690 flag, alreadythere := f.shorthands[c] 691 if !alreadythere { 692 if c == 'h' { // special case for nice help message. 693 f.usage() 694 err = ErrHelp 695 return 696 } 697 //TODO continue on error 698 err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands) 699 return 700 } 701 var value string 702 if len(shorthands) > 2 && shorthands[1] == '=' { 703 value = shorthands[2:] 704 outShorts = "" 705 } else if len(flag.NoOptDefVal) > 0 { 706 value = flag.NoOptDefVal 707 } else if len(shorthands) > 1 { 708 value = shorthands[1:] 709 outShorts = "" 710 } else if len(args) > 0 { 711 value = args[0] 712 outArgs = args[1:] 713 } else { 714 err = f.failf("flag needs an argument: %q in -%s", c, shorthands) 715 return 716 } 717 err = f.setFlag(flag, value, shorthands) 718 return 719} 720 721func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error) { 722 a = args 723 shorthands := s[1:] 724 725 for len(shorthands) > 0 { 726 shorthands, a, err = f.parseSingleShortArg(shorthands, args) 727 if err != nil { 728 return 729 } 730 } 731 732 return 733} 734 735func (f *FlagSet) parseArgs(args []string) (err error) { 736 for len(args) > 0 { 737 s := args[0] 738 args = args[1:] 739 if len(s) == 0 || s[0] != '-' || len(s) == 1 { 740 if !f.interspersed { 741 f.args = append(f.args, s) 742 f.args = append(f.args, args...) 743 return nil 744 } 745 f.args = append(f.args, s) 746 continue 747 } 748 749 if s[1] == '-' { 750 if len(s) == 2 { // "--" terminates the flags 751 f.argsLenAtDash = len(f.args) 752 f.args = append(f.args, args...) 753 break 754 } 755 args, err = f.parseLongArg(s, args) 756 } else { 757 args, err = f.parseShortArg(s, args) 758 } 759 if err != nil { 760 return 761 } 762 } 763 return 764} 765 766// Parse parses flag definitions from the argument list, which should not 767// include the command name. Must be called after all flags in the FlagSet 768// are defined and before flags are accessed by the program. 769// The return value will be ErrHelp if -help was set but not defined. 770func (f *FlagSet) Parse(arguments []string) error { 771 f.parsed = true 772 f.args = make([]string, 0, len(arguments)) 773 err := f.parseArgs(arguments) 774 if err != nil { 775 switch f.errorHandling { 776 case ContinueOnError: 777 return err 778 case ExitOnError: 779 os.Exit(2) 780 case PanicOnError: 781 panic(err) 782 } 783 } 784 return nil 785} 786 787// Parsed reports whether f.Parse has been called. 788func (f *FlagSet) Parsed() bool { 789 return f.parsed 790} 791 792// Parse parses the command-line flags from os.Args[1:]. Must be called 793// after all flags are defined and before flags are accessed by the program. 794func Parse() { 795 // Ignore errors; CommandLine is set for ExitOnError. 796 CommandLine.Parse(os.Args[1:]) 797} 798 799// SetInterspersed sets whether to support interspersed option/non-option arguments. 800func SetInterspersed(interspersed bool) { 801 CommandLine.SetInterspersed(interspersed) 802} 803 804// Parsed returns true if the command-line flags have been parsed. 805func Parsed() bool { 806 return CommandLine.Parsed() 807} 808 809// The default set of command-line flags, parsed from os.Args. 810var CommandLine = NewFlagSet(os.Args[0], ExitOnError) 811 812// NewFlagSet returns a new, empty flag set with the specified name and 813// error handling property. 814func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet { 815 f := &FlagSet{ 816 name: name, 817 errorHandling: errorHandling, 818 argsLenAtDash: -1, 819 interspersed: true, 820 } 821 return f 822} 823 824// SetInterspersed sets whether to support interspersed option/non-option arguments. 825func (f *FlagSet) SetInterspersed(interspersed bool) { 826 f.interspersed = interspersed 827} 828 829// Init sets the name and error handling property for a flag set. 830// By default, the zero FlagSet uses an empty name and the 831// ContinueOnError error handling policy. 832func (f *FlagSet) Init(name string, errorHandling ErrorHandling) { 833 f.name = name 834 f.errorHandling = errorHandling 835 f.argsLenAtDash = -1 836} 837