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