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