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  }