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