github.com/weaveworks/common@v0.0.0-20230728070032-dd9e68f319d5/mflag/flag.go (about) 1 // Copyright 2014-2016 The Docker & 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 // Package mflag implements command-line flag parsing. 6 // 7 // Usage: 8 // 9 // Define flags using flag.String(), Bool(), Int(), etc. 10 // 11 // This declares an integer flag, -f or --flagname, stored in the pointer ip, with type *int. 12 // import flag "github.com/docker/docker/pkg/mflag" 13 // var ip = flag.Int([]string{"f", "-flagname"}, 1234, "help message for flagname") 14 // If you like, you can bind the flag to a variable using the Var() functions. 15 // var flagvar int 16 // func init() { 17 // // -flaghidden will work, but will be hidden from the usage 18 // flag.IntVar(&flagvar, []string{"f", "#flaghidden", "-flagname"}, 1234, "help message for flagname") 19 // } 20 // Or you can create custom flags that satisfy the Value interface (with 21 // pointer receivers) and couple them to flag parsing by 22 // flag.Var(&flagVal, []string{"name"}, "help message for flagname") 23 // For such flags, the default value is just the initial value of the variable. 24 // 25 // You can also add "deprecated" flags, they are still usable, but are not shown 26 // in the usage and will display a warning when you try to use them. `#` before 27 // an option means this option is deprecated, if there is a following option 28 // without `#` ahead, then that's the replacement, if not, it will just be removed: 29 // var ip = flag.Int([]string{"#f", "#flagname", "-flagname"}, 1234, "help message for flagname") 30 // this will display: `Warning: '-f' is deprecated, it will be replaced by '--flagname' soon. See usage.` or 31 // this will display: `Warning: '-flagname' is deprecated, it will be replaced by '--flagname' soon. See usage.` 32 // var ip = flag.Int([]string{"f", "#flagname"}, 1234, "help message for flagname") 33 // will display: `Warning: '-flagname' is deprecated, it will be removed soon. See usage.` 34 // so you can only use `-f`. 35 // 36 // You can also group one letter flags, if you declare 37 // var v = flag.Bool([]string{"v", "-verbose"}, false, "help message for verbose") 38 // var s = flag.Bool([]string{"s", "-slow"}, false, "help message for slow") 39 // you will be able to use the -vs or -sv 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 // Command line flag syntax: 55 // -flag 56 // -flag=x 57 // -flag="x" 58 // -flag='x' 59 // -flag x // non-boolean flags only 60 // One or two minus signs may be used; they are equivalent. 61 // The last form is not permitted for boolean flags because the 62 // meaning of the command 63 // cmd -x * 64 // will change if there is a file called 0, false, etc. You must 65 // use the -flag=false form to turn off a boolean flag. 66 // 67 // Flag parsing stops just before the first non-flag argument 68 // ("-" is a non-flag argument) or after the terminator "--". 69 // 70 // Integer flags accept 1234, 0664, 0x1234 and may be negative. 71 // Boolean flags may be 1, 0, t, f, true, false, TRUE, FALSE, True, False. 72 // Duration flags accept any input valid for time.ParseDuration. 73 // 74 // The default set of command-line flags is controlled by 75 // top-level functions. The FlagSet type allows one to define 76 // independent sets of flags, such as to implement subcommands 77 // in a command-line interface. The methods of FlagSet are 78 // analogous to the top-level functions for the command-line 79 // flag set. 80 81 package mflag 82 83 import ( 84 "errors" 85 "fmt" 86 "io" 87 "os" 88 "sort" 89 "strconv" 90 "strings" 91 "text/tabwriter" 92 "time" 93 ) 94 95 // ErrHelp is the error returned if the flag -help is invoked but no such flag is defined. 96 var ErrHelp = errors.New("flag: help requested") 97 98 // ErrRetry is the error returned if you need to try letter by letter 99 var ErrRetry = errors.New("flag: retry") 100 101 // -- bool Value 102 type boolValue bool 103 104 func newBoolValue(val bool, p *bool) *boolValue { 105 *p = val 106 return (*boolValue)(p) 107 } 108 109 func (b *boolValue) Set(s string) error { 110 v, err := strconv.ParseBool(s) 111 *b = boolValue(v) 112 return err 113 } 114 115 func (b *boolValue) Get() interface{} { return bool(*b) } 116 117 func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) } 118 119 func (b *boolValue) IsBoolFlag() bool { return true } 120 121 // optional interface to indicate boolean flags that can be 122 // supplied without "=value" text 123 type boolFlag interface { 124 Value 125 IsBoolFlag() bool 126 } 127 128 // -- int Value 129 type intValue int 130 131 func newIntValue(val int, p *int) *intValue { 132 *p = val 133 return (*intValue)(p) 134 } 135 136 func (i *intValue) Set(s string) error { 137 v, err := strconv.ParseInt(s, 0, 64) 138 *i = intValue(v) 139 return err 140 } 141 142 func (i *intValue) Get() interface{} { return int(*i) } 143 144 func (i *intValue) String() string { return fmt.Sprintf("%v", *i) } 145 146 // -- int64 Value 147 type int64Value int64 148 149 func newInt64Value(val int64, p *int64) *int64Value { 150 *p = val 151 return (*int64Value)(p) 152 } 153 154 func (i *int64Value) Set(s string) error { 155 v, err := strconv.ParseInt(s, 0, 64) 156 *i = int64Value(v) 157 return err 158 } 159 160 func (i *int64Value) Get() interface{} { return int64(*i) } 161 162 func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) } 163 164 // -- uint Value 165 type uintValue uint 166 167 func newUintValue(val uint, p *uint) *uintValue { 168 *p = val 169 return (*uintValue)(p) 170 } 171 172 func (i *uintValue) Set(s string) error { 173 v, err := strconv.ParseUint(s, 0, 64) 174 *i = uintValue(v) 175 return err 176 } 177 178 func (i *uintValue) Get() interface{} { return uint(*i) } 179 180 func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) } 181 182 // -- uint64 Value 183 type uint64Value uint64 184 185 func newUint64Value(val uint64, p *uint64) *uint64Value { 186 *p = val 187 return (*uint64Value)(p) 188 } 189 190 func (i *uint64Value) Set(s string) error { 191 v, err := strconv.ParseUint(s, 0, 64) 192 *i = uint64Value(v) 193 return err 194 } 195 196 func (i *uint64Value) Get() interface{} { return uint64(*i) } 197 198 func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) } 199 200 // -- uint16 Value 201 type uint16Value uint16 202 203 func newUint16Value(val uint16, p *uint16) *uint16Value { 204 *p = val 205 return (*uint16Value)(p) 206 } 207 208 func (i *uint16Value) Set(s string) error { 209 v, err := strconv.ParseUint(s, 0, 16) 210 *i = uint16Value(v) 211 return err 212 } 213 214 func (i *uint16Value) Get() interface{} { return uint16(*i) } 215 216 func (i *uint16Value) String() string { return fmt.Sprintf("%v", *i) } 217 218 // -- string Value 219 type stringValue string 220 221 func newStringValue(val string, p *string) *stringValue { 222 *p = val 223 return (*stringValue)(p) 224 } 225 226 func (s *stringValue) Set(val string) error { 227 *s = stringValue(val) 228 return nil 229 } 230 231 func (s *stringValue) Get() interface{} { return string(*s) } 232 233 func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) } 234 235 // -- float64 Value 236 type float64Value float64 237 238 func newFloat64Value(val float64, p *float64) *float64Value { 239 *p = val 240 return (*float64Value)(p) 241 } 242 243 func (f *float64Value) Set(s string) error { 244 v, err := strconv.ParseFloat(s, 64) 245 *f = float64Value(v) 246 return err 247 } 248 249 func (f *float64Value) Get() interface{} { return float64(*f) } 250 251 func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) } 252 253 // -- time.Duration Value 254 type durationValue time.Duration 255 256 func newDurationValue(val time.Duration, p *time.Duration) *durationValue { 257 *p = val 258 return (*durationValue)(p) 259 } 260 261 func (d *durationValue) Set(s string) error { 262 v, err := time.ParseDuration(s) 263 *d = durationValue(v) 264 return err 265 } 266 267 func (d *durationValue) Get() interface{} { return time.Duration(*d) } 268 269 func (d *durationValue) String() string { return (*time.Duration)(d).String() } 270 271 // Value is the interface to the dynamic value stored in a flag. 272 // (The default value is represented as a string.) 273 // 274 // If a Value has an IsBoolFlag() bool method returning true, 275 // the command-line parser makes -name equivalent to -name=true 276 // rather than using the next command-line argument. 277 type Value interface { 278 String() string 279 Set(string) error 280 } 281 282 // Getter is an interface that allows the contents of a Value to be retrieved. 283 // It wraps the Value interface, rather than being part of it, because it 284 // appeared after Go 1 and its compatibility rules. All Value types provided 285 // by this package satisfy the Getter interface. 286 type Getter interface { 287 Value 288 Get() interface{} 289 } 290 291 // ErrorHandling defines how to handle flag parsing errors. 292 type ErrorHandling int 293 294 // ErrorHandling strategies available when a flag parsing error occurs 295 const ( 296 ContinueOnError ErrorHandling = iota 297 ExitOnError 298 PanicOnError 299 ) 300 301 // A FlagSet represents a set of defined flags. The zero value of a FlagSet 302 // has no name and has ContinueOnError error handling. 303 type FlagSet struct { 304 // Usage is the function called when an error occurs while parsing flags. 305 // The field is a function (not a method) that may be changed to point to 306 // a custom error handler. 307 Usage func() 308 ShortUsage func() 309 310 name string 311 parsed bool 312 actual map[string]*Flag 313 formal map[string]*Flag 314 args []string // arguments after flags 315 errorHandling ErrorHandling 316 output io.Writer // nil means stderr; use Out() accessor 317 nArgRequirements []nArgRequirement 318 } 319 320 // A Flag represents the state of a flag. 321 type Flag struct { 322 Names []string // name as it appears on command line 323 Usage string // help message 324 Value Value // value as set 325 DefValue string // default value (as text); for usage message 326 } 327 328 type flagSlice []string 329 330 func (p flagSlice) Len() int { return len(p) } 331 func (p flagSlice) Less(i, j int) bool { 332 pi, pj := strings.TrimPrefix(p[i], "-"), strings.TrimPrefix(p[j], "-") 333 lpi, lpj := strings.ToLower(pi), strings.ToLower(pj) 334 if lpi != lpj { 335 return lpi < lpj 336 } 337 return pi < pj 338 } 339 func (p flagSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 340 341 // sortFlags returns the flags as a slice in lexicographical sorted order. 342 func sortFlags(flags map[string]*Flag) []*Flag { 343 var list flagSlice 344 345 // The sorted list is based on the first name, when flag map might use the other names. 346 nameMap := make(map[string]string) 347 348 for n, f := range flags { 349 fName := strings.TrimPrefix(f.Names[0], "#") 350 nameMap[fName] = n 351 if len(f.Names) == 1 { 352 list = append(list, fName) 353 continue 354 } 355 356 found := false 357 for _, name := range list { 358 if name == fName { 359 found = true 360 break 361 } 362 } 363 if !found { 364 list = append(list, fName) 365 } 366 } 367 sort.Sort(list) 368 result := make([]*Flag, len(list)) 369 for i, name := range list { 370 result[i] = flags[nameMap[name]] 371 } 372 return result 373 } 374 375 // Name returns the name of the FlagSet. 376 func (fs *FlagSet) Name() string { 377 return fs.name 378 } 379 380 // Out returns the destination for usage and error messages. 381 func (fs *FlagSet) Out() io.Writer { 382 if fs.output == nil { 383 return os.Stderr 384 } 385 return fs.output 386 } 387 388 // SetOutput sets the destination for usage and error messages. 389 // If output is nil, os.Stderr is used. 390 func (fs *FlagSet) SetOutput(output io.Writer) { 391 fs.output = output 392 } 393 394 // VisitAll visits the flags in lexicographical order, calling fn for each. 395 // It visits all flags, even those not set. 396 func (fs *FlagSet) VisitAll(fn func(*Flag)) { 397 for _, flag := range sortFlags(fs.formal) { 398 fn(flag) 399 } 400 } 401 402 // VisitAll visits the command-line flags in lexicographical order, calling 403 // fn for each. It visits all flags, even those not set. 404 func VisitAll(fn func(*Flag)) { 405 CommandLine.VisitAll(fn) 406 } 407 408 // Visit visits the flags in lexicographical order, calling fn for each. 409 // It visits only those flags that have been set. 410 func (fs *FlagSet) Visit(fn func(*Flag)) { 411 for _, flag := range sortFlags(fs.actual) { 412 fn(flag) 413 } 414 } 415 416 // Visit visits the command-line flags in lexicographical order, calling fn 417 // for each. It visits only those flags that have been set. 418 func Visit(fn func(*Flag)) { 419 CommandLine.Visit(fn) 420 } 421 422 // Lookup returns the Flag structure of the named flag, returning nil if none exists. 423 func (fs *FlagSet) Lookup(name string) *Flag { 424 return fs.formal[name] 425 } 426 427 // IsSet indicates whether the specified flag is set in the given FlagSet 428 func (fs *FlagSet) IsSet(name string) bool { 429 return fs.actual[name] != nil 430 } 431 432 // Lookup returns the Flag structure of the named command-line flag, 433 // returning nil if none exists. 434 func Lookup(name string) *Flag { 435 return CommandLine.formal[name] 436 } 437 438 // IsSet indicates whether the specified flag was specified at all on the cmd line. 439 func IsSet(name string) bool { 440 return CommandLine.IsSet(name) 441 } 442 443 type nArgRequirementType int 444 445 // Indicator used to pass to BadArgs function 446 const ( 447 Exact nArgRequirementType = iota 448 Max 449 Min 450 ) 451 452 type nArgRequirement struct { 453 Type nArgRequirementType 454 N int 455 } 456 457 // Require adds a requirement about the number of arguments for the FlagSet. 458 // The first parameter can be Exact, Max, or Min to respectively specify the exact, 459 // the maximum, or the minimal number of arguments required. 460 // The actual check is done in FlagSet.CheckArgs(). 461 func (fs *FlagSet) Require(nArgRequirementType nArgRequirementType, nArg int) { 462 fs.nArgRequirements = append(fs.nArgRequirements, nArgRequirement{nArgRequirementType, nArg}) 463 } 464 465 // CheckArgs uses the requirements set by FlagSet.Require() to validate 466 // the number of arguments. If the requirements are not met, 467 // an error message string is returned. 468 func (fs *FlagSet) CheckArgs() (message string) { 469 for _, req := range fs.nArgRequirements { 470 var arguments string 471 if req.N == 1 { 472 arguments = "1 argument" 473 } else { 474 arguments = fmt.Sprintf("%d arguments", req.N) 475 } 476 477 str := func(kind string) string { 478 return fmt.Sprintf("%q requires %s%s", fs.name, kind, arguments) 479 } 480 481 switch req.Type { 482 case Exact: 483 if fs.NArg() != req.N { 484 return str("") 485 } 486 case Max: 487 if fs.NArg() > req.N { 488 return str("a maximum of ") 489 } 490 case Min: 491 if fs.NArg() < req.N { 492 return str("a minimum of ") 493 } 494 } 495 } 496 return "" 497 } 498 499 // Set sets the value of the named flag. 500 func (fs *FlagSet) Set(name, value string) error { 501 flag, ok := fs.formal[name] 502 if !ok { 503 return fmt.Errorf("no such flag -%v", name) 504 } 505 if err := flag.Value.Set(value); err != nil { 506 return err 507 } 508 if fs.actual == nil { 509 fs.actual = make(map[string]*Flag) 510 } 511 fs.actual[name] = flag 512 return nil 513 } 514 515 // Set sets the value of the named command-line flag. 516 func Set(name, value string) error { 517 return CommandLine.Set(name, value) 518 } 519 520 // isZeroValue guesses whether the string represents the zero 521 // value for a flag. It is not accurate but in practice works OK. 522 func isZeroValue(value string) bool { 523 switch value { 524 case "false": 525 return true 526 case "": 527 return true 528 case "0": 529 return true 530 } 531 return false 532 } 533 534 // PrintDefaults prints, to standard error unless configured 535 // otherwise, the default values of all defined flags in the set. 536 func (fs *FlagSet) PrintDefaults() { 537 writer := tabwriter.NewWriter(fs.Out(), 20, 1, 3, ' ', 0) 538 539 // Add a blank line between cmd description and list of options 540 if fs.FlagCount() > 0 { 541 fmt.Fprintln(writer, "") 542 } 543 544 fs.VisitAll(func(flag *Flag) { 545 names := []string{} 546 for _, name := range flag.Names { 547 if name[0] != '#' { 548 names = append(names, name) 549 } 550 } 551 if len(names) > 0 && len(flag.Usage) > 0 { 552 val := flag.DefValue 553 554 if isZeroValue(val) { 555 format := " -%s" 556 fmt.Fprintf(writer, format, strings.Join(names, ", -")) 557 } else { 558 format := " -%s=%s" 559 fmt.Fprintf(writer, format, strings.Join(names, ", -"), val) 560 } 561 for _, line := range strings.Split(flag.Usage, "\n") { 562 fmt.Fprintln(writer, "\t", line) 563 } 564 } 565 }) 566 writer.Flush() 567 } 568 569 // PrintDefaults prints to standard error the default values of all defined command-line flags. 570 func PrintDefaults() { 571 CommandLine.PrintDefaults() 572 } 573 574 // defaultUsage is the default function to print a usage message. 575 func defaultUsage(fs *FlagSet) { 576 if fs.name == "" { 577 fmt.Fprintf(fs.Out(), "Usage:\n") 578 } else { 579 fmt.Fprintf(fs.Out(), "Usage of %s:\n", fs.name) 580 } 581 fs.PrintDefaults() 582 } 583 584 // NOTE: Usage is not just defaultUsage(CommandLine) 585 // because it serves (via godoc flag Usage) as the example 586 // for how to write your own usage function. 587 588 // Usage prints to standard error a usage message documenting all defined command-line flags. 589 // The function is a variable that may be changed to point to a custom function. 590 var Usage = func() { 591 fmt.Fprintf(CommandLine.Out(), "Usage of %s:\n", os.Args[0]) 592 PrintDefaults() 593 } 594 595 // ShortUsage prints to standard error a usage message documenting the standard command layout 596 // The function is a variable that may be changed to point to a custom function. 597 var ShortUsage = func() { 598 fmt.Fprintf(CommandLine.output, "Usage of %s:\n", os.Args[0]) 599 } 600 601 // FlagCount returns the number of flags that have been defined. 602 func (fs *FlagSet) FlagCount() int { return len(sortFlags(fs.formal)) } 603 604 // FlagCountUndeprecated returns the number of undeprecated flags that have been defined. 605 func (fs *FlagSet) FlagCountUndeprecated() int { 606 count := 0 607 for _, flag := range sortFlags(fs.formal) { 608 for _, name := range flag.Names { 609 if name[0] != '#' { 610 count++ 611 break 612 } 613 } 614 } 615 return count 616 } 617 618 // NFlag returns the number of flags that have been set. 619 func (fs *FlagSet) NFlag() int { return len(fs.actual) } 620 621 // NFlag returns the number of command-line flags that have been set. 622 func NFlag() int { return len(CommandLine.actual) } 623 624 // Arg returns the i'th argument. Arg(0) is the first remaining argument 625 // after flags have been processed. 626 func (fs *FlagSet) Arg(i int) string { 627 if i < 0 || i >= len(fs.args) { 628 return "" 629 } 630 return fs.args[i] 631 } 632 633 // Arg returns the i'th command-line argument. Arg(0) is the first remaining argument 634 // after flags have been processed. 635 func Arg(i int) string { 636 return CommandLine.Arg(i) 637 } 638 639 // NArg is the number of arguments remaining after flags have been processed. 640 func (fs *FlagSet) NArg() int { return len(fs.args) } 641 642 // NArg is the number of arguments remaining after flags have been processed. 643 func NArg() int { return len(CommandLine.args) } 644 645 // Args returns the non-flag arguments. 646 func (fs *FlagSet) Args() []string { return fs.args } 647 648 // Args returns the non-flag command-line arguments. 649 func Args() []string { return CommandLine.args } 650 651 // BoolVar defines a bool flag with specified name, default value, and usage string. 652 // The argument p points to a bool variable in which to store the value of the flag. 653 func (fs *FlagSet) BoolVar(p *bool, names []string, value bool, usage string) { 654 fs.Var(newBoolValue(value, p), names, usage) 655 } 656 657 // BoolVar defines a bool flag with specified name, default value, and usage string. 658 // The argument p points to a bool variable in which to store the value of the flag. 659 func BoolVar(p *bool, names []string, value bool, usage string) { 660 CommandLine.Var(newBoolValue(value, p), names, usage) 661 } 662 663 // Bool defines a bool flag with specified name, default value, and usage string. 664 // The return value is the address of a bool variable that stores the value of the flag. 665 func (fs *FlagSet) Bool(names []string, value bool, usage string) *bool { 666 p := new(bool) 667 fs.BoolVar(p, names, value, usage) 668 return p 669 } 670 671 // Bool defines a bool flag with specified name, default value, and usage string. 672 // The return value is the address of a bool variable that stores the value of the flag. 673 func Bool(names []string, value bool, usage string) *bool { 674 return CommandLine.Bool(names, value, usage) 675 } 676 677 // IntVar defines an int flag with specified name, default value, and usage string. 678 // The argument p points to an int variable in which to store the value of the flag. 679 func (fs *FlagSet) IntVar(p *int, names []string, value int, usage string) { 680 fs.Var(newIntValue(value, p), names, usage) 681 } 682 683 // IntVar defines an int flag with specified name, default value, and usage string. 684 // The argument p points to an int variable in which to store the value of the flag. 685 func IntVar(p *int, names []string, value int, usage string) { 686 CommandLine.Var(newIntValue(value, p), names, usage) 687 } 688 689 // Int defines an int flag with specified name, default value, and usage string. 690 // The return value is the address of an int variable that stores the value of the flag. 691 func (fs *FlagSet) Int(names []string, value int, usage string) *int { 692 p := new(int) 693 fs.IntVar(p, names, value, usage) 694 return p 695 } 696 697 // Int defines an int flag with specified name, default value, and usage string. 698 // The return value is the address of an int variable that stores the value of the flag. 699 func Int(names []string, value int, usage string) *int { 700 return CommandLine.Int(names, value, usage) 701 } 702 703 // Int64Var defines an int64 flag with specified name, default value, and usage string. 704 // The argument p points to an int64 variable in which to store the value of the flag. 705 func (fs *FlagSet) Int64Var(p *int64, names []string, value int64, usage string) { 706 fs.Var(newInt64Value(value, p), names, usage) 707 } 708 709 // Int64Var defines an int64 flag with specified name, default value, and usage string. 710 // The argument p points to an int64 variable in which to store the value of the flag. 711 func Int64Var(p *int64, names []string, value int64, usage string) { 712 CommandLine.Var(newInt64Value(value, p), names, usage) 713 } 714 715 // Int64 defines an int64 flag with specified name, default value, and usage string. 716 // The return value is the address of an int64 variable that stores the value of the flag. 717 func (fs *FlagSet) Int64(names []string, value int64, usage string) *int64 { 718 p := new(int64) 719 fs.Int64Var(p, names, value, usage) 720 return p 721 } 722 723 // Int64 defines an int64 flag with specified name, default value, and usage string. 724 // The return value is the address of an int64 variable that stores the value of the flag. 725 func Int64(names []string, value int64, usage string) *int64 { 726 return CommandLine.Int64(names, value, usage) 727 } 728 729 // UintVar defines a uint flag with specified name, default value, and usage string. 730 // The argument p points to a uint variable in which to store the value of the flag. 731 func (fs *FlagSet) UintVar(p *uint, names []string, value uint, usage string) { 732 fs.Var(newUintValue(value, p), names, usage) 733 } 734 735 // UintVar defines a uint flag with specified name, default value, and usage string. 736 // The argument p points to a uint variable in which to store the value of the flag. 737 func UintVar(p *uint, names []string, value uint, usage string) { 738 CommandLine.Var(newUintValue(value, p), names, usage) 739 } 740 741 // Uint defines a uint flag with specified name, default value, and usage string. 742 // The return value is the address of a uint variable that stores the value of the flag. 743 func (fs *FlagSet) Uint(names []string, value uint, usage string) *uint { 744 p := new(uint) 745 fs.UintVar(p, names, value, usage) 746 return p 747 } 748 749 // Uint defines a uint flag with specified name, default value, and usage string. 750 // The return value is the address of a uint variable that stores the value of the flag. 751 func Uint(names []string, value uint, usage string) *uint { 752 return CommandLine.Uint(names, value, usage) 753 } 754 755 // Uint64Var defines a uint64 flag with specified name, default value, and usage string. 756 // The argument p points to a uint64 variable in which to store the value of the flag. 757 func (fs *FlagSet) Uint64Var(p *uint64, names []string, value uint64, usage string) { 758 fs.Var(newUint64Value(value, p), names, usage) 759 } 760 761 // Uint64Var defines a uint64 flag with specified name, default value, and usage string. 762 // The argument p points to a uint64 variable in which to store the value of the flag. 763 func Uint64Var(p *uint64, names []string, value uint64, usage string) { 764 CommandLine.Var(newUint64Value(value, p), names, usage) 765 } 766 767 // Uint64 defines a uint64 flag with specified name, default value, and usage string. 768 // The return value is the address of a uint64 variable that stores the value of the flag. 769 func (fs *FlagSet) Uint64(names []string, value uint64, usage string) *uint64 { 770 p := new(uint64) 771 fs.Uint64Var(p, names, value, usage) 772 return p 773 } 774 775 // Uint64 defines a uint64 flag with specified name, default value, and usage string. 776 // The return value is the address of a uint64 variable that stores the value of the flag. 777 func Uint64(names []string, value uint64, usage string) *uint64 { 778 return CommandLine.Uint64(names, value, usage) 779 } 780 781 // Uint16Var defines a uint16 flag with specified name, default value, and usage string. 782 // The argument p points to a uint16 variable in which to store the value of the flag. 783 func (fs *FlagSet) Uint16Var(p *uint16, names []string, value uint16, usage string) { 784 fs.Var(newUint16Value(value, p), names, usage) 785 } 786 787 // Uint16Var defines a uint16 flag with specified name, default value, and usage string. 788 // The argument p points to a uint16 variable in which to store the value of the flag. 789 func Uint16Var(p *uint16, names []string, value uint16, usage string) { 790 CommandLine.Var(newUint16Value(value, p), names, usage) 791 } 792 793 // Uint16 defines a uint16 flag with specified name, default value, and usage string. 794 // The return value is the address of a uint16 variable that stores the value of the flag. 795 func (fs *FlagSet) Uint16(names []string, value uint16, usage string) *uint16 { 796 p := new(uint16) 797 fs.Uint16Var(p, names, value, usage) 798 return p 799 } 800 801 // Uint16 defines a uint16 flag with specified name, default value, and usage string. 802 // The return value is the address of a uint16 variable that stores the value of the flag. 803 func Uint16(names []string, value uint16, usage string) *uint16 { 804 return CommandLine.Uint16(names, value, usage) 805 } 806 807 // StringVar defines a string flag with specified name, default value, and usage string. 808 // The argument p points to a string variable in which to store the value of the flag. 809 func (fs *FlagSet) StringVar(p *string, names []string, value string, usage string) { 810 fs.Var(newStringValue(value, p), names, usage) 811 } 812 813 // StringVar defines a string flag with specified name, default value, and usage string. 814 // The argument p points to a string variable in which to store the value of the flag. 815 func StringVar(p *string, names []string, value string, usage string) { 816 CommandLine.Var(newStringValue(value, p), names, usage) 817 } 818 819 // String defines a string flag with specified name, default value, and usage string. 820 // The return value is the address of a string variable that stores the value of the flag. 821 func (fs *FlagSet) String(names []string, value string, usage string) *string { 822 p := new(string) 823 fs.StringVar(p, names, value, usage) 824 return p 825 } 826 827 // String defines a string flag with specified name, default value, and usage string. 828 // The return value is the address of a string variable that stores the value of the flag. 829 func String(names []string, value string, usage string) *string { 830 return CommandLine.String(names, value, usage) 831 } 832 833 // Float64Var defines a float64 flag with specified name, default value, and usage string. 834 // The argument p points to a float64 variable in which to store the value of the flag. 835 func (fs *FlagSet) Float64Var(p *float64, names []string, value float64, usage string) { 836 fs.Var(newFloat64Value(value, p), names, usage) 837 } 838 839 // Float64Var defines a float64 flag with specified name, default value, and usage string. 840 // The argument p points to a float64 variable in which to store the value of the flag. 841 func Float64Var(p *float64, names []string, value float64, usage string) { 842 CommandLine.Var(newFloat64Value(value, p), names, usage) 843 } 844 845 // Float64 defines a float64 flag with specified name, default value, and usage string. 846 // The return value is the address of a float64 variable that stores the value of the flag. 847 func (fs *FlagSet) Float64(names []string, value float64, usage string) *float64 { 848 p := new(float64) 849 fs.Float64Var(p, names, value, usage) 850 return p 851 } 852 853 // Float64 defines a float64 flag with specified name, default value, and usage string. 854 // The return value is the address of a float64 variable that stores the value of the flag. 855 func Float64(names []string, value float64, usage string) *float64 { 856 return CommandLine.Float64(names, value, usage) 857 } 858 859 // DurationVar defines a time.Duration flag with specified name, default value, and usage string. 860 // The argument p points to a time.Duration variable in which to store the value of the flag. 861 func (fs *FlagSet) DurationVar(p *time.Duration, names []string, value time.Duration, usage string) { 862 fs.Var(newDurationValue(value, p), names, usage) 863 } 864 865 // DurationVar defines a time.Duration flag with specified name, default value, and usage string. 866 // The argument p points to a time.Duration variable in which to store the value of the flag. 867 func DurationVar(p *time.Duration, names []string, value time.Duration, usage string) { 868 CommandLine.Var(newDurationValue(value, p), names, usage) 869 } 870 871 // Duration defines a time.Duration flag with specified name, default value, and usage string. 872 // The return value is the address of a time.Duration variable that stores the value of the flag. 873 func (fs *FlagSet) Duration(names []string, value time.Duration, usage string) *time.Duration { 874 p := new(time.Duration) 875 fs.DurationVar(p, names, value, usage) 876 return p 877 } 878 879 // Duration defines a time.Duration flag with specified name, default value, and usage string. 880 // The return value is the address of a time.Duration variable that stores the value of the flag. 881 func Duration(names []string, value time.Duration, usage string) *time.Duration { 882 return CommandLine.Duration(names, value, usage) 883 } 884 885 // Var defines a flag with the specified name and usage string. The type and 886 // value of the flag are represented by the first argument, of type Value, which 887 // typically holds a user-defined implementation of Value. For instance, the 888 // caller could create a flag that turns a comma-separated string into a slice 889 // of strings by giving the slice the methods of Value; in particular, Set would 890 // decompose the comma-separated string into the slice. 891 func (fs *FlagSet) Var(value Value, names []string, usage string) { 892 // Remember the default value as a string; it won't change. 893 flag := &Flag{names, usage, value, value.String()} 894 for _, name := range names { 895 name = strings.TrimPrefix(name, "#") 896 _, alreadythere := fs.formal[name] 897 if alreadythere { 898 var msg string 899 if fs.name == "" { 900 msg = fmt.Sprintf("flag redefined: %s", name) 901 } else { 902 msg = fmt.Sprintf("%s flag redefined: %s", fs.name, name) 903 } 904 fmt.Fprintln(fs.Out(), msg) 905 panic(msg) // Happens only if flags are declared with identical names 906 } 907 if fs.formal == nil { 908 fs.formal = make(map[string]*Flag) 909 } 910 fs.formal[name] = flag 911 } 912 } 913 914 // Var defines a flag with the specified name and usage string. The type and 915 // value of the flag are represented by the first argument, of type Value, which 916 // typically holds a user-defined implementation of Value. For instance, the 917 // caller could create a flag that turns a comma-separated string into a slice 918 // of strings by giving the slice the methods of Value; in particular, Set would 919 // decompose the comma-separated string into the slice. 920 func Var(value Value, names []string, usage string) { 921 CommandLine.Var(value, names, usage) 922 } 923 924 // failf prints to standard error a formatted error and usage message and 925 // returns the error. 926 func (fs *FlagSet) failf(format string, a ...interface{}) error { 927 err := fmt.Errorf(format, a...) 928 fmt.Fprintln(fs.Out(), err) 929 if os.Args[0] == fs.name { 930 fmt.Fprintf(fs.Out(), "See '%s --help'.\n", os.Args[0]) 931 } else { 932 fmt.Fprintf(fs.Out(), "See '%s %s --help'.\n", os.Args[0], fs.name) 933 } 934 return err 935 } 936 937 // usage calls the Usage method for the flag set, or the usage function if 938 // the flag set is CommandLine. 939 func (fs *FlagSet) usage() { 940 if fs == CommandLine { 941 Usage() 942 } else if fs.Usage == nil { 943 defaultUsage(fs) 944 } else { 945 fs.Usage() 946 } 947 } 948 949 func trimQuotes(str string) string { 950 if len(str) == 0 { 951 return str 952 } 953 type quote struct { 954 start, end byte 955 } 956 957 // All valid quote types. 958 quotes := []quote{ 959 // Double quotes 960 { 961 start: '"', 962 end: '"', 963 }, 964 965 // Single quotes 966 { 967 start: '\'', 968 end: '\'', 969 }, 970 } 971 972 for _, quote := range quotes { 973 // Only strip if outermost match. 974 if str[0] == quote.start && str[len(str)-1] == quote.end { 975 str = str[1 : len(str)-1] 976 break 977 } 978 } 979 980 return str 981 } 982 983 // parseOne parses one flag. It reports whether a flag was seen. 984 func (fs *FlagSet) parseOne() (bool, string, error) { 985 if len(fs.args) == 0 { 986 return false, "", nil 987 } 988 s := fs.args[0] 989 if len(s) == 0 || s[0] != '-' || len(s) == 1 { 990 return false, "", nil 991 } 992 if s[1] == '-' && len(s) == 2 { // "--" terminates the flags 993 fs.args = fs.args[1:] 994 return false, "", nil 995 } 996 name := s[1:] 997 if len(name) == 0 || name[0] == '=' { 998 return false, "", fs.failf("bad flag syntax: %s", s) 999 } 1000 1001 // it's a flag. does it have an argument? 1002 fs.args = fs.args[1:] 1003 hasValue := false 1004 value := "" 1005 if i := strings.Index(name, "="); i != -1 { 1006 value = trimQuotes(name[i+1:]) 1007 hasValue = true 1008 name = name[:i] 1009 } 1010 1011 m := fs.formal 1012 flag, alreadythere := m[name] // BUG 1013 if !alreadythere { 1014 if name == "-help" || name == "help" || name == "h" { // special case for nice help message. 1015 fs.usage() 1016 return false, "", ErrHelp 1017 } 1018 if len(name) > 0 && name[0] == '-' { 1019 return false, "", fs.failf("flag provided but not defined: -%s", name) 1020 } 1021 return false, name, ErrRetry 1022 } 1023 if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg 1024 if hasValue { 1025 if err := fv.Set(value); err != nil { 1026 return false, "", fs.failf("invalid boolean value %q for -%s: %v", value, name, err) 1027 } 1028 } else { 1029 fv.Set("true") 1030 } 1031 } else { 1032 // It must have a value, which might be the next argument. 1033 if !hasValue && len(fs.args) > 0 { 1034 // value is the next arg 1035 hasValue = true 1036 value, fs.args = fs.args[0], fs.args[1:] 1037 } 1038 if !hasValue { 1039 return false, "", fs.failf("flag needs an argument: -%s", name) 1040 } 1041 if err := flag.Value.Set(value); err != nil { 1042 return false, "", fs.failf("invalid value %q for flag -%s: %v", value, name, err) 1043 } 1044 } 1045 if fs.actual == nil { 1046 fs.actual = make(map[string]*Flag) 1047 } 1048 fs.actual[name] = flag 1049 for i, n := range flag.Names { 1050 if n == fmt.Sprintf("#%s", name) { 1051 replacement := "" 1052 for j := i; j < len(flag.Names); j++ { 1053 if flag.Names[j][0] != '#' { 1054 replacement = flag.Names[j] 1055 break 1056 } 1057 } 1058 if replacement != "" { 1059 fmt.Fprintf(fs.Out(), "Warning: '-%s' is deprecated, it will be replaced by '-%s' soon. See usage.\n", name, replacement) 1060 } else { 1061 fmt.Fprintf(fs.Out(), "Warning: '-%s' is deprecated, it will be removed soon. See usage.\n", name) 1062 } 1063 } 1064 } 1065 return true, "", nil 1066 } 1067 1068 // Parse parses flag definitions from the argument list, which should not 1069 // include the command name. Must be called after all flags in the FlagSet 1070 // are defined and before flags are accessed by the program. 1071 // The return value will be ErrHelp if -help was set but not defined. 1072 func (fs *FlagSet) Parse(arguments []string) error { 1073 fs.parsed = true 1074 fs.args = arguments 1075 for { 1076 seen, name, err := fs.parseOne() 1077 if seen { 1078 continue 1079 } 1080 if err == nil { 1081 break 1082 } 1083 if err == ErrRetry { 1084 if len(name) > 1 { 1085 err = nil 1086 for _, letter := range strings.Split(name, "") { 1087 fs.args = append([]string{"-" + letter}, fs.args...) 1088 seen2, _, err2 := fs.parseOne() 1089 if seen2 { 1090 continue 1091 } 1092 if err2 != nil { 1093 err = fs.failf("flag provided but not defined: -%s", name) 1094 break 1095 } 1096 } 1097 if err == nil { 1098 continue 1099 } 1100 } else { 1101 err = fs.failf("flag provided but not defined: -%s", name) 1102 } 1103 } 1104 switch fs.errorHandling { 1105 case ContinueOnError: 1106 return err 1107 case ExitOnError: 1108 os.Exit(125) 1109 case PanicOnError: 1110 panic(err) 1111 } 1112 } 1113 return nil 1114 } 1115 1116 // ParseFlags is a utility function that adds a help flag if withHelp is true, 1117 // calls fs.Parse(args) and prints a relevant error message if there are 1118 // incorrect number of arguments. It returns error only if error handling is 1119 // set to ContinueOnError and parsing fails. If error handling is set to 1120 // ExitOnError, it's safe to ignore the return value. 1121 func (fs *FlagSet) ParseFlags(args []string, withHelp bool) error { 1122 var help *bool 1123 if withHelp { 1124 help = fs.Bool([]string{"#help", "-help"}, false, "Print usage") 1125 } 1126 if err := fs.Parse(args); err != nil { 1127 return err 1128 } 1129 if help != nil && *help { 1130 fs.SetOutput(os.Stdout) 1131 fs.Usage() 1132 os.Exit(0) 1133 } 1134 if str := fs.CheckArgs(); str != "" { 1135 fs.SetOutput(os.Stderr) 1136 fs.ReportError(str, withHelp) 1137 fs.ShortUsage() 1138 os.Exit(1) 1139 } 1140 return nil 1141 } 1142 1143 // ReportError is a utility method that prints a user-friendly message 1144 // containing the error that occurred during parsing and a suggestion to get help 1145 func (fs *FlagSet) ReportError(str string, withHelp bool) { 1146 if withHelp { 1147 if os.Args[0] == fs.Name() { 1148 str += ".\nSee '" + os.Args[0] + " --help'" 1149 } else { 1150 str += ".\nSee '" + os.Args[0] + " " + fs.Name() + " --help'" 1151 } 1152 } 1153 fmt.Fprintf(fs.Out(), "%s: %s.\n", os.Args[0], str) 1154 } 1155 1156 // Parsed reports whether fs.Parse has been called. 1157 func (fs *FlagSet) Parsed() bool { 1158 return fs.parsed 1159 } 1160 1161 // Parse parses the command-line flags from os.Args[1:]. Must be called 1162 // after all flags are defined and before flags are accessed by the program. 1163 func Parse() { 1164 // Ignore errors; CommandLine is set for ExitOnError. 1165 CommandLine.Parse(os.Args[1:]) 1166 } 1167 1168 // Parsed returns true if the command-line flags have been parsed. 1169 func Parsed() bool { 1170 return CommandLine.Parsed() 1171 } 1172 1173 // CommandLine is the default set of command-line flags, parsed from os.Args. 1174 // The top-level functions such as BoolVar, Arg, and on are wrappers for the 1175 // methods of CommandLine. 1176 var CommandLine = NewFlagSet(os.Args[0], ExitOnError) 1177 1178 // NewFlagSet returns a new, empty flag set with the specified name and 1179 // error handling property. 1180 func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet { 1181 f := &FlagSet{ 1182 name: name, 1183 errorHandling: errorHandling, 1184 } 1185 return f 1186 } 1187 1188 // Init sets the name and error handling property for a flag set. 1189 // By default, the zero FlagSet uses an empty name and the 1190 // ContinueOnError error handling policy. 1191 func (fs *FlagSet) Init(name string, errorHandling ErrorHandling) { 1192 fs.name = name 1193 fs.errorHandling = errorHandling 1194 } 1195 1196 type mergeVal struct { 1197 Value 1198 key string 1199 fset *FlagSet 1200 } 1201 1202 func (v mergeVal) Set(s string) error { 1203 return v.fset.Set(v.key, s) 1204 } 1205 1206 func (v mergeVal) IsBoolFlag() bool { 1207 if b, ok := v.Value.(boolFlag); ok { 1208 return b.IsBoolFlag() 1209 } 1210 return false 1211 } 1212 1213 // Name returns the name of a mergeVal. 1214 // If the original value had a name, return the original name, 1215 // otherwise, return the key asinged to this mergeVal. 1216 func (v mergeVal) Name() string { 1217 type namedValue interface { 1218 Name() string 1219 } 1220 if nVal, ok := v.Value.(namedValue); ok { 1221 return nVal.Name() 1222 } 1223 return v.key 1224 } 1225 1226 // Merge is a helper function that merges n FlagSets into a single dest FlagSet 1227 // In case of name collision between the flagsets it will apply 1228 // the destination FlagSet's errorHandling behavior. 1229 func Merge(dest *FlagSet, flagsets ...*FlagSet) error { 1230 for _, fset := range flagsets { 1231 if fset.formal == nil { 1232 continue 1233 } 1234 for k, f := range fset.formal { 1235 if _, ok := dest.formal[k]; ok { 1236 var err error 1237 if fset.name == "" { 1238 err = fmt.Errorf("flag redefined: %s", k) 1239 } else { 1240 err = fmt.Errorf("%s flag redefined: %s", fset.name, k) 1241 } 1242 fmt.Fprintln(fset.Out(), err.Error()) 1243 // Happens only if flags are declared with identical names 1244 switch dest.errorHandling { 1245 case ContinueOnError: 1246 return err 1247 case ExitOnError: 1248 os.Exit(2) 1249 case PanicOnError: 1250 panic(err) 1251 } 1252 } 1253 newF := *f 1254 newF.Value = mergeVal{f.Value, k, fset} 1255 if dest.formal == nil { 1256 dest.formal = make(map[string]*Flag) 1257 } 1258 dest.formal[k] = &newF 1259 } 1260 } 1261 return nil 1262 } 1263 1264 // IsEmpty reports if the FlagSet is actually empty. 1265 func (fs *FlagSet) IsEmpty() bool { 1266 return len(fs.actual) == 0 1267 }