github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/fla9/fla9.go (about) 1 /* 2 Package fla9 implements command-line flag parsing. 3 4 Usage: 5 6 Define flags using flag.String(), Bool(), Int(), etc. 7 8 This declares an integer flag, -flagname, stored in the pointer ip, with type *int. 9 10 import "flag" 11 var ip = flag.Int("flagname", 1234, "help message for flagname") 12 13 If you like, you can bind the flag to a variable using the Var() functions. 14 15 var flagvar int 16 func init() { 17 flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname") 18 } 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 23 flag.Var(&flagVal, "name", "help message for flagname") 24 25 For such flags, the default value is just the initial value of the variable. 26 27 After all flags are defined, call 28 29 flag.Parse() 30 31 to parse the command line into the defined flags. 32 33 Flags may then be used directly. If you're using the flags themselves, 34 they are all pointers; if you bind to variables, they're values. 35 36 fmt.Println("ip has value ", *ip) 37 fmt.Println("flagvar has value ", flagvar) 38 39 After parsing, the arguments following the flags are available as the 40 slice flag.Args() or individually as flag.Arg(i). 41 The arguments are indexed from 0 through flag.NArg()-1. 42 43 Command line flag syntax: 44 45 -flag 46 -flag=x 47 -flag x // non-boolean flags only 48 49 One or two minus signs may be used; they are equivalent. 50 The last form is not permitted for boolean flags because the 51 meaning of the command 52 53 cmd -x * 54 55 will change if there is a file called 0, false, etc. You must 56 use the -flag=false form to turn off a boolean flag. 57 58 Flag parsing stops just before the first non-flag argument 59 ("-" is a non-flag argument) or after the terminator "--". 60 61 Integer flags accept 1234, 0664, 0x1234 and may be negative. 62 Boolean flags may be: 63 64 1, 0, t, f, T, F, true, false, TRUE, FALSE, True, False 65 66 Duration flags accept any input valid for time.ParseDuration. 67 68 The default set of command-line flags is controlled by 69 top-level functions. The FlagSet type allows one to define 70 independent sets of flags, such as to implement subcommands 71 in a command-line interface. The methods of FlagSet are 72 analogous to the top-level functions for the command-line 73 flag set. 74 */ 75 package fla9 76 77 import ( 78 "bufio" 79 "errors" 80 "fmt" 81 "io" 82 "io/ioutil" 83 "os" 84 "reflect" 85 "sort" 86 "strconv" 87 "strings" 88 "time" 89 90 "github.com/bingoohuang/gg/pkg/ss" 91 ) 92 93 // ErrHelp is the error returned if the -help or -h flag is invoked 94 // but no such flag is defined. 95 var ErrHelp = errors.New("flag: help requested") 96 97 // -- bool Value 98 type boolValue bool 99 100 func newBoolValue(val bool, p *bool) *boolValue { 101 *p = val 102 return (*boolValue)(p) 103 } 104 105 func (b *boolValue) Set(s string) error { 106 v, err := strconv.ParseBool(s) 107 *b = boolValue(v) 108 return err 109 } 110 111 func (b *boolValue) Get() interface{} { return bool(*b) } 112 func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) } 113 func (b *boolValue) IsBoolFlag() bool { return true } 114 115 // optional interface to indicate boolean flags that can be 116 // supplied without "=value" text 117 type boolFlag interface { 118 Value 119 IsBoolFlag() bool 120 } 121 122 type countValue int 123 124 func newCountValue(val int, p *int) *countValue { 125 *p = val 126 return (*countValue)(p) 127 } 128 129 func (i *countValue) Set(s string) error { 130 *i = countValue(len(s) + 1) 131 return nil 132 } 133 134 func (i *countValue) Get() interface{} { return int(*i) } 135 func (i *countValue) String() string { return fmt.Sprintf("%v", *i) } 136 137 // -- int Value 138 type intValue int 139 140 func newIntValue(val int, p *int) *intValue { 141 *p = val 142 return (*intValue)(p) 143 } 144 145 func (i *intValue) Set(s string) error { 146 v, err := strconv.ParseInt(s, 0, 64) 147 *i = intValue(v) 148 return err 149 } 150 151 func (i *intValue) Get() interface{} { return int(*i) } 152 func (i *intValue) String() string { return fmt.Sprintf("%v", *i) } 153 154 // -- int32 Value 155 type int32Value int32 156 157 func newInt32Value(val int32, p *int32) *int32Value { 158 *p = val 159 return (*int32Value)(p) 160 } 161 162 func (i *int32Value) Set(s string) error { 163 v, err := strconv.ParseInt(s, 0, 32) 164 *i = int32Value(v) 165 return err 166 } 167 168 func (i *int32Value) Get() interface{} { return int32(*i) } 169 func (i *int32Value) String() string { return fmt.Sprintf("%v", *i) } 170 171 // -- int64 Value 172 type int64Value int64 173 174 func newInt64Value(val int64, p *int64) *int64Value { 175 *p = val 176 return (*int64Value)(p) 177 } 178 179 func (i *int64Value) Set(s string) error { 180 v, err := strconv.ParseInt(s, 0, 64) 181 *i = int64Value(v) 182 return err 183 } 184 185 func (i *int64Value) Get() interface{} { return int64(*i) } 186 func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) } 187 188 // -- uint Value 189 type uintValue uint 190 191 func newUintValue(val uint, p *uint) *uintValue { 192 *p = val 193 return (*uintValue)(p) 194 } 195 196 func (i *uintValue) Set(s string) error { 197 v, err := strconv.ParseUint(s, 0, 64) 198 *i = uintValue(v) 199 return err 200 } 201 202 func (i *uintValue) Get() interface{} { return uint(*i) } 203 func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) } 204 205 // -- uint32 Value 206 type uint32Value uint32 207 208 func newUint32Value(val uint32, p *uint32) *uint32Value { 209 *p = val 210 return (*uint32Value)(p) 211 } 212 213 func (i *uint32Value) Set(s string) error { 214 v, err := strconv.ParseUint(s, 0, 32) 215 *i = uint32Value(v) 216 return err 217 } 218 219 func (i *uint32Value) Get() interface{} { return uint32(*i) } 220 func (i *uint32Value) String() string { return fmt.Sprintf("%v", *i) } 221 222 // -- uint64 Value 223 type uint64Value uint64 224 225 func newUint64Value(val uint64, p *uint64) *uint64Value { 226 *p = val 227 return (*uint64Value)(p) 228 } 229 230 func (i *uint64Value) Set(s string) error { 231 v, err := strconv.ParseUint(s, 0, 64) 232 *i = uint64Value(v) 233 return err 234 } 235 236 func (i *uint64Value) Get() interface{} { return uint64(*i) } 237 func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) } 238 239 // -- string Value 240 type stringValue string 241 242 func newStringValue(val string, p *string) *stringValue { 243 *p = val 244 return (*stringValue)(p) 245 } 246 247 func (s *stringValue) Set(val string) error { 248 *s = stringValue(val) 249 return nil 250 } 251 252 func (s *stringValue) Get() interface{} { return string(*s) } 253 func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) } 254 255 type stringsValue struct { 256 arr []string 257 p *[]string 258 } 259 260 func newStringsValue(val []string, p *[]string) *stringsValue { 261 *p = val 262 return &stringsValue{ 263 arr: val, 264 p: p, 265 } 266 } 267 268 func (i *stringsValue) String() string { return strings.Join(i.arr, ",") } 269 func (i *stringsValue) Get() interface{} { return i.arr } 270 func (i *stringsValue) Set(value string) error { 271 i.arr = append(i.arr, value) 272 *i.p = i.arr 273 return nil 274 } 275 276 // -- float32 Value 277 type float32Value float32 278 279 func newFloat32Value(val float32, p *float32) *float32Value { 280 *p = val 281 return (*float32Value)(p) 282 } 283 284 func (f *float32Value) Set(s string) error { 285 v, err := strconv.ParseFloat(s, 32) 286 *f = float32Value(v) 287 return err 288 } 289 290 func (f *float32Value) Get() interface{} { return float32(*f) } 291 func (f *float32Value) String() string { return fmt.Sprintf("%v", *f) } 292 293 // -- float64 Value 294 type float64Value float64 295 296 func newFloat64Value(val float64, p *float64) *float64Value { 297 *p = val 298 return (*float64Value)(p) 299 } 300 301 func (f *float64Value) Set(s string) error { 302 v, err := strconv.ParseFloat(s, 64) 303 *f = float64Value(v) 304 return err 305 } 306 307 func (f *float64Value) Get() interface{} { return float64(*f) } 308 func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) } 309 310 // -- time.Duration Value 311 type durationValue time.Duration 312 313 func newDurationValue(val time.Duration, p *time.Duration) *durationValue { 314 *p = val 315 return (*durationValue)(p) 316 } 317 318 func (d *durationValue) Set(s string) error { 319 v, err := time.ParseDuration(s) 320 *d = durationValue(v) 321 return err 322 } 323 324 func (d *durationValue) Get() interface{} { return time.Duration(*d) } 325 func (d *durationValue) String() string { return (*time.Duration)(d).String() } 326 327 // Value is the interface to the dynamic value stored in a flag. 328 // (The default value is represented as a string.) 329 // 330 // If a Value has an IsBoolFlag() bool method returning true, 331 // the command-line parser makes -name equivalent to -name=true 332 // rather than using the next command-line argument. 333 // 334 // Set is called once, in command line order, for each flag present. 335 type Value interface { 336 String() string 337 Set(string) error 338 } 339 340 // Getter is an interface that allows the contents of a Value to be retrieved. 341 // It wraps the Value interface, rather than being part of it, because it 342 // appeared after Go 1 and its compatibility rules. All Value types provided 343 // by this package satisfy the Getter interface. 344 type Getter interface { 345 Value 346 Get() interface{} 347 } 348 349 // ErrorHandling defines how FlagSet.Parse behaves if the parse fails. 350 type ErrorHandling int 351 352 // These constants cause FlagSet.Parse to behave as described if the parse fails. 353 const ( 354 ContinueOnError ErrorHandling = iota // Return a descriptive error. 355 ExitOnError // Call os.Exit(2). 356 PanicOnError // Call panic with a descriptive error. 357 ) 358 359 // A FlagSet represents a set of defined flags. The zero value of a FlagSet 360 // has no name and has ContinueOnError error handling. 361 type FlagSet struct { 362 // Usage is the function called when an error occurs while parsing flags. 363 // The field is a function (not a method) that may be changed to point to 364 // a custom error handler. 365 Usage func() 366 367 name string 368 parsed bool 369 actual map[string]*Flag 370 formal map[string]*Flag 371 envPrefix string // prefix to all env variable names 372 args []string // arguments after flags 373 jumpedArgs []string // arguments after flags 374 errorHandling ErrorHandling 375 output io.Writer // nil means stderr; use out() accessor 376 } 377 378 // A Flag represents the state of a flag. 379 type Flag struct { 380 Name string // name as it appears on command line 381 ShortName string // name as it appears on command line 382 Usage string // help message 383 Value Value // value as set 384 DefValue string // default value (as text); for usage message 385 Alias bool 386 } 387 388 // sortFlags returns the flags as a slice in lexicographical sorted order. 389 func sortFlags(flags map[string]*Flag) []*Flag { 390 list := make(sort.StringSlice, 0, len(flags)) 391 for _, f := range flags { 392 if !f.Alias { 393 list = append(list, f.Name) 394 } 395 } 396 list.Sort() 397 result := make([]*Flag, len(list)) 398 for i, name := range list { 399 result[i] = flags[name] 400 } 401 return result 402 } 403 404 func (f *FlagSet) out() io.Writer { 405 if f.output == nil { 406 return os.Stderr 407 } 408 return f.output 409 } 410 411 // SetOutput sets the destination for usage and error messages. 412 // If output is nil, os.Stderr is used. 413 func (f *FlagSet) SetOutput(output io.Writer) { f.output = output } 414 415 // VisitAll visits the flags in lexicographical order, calling fn for each. 416 // It visits all flags, even those not set. 417 func (f *FlagSet) VisitAll(fn func(*Flag)) { 418 for _, flag := range sortFlags(f.formal) { 419 fn(flag) 420 } 421 } 422 423 // VisitAll visits the command-line flags in lexicographical order, calling 424 // fn for each. It visits all flags, even those not set. 425 func VisitAll(fn func(*Flag)) { CommandLine.VisitAll(fn) } 426 427 // Visit visits the flags in lexicographical order, calling fn for each. 428 // It visits only those flags that have been set. 429 func (f *FlagSet) Visit(fn func(*Flag)) { 430 for _, flag := range sortFlags(f.actual) { 431 fn(flag) 432 } 433 } 434 435 // Visit visits the command-line flags in lexicographical order, calling fn 436 // for each. It visits only those flags that have been set. 437 func Visit(fn func(*Flag)) { CommandLine.Visit(fn) } 438 439 // Lookup returns the Flag structure of the named flag, returning nil if none exists. 440 func (f *FlagSet) Lookup(name string) *Flag { return f.formal[name] } 441 442 // Lookup returns the Flag structure of the named command-line flag, 443 // returning nil if none exists. 444 func Lookup(name string) *Flag { return CommandLine.formal[name] } 445 446 // Set sets the value of the named flag. 447 func (f *FlagSet) Set(name, value string) error { 448 flag, ok := f.formal[name] 449 if !ok { 450 return fmt.Errorf("no such flag -%v", name) 451 } 452 err := flag.Value.Set(value) 453 if err != nil { 454 return err 455 } 456 if f.actual == nil { 457 f.actual = make(map[string]*Flag) 458 } 459 f.actual[name] = flag 460 return nil 461 } 462 463 // Set sets the value of the named command-line flag. 464 func Set(name, value string) error { return CommandLine.Set(name, value) } 465 466 // isZeroValue guesses whether the string represents the zero 467 // value for a flag. It is not accurate but in practice works OK. 468 func isZeroValue(flag *Flag, value string) bool { 469 // Build a zero value of the flag's Value type, and see if the 470 // result of calling its String method equals the value passed in. 471 // This works unless the Value type is itself an interface type. 472 typ := reflect.TypeOf(flag.Value) 473 var z reflect.Value 474 if typ.Kind() == reflect.Ptr { 475 z = reflect.New(typ.Elem()) 476 } else { 477 z = reflect.Zero(typ) 478 } 479 if value == z.Interface().(Value).String() { 480 return true 481 } 482 483 switch value { 484 case "false", "", "0": 485 return true 486 } 487 return false 488 } 489 490 // UnquoteUsage extracts a back-quoted name from the usage 491 // string for a flag and returns it and the un-quoted usage. 492 // Given "a `name` to show" it returns ("name", "a name to show"). 493 // If there are no back quotes, the name is an educated guess of the 494 // type of the flag's value, or the empty string if the flag is boolean. 495 func UnquoteUsage(flag *Flag) (name string, usage string) { 496 // Look for a back-quoted name, but avoid the strings package. 497 usage = flag.Usage 498 for i := 0; i < len(usage); i++ { 499 if usage[i] == '`' { 500 for j := i + 1; j < len(usage); j++ { 501 if usage[j] == '`' { 502 name = usage[i+1 : j] 503 usage = usage[:i] + name + usage[j+1:] 504 return name, usage 505 } 506 } 507 break // Only one back quote; use type name. 508 } 509 } 510 // No explicit name, so use type if we can find one. 511 name = "value" 512 switch flag.Value.(type) { 513 case boolFlag: 514 name = "" 515 case *durationValue: 516 name = "duration" 517 case *float64Value: 518 name = "float" 519 case *intValue, *int64Value: 520 name = "int" 521 case *stringValue: 522 name = "string" 523 case *uintValue, *uint64Value: 524 name = "uint" 525 } 526 return 527 } 528 529 // PrintDefaults prints to standard error the default values of all 530 // defined command-line flags in the set. See the documentation for 531 // the global function PrintDefaults for more information. 532 func (f *FlagSet) PrintDefaults() { 533 visited := map[*Flag]bool{} 534 f.VisitAll(func(flag *Flag) { 535 if visited[flag] { 536 return 537 } 538 visited[flag] = true 539 540 s := fmt.Sprintf(" -%s", flag.Name) // Two spaces before -; see next two comments. 541 if flag.ShortName != "" { 542 s += fmt.Sprintf(" (-%s)", flag.ShortName) 543 } 544 name, usage := UnquoteUsage(flag) 545 if len(name) > 0 { 546 s += " " + name 547 } 548 // Boolean flags of one ASCII letter are so common we 549 // treat them specially, putting their usage on the same line. 550 if len(s) <= 4 { // space, space, '-', 'x'. 551 s += "\t" 552 } else { 553 // Four spaces before the tab triggers good alignment 554 // for both 4- and 8-space tab stops. 555 s += "\t" 556 } 557 s += usage 558 if !isZeroValue(flag, flag.DefValue) { 559 if _, ok := flag.Value.(*stringValue); ok { 560 // put quotes on the value 561 s += fmt.Sprintf(" (default %q)", flag.DefValue) 562 } else { 563 s += fmt.Sprintf(" (default %v)", flag.DefValue) 564 } 565 } 566 fmt.Fprint(f.out(), s, "\n") 567 }) 568 } 569 570 // PrintDefaults prints, to standard error unless configured otherwise, 571 // a usage message showing the default settings of all defined 572 // command-line flags. 573 // For an integer valued flag x, the default output has the form 574 // 575 // -x int 576 // usage-message-for-x (default 7) 577 // 578 // The usage message will appear on a separate line for anything but 579 // a bool flag with a one-byte name. For bool flags, the type is 580 // omitted and if the flag name is one byte the usage message appears 581 // on the same line. The parenthetical default is omitted if the 582 // default is the zero value for the type. The listed type, here int, 583 // can be changed by placing a back-quoted name in the flag's usage 584 // string; the first such item in the message is taken to be a parameter 585 // name to show in the message and the back quotes are stripped from 586 // the message when displayed. For instance, given 587 // 588 // flag.String("I", "", "search `directory` for include files") 589 // 590 // the output will be 591 // 592 // -I directory 593 // search directory for include files. 594 func PrintDefaults() { CommandLine.PrintDefaults() } 595 596 // defaultUsage is the default function to print a usage message. 597 func (f *FlagSet) defaultUsage() { 598 if f.name == "" { 599 fmt.Fprintf(f.out(), "Usage:\n") 600 } else { 601 fmt.Fprintf(f.out(), "Usage of %s:\n", f.name) 602 } 603 f.PrintDefaults() 604 } 605 606 // NOTE: Usage is not just defaultUsage(CommandLine) 607 // because it serves (via godoc flag Usage) as the example 608 // for how to write your own usage function. 609 610 // Usage prints to standard error a usage message documenting all defined command-line flags. 611 // It is called when an error occurs while parsing flags. 612 // The function is a variable that may be changed to point to a custom function. 613 // By default it prints a simple header and calls PrintDefaults; for details about the 614 // format of the output and how to control it, see the documentation for PrintDefaults. 615 var Usage = func() { 616 fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) 617 PrintDefaults() 618 } 619 620 // NFlag returns the number of flags that have been set. 621 func (f *FlagSet) NFlag() int { return len(f.actual) } 622 623 // NFlag returns the number of command-line flags that have been set. 624 func NFlag() int { return len(CommandLine.actual) } 625 626 // Arg returns the i'th argument. Arg(0) is the first remaining argument 627 // after flags have been processed. Arg returns an empty string if the 628 // requested element does not exist. 629 func (f *FlagSet) Arg(i int) string { 630 if i < 0 || i >= len(f.jumpedArgs) { 631 return "" 632 } 633 return f.jumpedArgs[i] 634 } 635 636 // Arg returns the i'th command-line argument. Arg(0) is the first remaining argument 637 // after flags have been processed. Arg returns an empty string if the 638 // requested element does not exist. 639 func Arg(i int) string { return CommandLine.Arg(i) } 640 641 // NArg is the number of arguments remaining after flags have been processed. 642 func (f *FlagSet) NArg() int { return len(f.jumpedArgs) } 643 644 // NArg is the number of arguments remaining after flags have been processed. 645 func NArg() int { return CommandLine.NArg() } 646 647 // Args returns the non-flag arguments. 648 func (f *FlagSet) Args() []string { return f.jumpedArgs } 649 650 // Args returns the non-flag command-line arguments. 651 func Args() []string { return CommandLine.Args() } 652 653 // BoolVar defines a bool flag with specified name, default value, and usage string. 654 // The argument p points to a bool variable in which to store the value of the flag. 655 func (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string) { 656 f.Var(newBoolValue(value, p), name, usage) 657 } 658 659 // BoolVar defines a bool flag with specified name, default value, and usage string. 660 // The argument p points to a bool variable in which to store the value of the flag. 661 func BoolVar(p *bool, name string, value bool, usage string) { 662 CommandLine.Var(newBoolValue(value, p), name, usage) 663 } 664 665 // Bool defines a bool flag with specified name, default value, and usage string. 666 // The return value is the address of a bool variable that stores the value of the flag. 667 func (f *FlagSet) Bool(name string, value bool, usage string) *bool { 668 p := new(bool) 669 f.BoolVar(p, name, value, usage) 670 return p 671 } 672 673 // Bool defines a bool flag with specified name, default value, and usage string. 674 // The return value is the address of a bool variable that stores the value of the flag. 675 func Bool(name string, value bool, usage string) *bool { 676 return CommandLine.Bool(name, value, usage) 677 } 678 679 // IntVar defines an int flag with specified name, default value, and usage string. 680 // The argument p points to an int variable in which to store the value of the flag. 681 func (f *FlagSet) IntVar(p *int, name string, value int, usage string) { 682 f.Var(newIntValue(value, p), name, usage) 683 } 684 685 // IntVar defines an int flag with specified name, default value, and usage string. 686 // The argument p points to an int variable in which to store the value of the flag. 687 func IntVar(p *int, name string, value int, usage string) { 688 CommandLine.Var(newIntValue(value, p), name, usage) 689 } 690 691 // Int32Var defines an int flag with specified name, default value, and usage string. 692 // The argument p points to an int variable in which to store the value of the flag. 693 func (f *FlagSet) Int32Var(p *int32, name string, value int32, usage string) { 694 f.Var(newInt32Value(value, p), name, usage) 695 } 696 697 // Int32Var defines an int flag with specified name, default value, and usage string. 698 // The argument p points to an int variable in which to store the value of the flag. 699 func Int32Var(p *int32, name string, value int32, usage string) { 700 CommandLine.Var(newInt32Value(value, p), name, usage) 701 } 702 703 // Int defines an int flag with specified name, default value, and usage string. 704 // The return value is the address of an int variable that stores the value of the flag. 705 func (f *FlagSet) Int(name string, value int, usage string) *int { 706 p := new(int) 707 f.IntVar(p, name, value, usage) 708 return p 709 } 710 711 // Int defines an int flag with specified name, default value, and usage string. 712 // The return value is the address of an int variable that stores the value of the flag. 713 func Int(name string, value int, usage string) *int { 714 return CommandLine.Int(name, value, usage) 715 } 716 717 // CountVar defines an int flag with specified name, default value, and usage string. 718 // The argument p points to an int variable in which to store the value of the flag. 719 func (f *FlagSet) CountVar(p *int, name string, value int, usage string) { 720 f.Var(newCountValue(value, p), name, usage) 721 } 722 723 // CountVar defines an int flag with specified name, default value, and usage string. 724 // The argument p points to an int variable in which to store the value of the flag. 725 func CountVar(p *int, name string, value int, usage string) { 726 CommandLine.Var(newCountValue(value, p), name, usage) 727 } 728 729 // Count defines an int flag with specified name, default value, and usage string. 730 // The return value is the address of an int variable that stores the value of the flag. 731 func (f *FlagSet) Count(name string, value int, usage string) *int { 732 p := new(int) 733 f.CountVar(p, name, value, usage) 734 return p 735 } 736 737 // Count defines an int flag with specified name, default value, and usage string. 738 // The return value is the address of an int variable that stores the value of the flag. 739 func Count(name string, value int, usage string) *int { 740 return CommandLine.Count(name, value, usage) 741 } 742 743 // Int64Var defines an int64 flag with specified name, default value, and usage string. 744 // The argument p points to an int64 variable in which to store the value of the flag. 745 func (f *FlagSet) Int64Var(p *int64, name string, value int64, usage string) { 746 f.Var(newInt64Value(value, p), name, usage) 747 } 748 749 // Int64Var defines an int64 flag with specified name, default value, and usage string. 750 // The argument p points to an int64 variable in which to store the value of the flag. 751 func Int64Var(p *int64, name string, value int64, usage string) { 752 CommandLine.Var(newInt64Value(value, p), name, usage) 753 } 754 755 // Int64 defines an int64 flag with specified name, default value, and usage string. 756 // The return value is the address of an int64 variable that stores the value of the flag. 757 func (f *FlagSet) Int64(name string, value int64, usage string) *int64 { 758 p := new(int64) 759 f.Int64Var(p, name, value, usage) 760 return p 761 } 762 763 // Int64 defines an int64 flag with specified name, default value, and usage string. 764 // The return value is the address of an int64 variable that stores the value of the flag. 765 func Int64(name string, value int64, usage string) *int64 { 766 return CommandLine.Int64(name, value, usage) 767 } 768 769 // UintVar defines a uint flag with specified name, default value, and usage string. 770 // The argument p points to a uint variable in which to store the value of the flag. 771 func (f *FlagSet) UintVar(p *uint, name string, value uint, usage string) { 772 f.Var(newUintValue(value, p), name, usage) 773 } 774 775 // UintVar defines a uint flag with specified name, default value, and usage string. 776 // The argument p points to a uint variable in which to store the value of the flag. 777 func UintVar(p *uint, name string, value uint, usage string) { 778 CommandLine.Var(newUintValue(value, p), name, usage) 779 } 780 781 // Uint32Var defines a uint flag with specified name, default value, and usage string. 782 // The argument p points to a uint variable in which to store the value of the flag. 783 func (f *FlagSet) Uint32Var(p *uint32, name string, value uint32, usage string) { 784 f.Var(newUint32Value(value, p), name, usage) 785 } 786 787 // Uint32Var defines a uint flag with specified name, default value, and usage string. 788 // The argument p points to a uint variable in which to store the value of the flag. 789 func Uint32Var(p *uint32, name string, value uint32, usage string) { 790 CommandLine.Var(newUint32Value(value, p), name, usage) 791 } 792 793 // Uint defines a uint flag with specified name, default value, and usage string. 794 // The return value is the address of a uint variable that stores the value of the flag. 795 func (f *FlagSet) Uint(name string, value uint, usage string) *uint { 796 p := new(uint) 797 f.UintVar(p, name, value, usage) 798 return p 799 } 800 801 // Uint defines a uint flag with specified name, default value, and usage string. 802 // The return value is the address of a uint variable that stores the value of the flag. 803 func Uint(name string, value uint, usage string) *uint { return CommandLine.Uint(name, value, usage) } 804 805 // Uint64Var defines a uint64 flag with specified name, default value, and usage string. 806 // The argument p points to a uint64 variable in which to store the value of the flag. 807 func (f *FlagSet) Uint64Var(p *uint64, name string, value uint64, usage string) { 808 f.Var(newUint64Value(value, p), name, usage) 809 } 810 811 // Uint64Var defines a uint64 flag with specified name, default value, and usage string. 812 // The argument p points to a uint64 variable in which to store the value of the flag. 813 func Uint64Var(p *uint64, name string, value uint64, usage string) { 814 CommandLine.Var(newUint64Value(value, p), name, usage) 815 } 816 817 // Uint64 defines a uint64 flag with specified name, default value, and usage string. 818 // The return value is the address of a uint64 variable that stores the value of the flag. 819 func (f *FlagSet) Uint64(name string, value uint64, usage string) *uint64 { 820 p := new(uint64) 821 f.Uint64Var(p, name, value, usage) 822 return p 823 } 824 825 // Uint64 defines a uint64 flag with specified name, default value, and usage string. 826 // The return value is the address of a uint64 variable that stores the value of the flag. 827 func Uint64(name string, value uint64, usage string) *uint64 { 828 return CommandLine.Uint64(name, value, usage) 829 } 830 831 // StringsVar 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 (f *FlagSet) StringsVar(p *[]string, name string, value []string, usage string) { 834 f.Var(newStringsValue(value, p), name, usage) 835 } 836 837 // StringVar defines a string flag with specified name, default value, and usage string. 838 // The argument p points to a string variable in which to store the value of the flag. 839 func (f *FlagSet) StringVar(p *string, name, value, usage string) { 840 f.Var(newStringValue(value, p), name, usage) 841 } 842 843 // StringsVar defines a string flag with specified name, default value, and usage string. 844 // The argument p points to a string variable in which to store the value of the flag. 845 func StringsVar(p *[]string, name string, value []string, usage string) { 846 CommandLine.Var(newStringsValue(value, p), name, usage) 847 } 848 849 // StringVar defines a string flag with specified name, default value, and usage string. 850 // The argument p points to a string variable in which to store the value of the flag. 851 func StringVar(p *string, name, value, usage string) { 852 CommandLine.Var(newStringValue(value, p), name, usage) 853 } 854 855 // String defines a string flag with specified name, default value, and usage string. 856 // The return value is the address of a string variable that stores the value of the flag. 857 func (f *FlagSet) String(name, value, usage string) *string { 858 p := new(string) 859 f.StringVar(p, name, value, usage) 860 return p 861 } 862 863 // Strings defines a string flag with specified name, default value, and usage string. 864 // The return value is the address of a string variable that stores the value of the flag. 865 func (f *FlagSet) Strings(name string, value []string, usage string) *[]string { 866 var p []string 867 f.StringsVar(&p, name, value, usage) 868 return &p 869 } 870 871 // String defines a string flag with specified name, default value, and usage string. 872 // The return value is the address of a string variable that stores the value of the flag. 873 func String(name, value, usage string) *string { 874 return CommandLine.String(name, value, usage) 875 } 876 877 // Strings defines multiple string flag with specified name, default value, and usage string. 878 // The return value is the address of a string variable that stores the value of the flag. 879 func Strings(name string, value []string, usage string) *[]string { 880 return CommandLine.Strings(name, value, usage) 881 } 882 883 // Float32Var defines a float32 flag with specified name, default value, and usage string. 884 // The argument p points to a float32 variable in which to store the value of the flag. 885 func (f *FlagSet) Float32Var(p *float32, name string, value float32, usage string) { 886 f.Var(newFloat32Value(value, p), name, usage) 887 } 888 889 // Float32Var defines a float32 flag with specified name, default value, and usage string. 890 // The argument p points to a float32 variable in which to store the value of the flag. 891 func Float32Var(p *float32, name string, value float32, usage string) { 892 CommandLine.Var(newFloat32Value(value, p), name, usage) 893 } 894 895 // Float64Var defines a float64 flag with specified name, default value, and usage string. 896 // The argument p points to a float64 variable in which to store the value of the flag. 897 func (f *FlagSet) Float64Var(p *float64, name string, value float64, usage string) { 898 f.Var(newFloat64Value(value, p), name, usage) 899 } 900 901 // Float64Var defines a float64 flag with specified name, default value, and usage string. 902 // The argument p points to a float64 variable in which to store the value of the flag. 903 func Float64Var(p *float64, name string, value float64, usage string) { 904 CommandLine.Var(newFloat64Value(value, p), name, usage) 905 } 906 907 // Float64 defines a float64 flag with specified name, default value, and usage string. 908 // The return value is the address of a float64 variable that stores the value of the flag. 909 func (f *FlagSet) Float64(name string, value float64, usage string) *float64 { 910 p := new(float64) 911 f.Float64Var(p, name, value, usage) 912 return p 913 } 914 915 // Float64 defines a float64 flag with specified name, default value, and usage string. 916 // The return value is the address of a float64 variable that stores the value of the flag. 917 func Float64(name string, value float64, usage string) *float64 { 918 return CommandLine.Float64(name, value, usage) 919 } 920 921 // DurationVar defines a time.Duration flag with specified name, default value, and usage string. 922 // The argument p points to a time.Duration variable in which to store the value of the flag. 923 // The flag accepts a value acceptable to time.ParseDuration. 924 func DurationVar(p *time.Duration, name string, value time.Duration, usage string) { 925 CommandLine.Var(newDurationValue(value, p), name, usage) 926 } 927 928 // Duration defines a time.Duration flag with specified name, default value, and usage string. 929 // The return value is the address of a time.Duration variable that stores the value of the flag. 930 // The flag accepts a value acceptable to time.ParseDuration. 931 func Duration(name string, value time.Duration, usage string) *time.Duration { 932 return CommandLine.Duration(name, value, usage) 933 } 934 935 // DurationVar defines a time.Duration flag with specified name, default value, and usage string. 936 // The argument p points to a time.Duration variable in which to store the value of the flag. 937 // The flag accepts a value acceptable to time.ParseDuration. 938 func (f *FlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string) { 939 f.Var(newDurationValue(value, p), name, usage) 940 } 941 942 // Duration defines a time.Duration flag with specified name, default value, and usage string. 943 // The return value is the address of a time.Duration variable that stores the value of the flag. 944 // The flag accepts a value acceptable to time.ParseDuration. 945 func (f *FlagSet) Duration(name string, value time.Duration, usage string) *time.Duration { 946 p := new(time.Duration) 947 f.DurationVar(p, name, value, usage) 948 return p 949 } 950 951 // Var defines a flag with the specified name and usage string. The type and 952 // value of the flag are represented by the first argument, of type Value, which 953 // typically holds a user-defined implementation of Value. For instance, the 954 // caller could create a flag that turns a comma-separated string into a slice 955 // of strings by giving the slice the methods of Value; in particular, Set would 956 // decompose the comma-separated string into the slice. 957 func (f *FlagSet) Var(value Value, name string, usage string) { 958 shortName := "" 959 if p := strings.IndexByte(name, ','); p > 0 { 960 shortName = name[p+1:] 961 name = name[:p] 962 } 963 // Remember the default value as a string; it won't change. 964 flag := &Flag{Name: name, ShortName: shortName, Usage: usage, Value: value, DefValue: value.String()} 965 f.checkRedefined(name) 966 if shortName != "" { 967 f.checkRedefined(shortName) 968 } 969 if f.formal == nil { 970 f.formal = make(map[string]*Flag) 971 } 972 973 f.formal[name] = flag 974 if shortName != "" { 975 f.formal[shortName] = flag 976 } 977 978 kebab := ss.ToLowerKebab(name) 979 if _, exists := f.formal[kebab]; !exists { 980 kebabFlag := *flag 981 kebabFlag.Alias = true 982 f.formal[kebab] = &kebabFlag 983 } 984 } 985 986 func (f *FlagSet) checkRedefined(name string) { 987 if _, alreadythere := f.formal[name]; alreadythere { 988 var msg string 989 if f.name == "" { 990 msg = fmt.Sprintf("flag redefined: %s", name) 991 } else { 992 msg = fmt.Sprintf("%s flag redefined: %s", f.name, name) 993 } 994 fmt.Fprintln(f.out(), msg) 995 panic(msg) // Happens only if flags are declared with identical names 996 } 997 } 998 999 // Var defines a flag with the specified name and usage string. The type and 1000 // value of the flag are represented by the first argument, of type Value, which 1001 // typically holds a user-defined implementation of Value. For instance, the 1002 // caller could create a flag that turns a comma-separated string into a slice 1003 // of strings by giving the slice the methods of Value; in particular, Set would 1004 // decompose the comma-separated string into the slice. 1005 func Var(value Value, name, usage string) { 1006 CommandLine.Var(value, name, usage) 1007 } 1008 1009 // failf prints to standard error a formatted error and usage message and 1010 // returns the error. 1011 func (f *FlagSet) failf(format string, a ...interface{}) error { 1012 err := fmt.Errorf(format, a...) 1013 fmt.Fprintln(f.out(), err) 1014 f.usage() 1015 return err 1016 } 1017 1018 // usage calls the Usage method for the flag set if one is specified, 1019 // or the appropriate default usage function otherwise. 1020 func (f *FlagSet) usage() { 1021 if f.Usage == nil { 1022 f.defaultUsage() 1023 } else { 1024 f.Usage() 1025 } 1026 } 1027 1028 // parseOne parses one flag. It reports whether a flag was seen. 1029 func (f *FlagSet) parseOne() (bool, error) { 1030 if len(f.args) == 0 { 1031 return false, nil 1032 } 1033 s := f.args[0] 1034 if len(s) < 2 || s[0] != '-' { 1035 f.jumpedArgs = append(f.jumpedArgs, s) 1036 f.args = f.args[1:] 1037 return true, nil 1038 } 1039 numMinuses := 1 1040 if s[1] == '-' { 1041 numMinuses++ 1042 if len(s) == 2 { // "--" terminates the flags 1043 f.args = f.args[1:] 1044 return false, nil 1045 } 1046 } 1047 name := s[numMinuses:] 1048 if len(name) == 0 || name[0] == '-' || name[0] == '=' { 1049 return false, f.failf("bad flag syntax: %s", s) 1050 } 1051 1052 // ignore go test flags 1053 if strings.HasPrefix(name, "test.") { 1054 return false, nil 1055 } 1056 1057 // it's a flag. does it have an argument? 1058 f.args = f.args[1:] 1059 hasValue := false 1060 value := "" 1061 for i := 1; i < len(name); i++ { // equals cannot be first 1062 if name[i] == '=' { 1063 value = name[i+1:] 1064 hasValue = true 1065 name = name[0:i] 1066 break 1067 } 1068 } 1069 flag := f.formal[name] // BUG 1070 if flag == nil { 1071 flag = f.formal[ss.ToLowerKebab(name)] 1072 } 1073 if flag == nil { 1074 if flag, value = checkCombine(f.formal, name); flag != nil { 1075 name = flag.Name 1076 hasValue = true 1077 } 1078 } 1079 1080 if flag == nil { 1081 if name == "help" || name == "h" { // special case for nice help message. 1082 f.usage() 1083 return false, ErrHelp 1084 } 1085 1086 return false, f.failf("flag provided but not defined: -%s", name) 1087 } 1088 if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg 1089 if !hasValue { 1090 value = "true" 1091 if len(f.args) > 0 && ss.AnyOf(f.args[0], "true", "false") { 1092 value, f.args = f.args[0], f.args[1:] 1093 } 1094 } 1095 if err := fv.Set(value); err != nil { 1096 return false, f.failf("invalid boolean value %q for -%s: %v", value, name, err) 1097 } 1098 } else { 1099 if !hasValue { 1100 if _, ok := flag.Value.(*countValue); ok { 1101 hasValue = true 1102 } 1103 } 1104 // It must have a value, which might be the next argument. 1105 if !hasValue && len(f.args) > 0 { 1106 // value is the next arg 1107 hasValue = true 1108 value, f.args = f.args[0], f.args[1:] 1109 } 1110 1111 if !hasValue { 1112 if sb, ok := flag.Value.(*StringBool); ok { 1113 sb.SetExists(true) 1114 } else { 1115 return false, f.failf("flag needs an argument: -%s", name) 1116 } 1117 } else { 1118 if err := flag.Value.Set(value); err != nil { 1119 return false, f.failf("invalid value %q for flag -%s: %v", value, name, err) 1120 } 1121 } 1122 1123 } 1124 if f.actual == nil { 1125 f.actual = make(map[string]*Flag) 1126 } 1127 f.actual[name] = flag 1128 return true, nil 1129 } 1130 1131 func checkCombine(m map[string]*Flag, name string) (*Flag, string) { 1132 for i := len(name) - 1; i > 0; i-- { 1133 if flag, ok := m[name[:i]]; ok { 1134 return flag, name[i:] 1135 } 1136 } 1137 return nil, "" 1138 } 1139 1140 // Parse parses flag definitions from the argument list, which should not 1141 // include the command name. Must be called after all flags in the FlagSet 1142 // are defined and before flags are accessed by the program. 1143 // The return value will be ErrHelp if -help or -h were set but not defined. 1144 func (f *FlagSet) Parse(arguments []string) error { 1145 if _, ok := f.formal[DefaultConFlagName]; !ok { 1146 f.String(DefaultConFlagName, "", "Flags config file, a scaffold one will created when it does not exist.") 1147 defer delete(f.formal, DefaultConFlagName) 1148 } 1149 1150 if err := f.parseArgs(arguments); err != nil { 1151 return err 1152 } 1153 if err := f.parseEnv(); err != nil { 1154 return err 1155 } 1156 if err := f.parseConfigFile(); err != nil { 1157 return err 1158 } 1159 1160 return nil 1161 } 1162 1163 func (f *FlagSet) parseConfigFile() error { 1164 // Parse configuration from file 1165 var cFile string 1166 if cf := f.formal[DefaultConFlagName]; cf != nil { 1167 cFile = cf.Value.String() 1168 } 1169 if cf := f.actual[DefaultConFlagName]; cf != nil { 1170 cFile = cf.Value.String() 1171 } 1172 if cFile == "" { 1173 cFile = f.findConfigArgInUnresolved() 1174 } 1175 1176 if cFile == "" { 1177 return nil 1178 } 1179 1180 if err := f.ParseFile(cFile, true); err != nil { 1181 if os.IsNotExist(err) { 1182 f.createSampleFile(cFile) 1183 fmt.Println("scaffold flags file " + cFile + " created") 1184 } 1185 switch f.errorHandling { 1186 case ContinueOnError: 1187 return err 1188 case ExitOnError: 1189 os.Exit(2) 1190 case PanicOnError: 1191 panic(err) 1192 } 1193 } 1194 1195 return nil 1196 } 1197 1198 func (f *FlagSet) findConfigArgInUnresolved() string { 1199 configArg := "-" + DefaultConFlagName 1200 for i := 0; i < len(f.args); i++ { 1201 if strings.HasPrefix(f.args[i], configArg) { 1202 if f.args[i] == configArg && i+1 < len(f.args) { 1203 return f.args[i+1] 1204 } 1205 1206 if strings.HasPrefix(f.args[i], configArg+"=") { 1207 return f.args[i][len(configArg)+1:] 1208 break 1209 } 1210 } 1211 } 1212 return "" 1213 } 1214 1215 func (f *FlagSet) parseEnv() error { 1216 // Parse environment variables 1217 if err := f.ParseEnv(os.Environ()); err != nil { 1218 switch f.errorHandling { 1219 case ContinueOnError: 1220 return err 1221 case ExitOnError: 1222 os.Exit(2) 1223 case PanicOnError: 1224 panic(err) 1225 } 1226 } 1227 return nil 1228 } 1229 1230 func (f *FlagSet) parseArgs(arguments []string) error { 1231 f.parsed = true 1232 f.args = arguments 1233 for { 1234 seen, err := f.parseOne() 1235 if seen { 1236 continue 1237 } 1238 if err == nil { 1239 break 1240 } 1241 1242 if err == ErrHelp { 1243 os.Exit(0) 1244 } 1245 1246 switch f.errorHandling { 1247 case ContinueOnError: 1248 return err 1249 case ExitOnError: 1250 os.Exit(2) 1251 case PanicOnError: 1252 panic(err) 1253 } 1254 } 1255 return nil 1256 } 1257 1258 // Parsed reports whether f.Parse has been called. 1259 func (f *FlagSet) Parsed() bool { return f.parsed } 1260 1261 // Parse parses the command-line flags from os.Args[1:]. Must be called 1262 // after all flags are defined and before flags are accessed by the program. 1263 func Parse() { 1264 // Ignore errors; CommandLine is set for ExitOnError. 1265 CommandLine.Parse(os.Args[1:]) 1266 } 1267 1268 // Parsed reports whether the command-line flags have been parsed. 1269 func Parsed() bool { 1270 return CommandLine.Parsed() 1271 } 1272 1273 // CommandLine is the default set of command-line flags, parsed from os.Args. 1274 // The top-level functions such as BoolVar, Arg, and so on are wrappers for the 1275 // methods of CommandLine. 1276 var CommandLine = NewFlagSet(os.Args[0], ExitOnError) 1277 1278 func init() { 1279 // Override generic FlagSet default Usage with call to global Usage. 1280 // Note: This is not CommandLine.Usage = Usage, 1281 // because we want any eventual call to use any updated value of Usage, 1282 // not the value it has when this line is run. 1283 CommandLine.Usage = commandLineUsage 1284 } 1285 1286 func commandLineUsage() { 1287 Usage() 1288 } 1289 1290 // NewFlagSet returns a new, empty flag set with the specified name and 1291 // error handling property. 1292 func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet { 1293 f := &FlagSet{ 1294 name: name, 1295 errorHandling: errorHandling, 1296 envPrefix: EnvPrefix, 1297 } 1298 f.Usage = f.defaultUsage 1299 return f 1300 } 1301 1302 // Init sets the name and error handling property for a flag set. 1303 // By default, the zero FlagSet uses an empty name, EnvPrefix, and the 1304 // ContinueOnError error handling policy. 1305 func (f *FlagSet) Init(name string, errorHandling ErrorHandling) { 1306 f.name = name 1307 f.envPrefix = EnvPrefix 1308 f.errorHandling = errorHandling 1309 } 1310 1311 // EnvPrefix defines a string that will be implicitly prefixed to a 1312 // flag name before looking it up in the environment variables. 1313 var EnvPrefix = "GG" 1314 1315 // ParseEnv parses flags from environment variables. 1316 // Flags already set will be ignored. 1317 func (f *FlagSet) ParseEnv(environ []string) error { 1318 env := make(map[string]string) 1319 for _, s := range environ { 1320 if i := strings.Index(s, "="); i >= 1 { 1321 env[s[0:i]] = s[i+1:] 1322 } 1323 } 1324 1325 for _, flag := range f.formal { 1326 name := flag.Name 1327 if _, set := f.actual[name]; set { 1328 continue 1329 } 1330 1331 flag, alreadyThere := f.formal[name] 1332 if !alreadyThere { 1333 if name == "help" || name == "h" { // special case for nice help message. 1334 f.usage() 1335 return ErrHelp 1336 } 1337 1338 return f.failf("environment variable provided but not defined: %s", name) 1339 } 1340 1341 envKey := strings.ToUpper(flag.Name) 1342 if f.envPrefix != "" { 1343 envKey = f.envPrefix + "_" + envKey 1344 } 1345 envKey = strings.Replace(envKey, "-", "_", -1) 1346 1347 value, isSet := env[envKey] 1348 if !isSet { 1349 continue 1350 } 1351 1352 if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() && value == "" { 1353 // special case: doesn't need an arg 1354 // flag without value is regarded a bool 1355 value = ("true") 1356 } 1357 if err := flag.Value.Set(value); err != nil { 1358 return f.failf("invalid value %q for environment variable %s: %v", value, name, err) 1359 } 1360 1361 // update f.actual 1362 if f.actual == nil { 1363 f.actual = make(map[string]*Flag) 1364 } 1365 f.actual[name] = flag 1366 } 1367 return nil 1368 } 1369 1370 // NewFlagSetWithEnvPrefix returns a new empty flag set with the specified name, 1371 // environment variable prefix, and error handling property. 1372 func NewFlagSetWithEnvPrefix(name string, prefix string, errorHandling ErrorHandling) *FlagSet { 1373 f := NewFlagSet(name, errorHandling) 1374 f.envPrefix = prefix 1375 return f 1376 } 1377 1378 // DefaultConFlagName defines the flag name of the optional config file 1379 // path. Used to lookup and parse the config file when a default is set and 1380 // available on disk. 1381 var DefaultConFlagName = "fla9" 1382 1383 // ParseFile parses flags from the file in path. 1384 // Same format as commandline arguments, newlines and lines beginning with a 1385 // "#" character are ignored. Flags already set will be ignored. 1386 func (f *FlagSet) ParseFile(path string, ignoreUndefinedConf bool) error { 1387 fp, err := os.Open(path) // Extract arguments from file 1388 if err != nil { 1389 return err 1390 } 1391 defer fp.Close() 1392 1393 scanner := bufio.NewScanner(fp) 1394 for scanner.Scan() { 1395 line := strings.TrimSpace(scanner.Text()) 1396 1397 // Ignore empty lines or comments 1398 if line == "" || line[:1] == "#" || line[:1] == "//" || line[:1] == "--" { 1399 continue 1400 } 1401 1402 // Match `key=value` and `key value` 1403 name, value := line, "" 1404 for i, v := range line { 1405 if v == '=' || v == ' ' || v == ':' { 1406 name, value = strings.TrimSpace(line[:i]), strings.TrimSpace(line[i+1:]) 1407 break 1408 } 1409 } 1410 1411 name = strings.TrimPrefix(name, "-") 1412 1413 // Ignore flag when already set; arguments have precedence over file 1414 if f.actual[name] != nil { 1415 continue 1416 } 1417 1418 flag, alreadyThere := f.formal[name] 1419 if !alreadyThere { 1420 if flag, value = checkCombine(f.formal, name); flag != nil { 1421 name = flag.Name 1422 alreadyThere = true 1423 } 1424 } 1425 1426 if !alreadyThere { 1427 if ignoreUndefinedConf { 1428 continue 1429 } 1430 1431 if name == "help" || name == "h" { // special case for nice help message. 1432 f.usage() 1433 return ErrHelp 1434 } 1435 1436 return f.failf("configuration variable provided but not defined: %s", name) 1437 } 1438 1439 if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() && value == "" { 1440 // special case: doesn't need an arg 1441 value = "true" 1442 } 1443 1444 if err := flag.Value.Set(value); err != nil { 1445 return f.failf("invalid value %q for configuration variable %s: %v", value, name, err) 1446 } 1447 1448 // update f.actual 1449 if f.actual == nil { 1450 f.actual = make(map[string]*Flag) 1451 } 1452 f.actual[name] = flag 1453 } 1454 1455 return scanner.Err() 1456 } 1457 1458 func (f *FlagSet) createSampleFile(filename string) { 1459 sampleContent := "" 1460 f.VisitAll(func(fla *Flag) { 1461 if fla.Name == DefaultConFlagName { 1462 return 1463 } 1464 1465 if fla.Usage != "" { 1466 sampleContent += "# " + fla.Usage + "\n" 1467 } 1468 1469 sampleContent += "# " + fla.Name + " = " + fla.Value.String() + "\n\n" 1470 }) 1471 1472 if err := ioutil.WriteFile(filename, []byte(sampleContent), 0o600); err != nil { 1473 fmt.Printf("write file %s failed, error %v\n", filename, err) 1474 } 1475 }