Source file src/flag/flag.go

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  /*
     6  Package flag implements command-line flag parsing.
     7  
     8  # Usage
     9  
    10  Define flags using [flag.String], [Bool], [Int], etc.
    11  
    12  This declares an integer flag, -n, stored in the pointer nFlag, with type *int:
    13  
    14  	import "flag"
    15  	var nFlag = flag.Int("n", 1234, "help message for flag n")
    16  
    17  If you like, you can bind the flag to a variable using the Var() functions.
    18  
    19  	var flagvar int
    20  	func init() {
    21  		flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
    22  	}
    23  
    24  Or you can create custom flags that satisfy the Value interface (with
    25  pointer receivers) and couple them to flag parsing by
    26  
    27  	flag.Var(&flagVal, "name", "help message for flagname")
    28  
    29  For such flags, the default value is just the initial value of the variable.
    30  
    31  After all flags are defined, call
    32  
    33  	flag.Parse()
    34  
    35  to parse the command line into the defined flags.
    36  
    37  Flags may then be used directly. If you're using the flags themselves,
    38  they are all pointers; if you bind to variables, they're values.
    39  
    40  	fmt.Println("ip has value ", *ip)
    41  	fmt.Println("flagvar has value ", flagvar)
    42  
    43  After parsing, the arguments following the flags are available as the
    44  slice [flag.Args] or individually as [flag.Arg](i).
    45  The arguments are indexed from 0 through [flag.NArg]-1.
    46  
    47  # Command line flag syntax
    48  
    49  The following forms are permitted:
    50  
    51  	-flag
    52  	--flag   // double dashes are also permitted
    53  	-flag=x
    54  	-flag x  // non-boolean flags only
    55  
    56  One or two dashes may be used; they are equivalent.
    57  The last form is not permitted for boolean flags because the
    58  meaning of the command
    59  
    60  	cmd -x *
    61  
    62  where * is a Unix shell wildcard, will change if there is a file
    63  called 0, false, etc. You must use the -flag=false form to turn
    64  off a boolean flag.
    65  
    66  Flag parsing stops just before the first non-flag argument
    67  ("-" is a non-flag argument) or after the terminator "--".
    68  
    69  Integer flags accept 1234, 0664, 0x1234 and may be negative.
    70  Boolean flags may be:
    71  
    72  	1, 0, t, f, T, F, true, false, TRUE, FALSE, True, False
    73  
    74  Duration flags accept any input valid for time.ParseDuration.
    75  
    76  The default set of command-line flags is controlled by
    77  top-level functions.  The [FlagSet] type allows one to define
    78  independent sets of flags, such as to implement subcommands
    79  in a command-line interface. The methods of [FlagSet] are
    80  analogous to the top-level functions for the command-line
    81  flag set.
    82  */
    83  package flag
    84  
    85  import (
    86  	"encoding"
    87  	"errors"
    88  	"fmt"
    89  	"io"
    90  	"os"
    91  	"reflect"
    92  	"runtime"
    93  	"slices"
    94  	"strconv"
    95  	"strings"
    96  	"time"
    97  )
    98  
    99  // ErrHelp is the error returned if the -help or -h flag is invoked
   100  // but no such flag is defined.
   101  var ErrHelp = errors.New("flag: help requested")
   102  
   103  // errParse is returned by Set if a flag's value fails to parse, such as with an invalid integer for Int.
   104  // It then gets wrapped through failf to provide more information.
   105  var errParse = errors.New("parse error")
   106  
   107  // errRange is returned by Set if a flag's value is out of range.
   108  // It then gets wrapped through failf to provide more information.
   109  var errRange = errors.New("value out of range")
   110  
   111  func numError(err error) error {
   112  	ne, ok := err.(*strconv.NumError)
   113  	if !ok {
   114  		return err
   115  	}
   116  	if ne.Err == strconv.ErrSyntax {
   117  		return errParse
   118  	}
   119  	if ne.Err == strconv.ErrRange {
   120  		return errRange
   121  	}
   122  	return err
   123  }
   124  
   125  // -- bool Value
   126  type boolValue bool
   127  
   128  func newBoolValue(val bool, p *bool) *boolValue {
   129  	*p = val
   130  	return (*boolValue)(p)
   131  }
   132  
   133  func (b *boolValue) Set(s string) error {
   134  	v, err := strconv.ParseBool(s)
   135  	if err != nil {
   136  		err = errParse
   137  	}
   138  	*b = boolValue(v)
   139  	return err
   140  }
   141  
   142  func (b *boolValue) Get() any { return bool(*b) }
   143  
   144  func (b *boolValue) String() string { return strconv.FormatBool(bool(*b)) }
   145  
   146  func (b *boolValue) IsBoolFlag() bool { return true }
   147  
   148  // optional interface to indicate boolean flags that can be
   149  // supplied without "=value" text
   150  type boolFlag interface {
   151  	Value
   152  	IsBoolFlag() bool
   153  }
   154  
   155  // -- int Value
   156  type intValue int
   157  
   158  func newIntValue(val int, p *int) *intValue {
   159  	*p = val
   160  	return (*intValue)(p)
   161  }
   162  
   163  func (i *intValue) Set(s string) error {
   164  	v, err := strconv.ParseInt(s, 0, strconv.IntSize)
   165  	if err != nil {
   166  		err = numError(err)
   167  	}
   168  	*i = intValue(v)
   169  	return err
   170  }
   171  
   172  func (i *intValue) Get() any { return int(*i) }
   173  
   174  func (i *intValue) String() string { return strconv.Itoa(int(*i)) }
   175  
   176  // -- int64 Value
   177  type int64Value int64
   178  
   179  func newInt64Value(val int64, p *int64) *int64Value {
   180  	*p = val
   181  	return (*int64Value)(p)
   182  }
   183  
   184  func (i *int64Value) Set(s string) error {
   185  	v, err := strconv.ParseInt(s, 0, 64)
   186  	if err != nil {
   187  		err = numError(err)
   188  	}
   189  	*i = int64Value(v)
   190  	return err
   191  }
   192  
   193  func (i *int64Value) Get() any { return int64(*i) }
   194  
   195  func (i *int64Value) String() string { return strconv.FormatInt(int64(*i), 10) }
   196  
   197  // -- uint Value
   198  type uintValue uint
   199  
   200  func newUintValue(val uint, p *uint) *uintValue {
   201  	*p = val
   202  	return (*uintValue)(p)
   203  }
   204  
   205  func (i *uintValue) Set(s string) error {
   206  	v, err := strconv.ParseUint(s, 0, strconv.IntSize)
   207  	if err != nil {
   208  		err = numError(err)
   209  	}
   210  	*i = uintValue(v)
   211  	return err
   212  }
   213  
   214  func (i *uintValue) Get() any { return uint(*i) }
   215  
   216  func (i *uintValue) String() string { return strconv.FormatUint(uint64(*i), 10) }
   217  
   218  // -- uint64 Value
   219  type uint64Value uint64
   220  
   221  func newUint64Value(val uint64, p *uint64) *uint64Value {
   222  	*p = val
   223  	return (*uint64Value)(p)
   224  }
   225  
   226  func (i *uint64Value) Set(s string) error {
   227  	v, err := strconv.ParseUint(s, 0, 64)
   228  	if err != nil {
   229  		err = numError(err)
   230  	}
   231  	*i = uint64Value(v)
   232  	return err
   233  }
   234  
   235  func (i *uint64Value) Get() any { return uint64(*i) }
   236  
   237  func (i *uint64Value) String() string { return strconv.FormatUint(uint64(*i), 10) }
   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() any { return string(*s) }
   253  
   254  func (s *stringValue) String() string { return string(*s) }
   255  
   256  // -- float64 Value
   257  type float64Value float64
   258  
   259  func newFloat64Value(val float64, p *float64) *float64Value {
   260  	*p = val
   261  	return (*float64Value)(p)
   262  }
   263  
   264  func (f *float64Value) Set(s string) error {
   265  	v, err := strconv.ParseFloat(s, 64)
   266  	if err != nil {
   267  		err = numError(err)
   268  	}
   269  	*f = float64Value(v)
   270  	return err
   271  }
   272  
   273  func (f *float64Value) Get() any { return float64(*f) }
   274  
   275  func (f *float64Value) String() string { return strconv.FormatFloat(float64(*f), 'g', -1, 64) }
   276  
   277  // -- time.Duration Value
   278  type durationValue time.Duration
   279  
   280  func newDurationValue(val time.Duration, p *time.Duration) *durationValue {
   281  	*p = val
   282  	return (*durationValue)(p)
   283  }
   284  
   285  func (d *durationValue) Set(s string) error {
   286  	v, err := time.ParseDuration(s)
   287  	if err != nil {
   288  		err = errParse
   289  	}
   290  	*d = durationValue(v)
   291  	return err
   292  }
   293  
   294  func (d *durationValue) Get() any { return time.Duration(*d) }
   295  
   296  func (d *durationValue) String() string { return (*time.Duration)(d).String() }
   297  
   298  // -- encoding.TextUnmarshaler Value
   299  type textValue struct{ p encoding.TextUnmarshaler }
   300  
   301  func newTextValue(val encoding.TextMarshaler, p encoding.TextUnmarshaler) textValue {
   302  	ptrVal := reflect.ValueOf(p)
   303  	if ptrVal.Kind() != reflect.Ptr {
   304  		panic("variable value type must be a pointer")
   305  	}
   306  	defVal := reflect.ValueOf(val)
   307  	if defVal.Kind() == reflect.Ptr {
   308  		defVal = defVal.Elem()
   309  	}
   310  	if defVal.Type() != ptrVal.Type().Elem() {
   311  		panic(fmt.Sprintf("default type does not match variable type: %v != %v", defVal.Type(), ptrVal.Type().Elem()))
   312  	}
   313  	ptrVal.Elem().Set(defVal)
   314  	return textValue{p}
   315  }
   316  
   317  func (v textValue) Set(s string) error {
   318  	return v.p.UnmarshalText([]byte(s))
   319  }
   320  
   321  func (v textValue) Get() interface{} {
   322  	return v.p
   323  }
   324  
   325  func (v textValue) String() string {
   326  	if m, ok := v.p.(encoding.TextMarshaler); ok {
   327  		if b, err := m.MarshalText(); err == nil {
   328  			return string(b)
   329  		}
   330  	}
   331  	return ""
   332  }
   333  
   334  // -- func Value
   335  type funcValue func(string) error
   336  
   337  func (f funcValue) Set(s string) error { return f(s) }
   338  
   339  func (f funcValue) String() string { return "" }
   340  
   341  // -- boolFunc Value
   342  type boolFuncValue func(string) error
   343  
   344  func (f boolFuncValue) Set(s string) error { return f(s) }
   345  
   346  func (f boolFuncValue) String() string { return "" }
   347  
   348  func (f boolFuncValue) IsBoolFlag() bool { return true }
   349  
   350  // Value is the interface to the dynamic value stored in a flag.
   351  // (The default value is represented as a string.)
   352  //
   353  // If a Value has an IsBoolFlag() bool method returning true,
   354  // the command-line parser makes -name equivalent to -name=true
   355  // rather than using the next command-line argument.
   356  //
   357  // Set is called once, in command line order, for each flag present.
   358  // The flag package may call the [String] method with a zero-valued receiver,
   359  // such as a nil pointer.
   360  type Value interface {
   361  	String() string
   362  	Set(string) error
   363  }
   364  
   365  // Getter is an interface that allows the contents of a [Value] to be retrieved.
   366  // It wraps the [Value] interface, rather than being part of it, because it
   367  // appeared after Go 1 and its compatibility rules. All [Value] types provided
   368  // by this package satisfy the [Getter] interface, except the type used by [Func].
   369  type Getter interface {
   370  	Value
   371  	Get() any
   372  }
   373  
   374  // ErrorHandling defines how [FlagSet.Parse] behaves if the parse fails.
   375  type ErrorHandling int
   376  
   377  // These constants cause [FlagSet.Parse] to behave as described if the parse fails.
   378  const (
   379  	ContinueOnError ErrorHandling = iota // Return a descriptive error.
   380  	ExitOnError                          // Call os.Exit(2) or for -h/-help Exit(0).
   381  	PanicOnError                         // Call panic with a descriptive error.
   382  )
   383  
   384  // A FlagSet represents a set of defined flags. The zero value of a FlagSet
   385  // has no name and has [ContinueOnError] error handling.
   386  //
   387  // [Flag] names must be unique within a FlagSet. An attempt to define a flag whose
   388  // name is already in use will cause a panic.
   389  type FlagSet struct {
   390  	// Usage is the function called when an error occurs while parsing flags.
   391  	// The field is a function (not a method) that may be changed to point to
   392  	// a custom error handler. What happens after Usage is called depends
   393  	// on the ErrorHandling setting; for the command line, this defaults
   394  	// to ExitOnError, which exits the program after calling Usage.
   395  	Usage func()
   396  
   397  	name          string
   398  	parsed        bool
   399  	actual        map[string]*Flag
   400  	formal        map[string]*Flag
   401  	args          []string // arguments after flags
   402  	errorHandling ErrorHandling
   403  	output        io.Writer         // nil means stderr; use Output() accessor
   404  	undef         map[string]string // flags which didn't exist at the time of Set
   405  }
   406  
   407  // A Flag represents the state of a flag.
   408  type Flag struct {
   409  	Name     string // name as it appears on command line
   410  	Usage    string // help message
   411  	Value    Value  // value as set
   412  	DefValue string // default value (as text); for usage message
   413  }
   414  
   415  // sortFlags returns the flags as a slice in lexicographical sorted order.
   416  func sortFlags(flags map[string]*Flag) []*Flag {
   417  	result := make([]*Flag, len(flags))
   418  	i := 0
   419  	for _, f := range flags {
   420  		result[i] = f
   421  		i++
   422  	}
   423  	slices.SortFunc(result, func(a, b *Flag) int {
   424  		return strings.Compare(a.Name, b.Name)
   425  	})
   426  	return result
   427  }
   428  
   429  // Output returns the destination for usage and error messages. [os.Stderr] is returned if
   430  // output was not set or was set to nil.
   431  func (f *FlagSet) Output() io.Writer {
   432  	if f.output == nil {
   433  		return os.Stderr
   434  	}
   435  	return f.output
   436  }
   437  
   438  // Name returns the name of the flag set.
   439  func (f *FlagSet) Name() string {
   440  	return f.name
   441  }
   442  
   443  // ErrorHandling returns the error handling behavior of the flag set.
   444  func (f *FlagSet) ErrorHandling() ErrorHandling {
   445  	return f.errorHandling
   446  }
   447  
   448  // SetOutput sets the destination for usage and error messages.
   449  // If output is nil, [os.Stderr] is used.
   450  func (f *FlagSet) SetOutput(output io.Writer) {
   451  	f.output = output
   452  }
   453  
   454  // VisitAll visits the flags in lexicographical order, calling fn for each.
   455  // It visits all flags, even those not set.
   456  func (f *FlagSet) VisitAll(fn func(*Flag)) {
   457  	for _, flag := range sortFlags(f.formal) {
   458  		fn(flag)
   459  	}
   460  }
   461  
   462  // VisitAll visits the command-line flags in lexicographical order, calling
   463  // fn for each. It visits all flags, even those not set.
   464  func VisitAll(fn func(*Flag)) {
   465  	CommandLine.VisitAll(fn)
   466  }
   467  
   468  // Visit visits the flags in lexicographical order, calling fn for each.
   469  // It visits only those flags that have been set.
   470  func (f *FlagSet) Visit(fn func(*Flag)) {
   471  	for _, flag := range sortFlags(f.actual) {
   472  		fn(flag)
   473  	}
   474  }
   475  
   476  // Visit visits the command-line flags in lexicographical order, calling fn
   477  // for each. It visits only those flags that have been set.
   478  func Visit(fn func(*Flag)) {
   479  	CommandLine.Visit(fn)
   480  }
   481  
   482  // Lookup returns the [Flag] structure of the named flag, returning nil if none exists.
   483  func (f *FlagSet) Lookup(name string) *Flag {
   484  	return f.formal[name]
   485  }
   486  
   487  // Lookup returns the [Flag] structure of the named command-line flag,
   488  // returning nil if none exists.
   489  func Lookup(name string) *Flag {
   490  	return CommandLine.formal[name]
   491  }
   492  
   493  // Set sets the value of the named flag.
   494  func (f *FlagSet) Set(name, value string) error {
   495  	return f.set(name, value)
   496  }
   497  func (f *FlagSet) set(name, value string) error {
   498  	flag, ok := f.formal[name]
   499  	if !ok {
   500  		// Remember that a flag that isn't defined is being set.
   501  		// We return an error in this case, but in addition if
   502  		// subsequently that flag is defined, we want to panic
   503  		// at the definition point.
   504  		// This is a problem which occurs if both the definition
   505  		// and the Set call are in init code and for whatever
   506  		// reason the init code changes evaluation order.
   507  		// See issue 57411.
   508  		_, file, line, ok := runtime.Caller(2)
   509  		if !ok {
   510  			file = "?"
   511  			line = 0
   512  		}
   513  		if f.undef == nil {
   514  			f.undef = map[string]string{}
   515  		}
   516  		f.undef[name] = fmt.Sprintf("%s:%d", file, line)
   517  
   518  		return fmt.Errorf("no such flag -%v", name)
   519  	}
   520  	err := flag.Value.Set(value)
   521  	if err != nil {
   522  		return err
   523  	}
   524  	if f.actual == nil {
   525  		f.actual = make(map[string]*Flag)
   526  	}
   527  	f.actual[name] = flag
   528  	return nil
   529  }
   530  
   531  // Set sets the value of the named command-line flag.
   532  func Set(name, value string) error {
   533  	return CommandLine.set(name, value)
   534  }
   535  
   536  // isZeroValue determines whether the string represents the zero
   537  // value for a flag.
   538  func isZeroValue(flag *Flag, value string) (ok bool, err error) {
   539  	// Build a zero value of the flag's Value type, and see if the
   540  	// result of calling its String method equals the value passed in.
   541  	// This works unless the Value type is itself an interface type.
   542  	typ := reflect.TypeOf(flag.Value)
   543  	var z reflect.Value
   544  	if typ.Kind() == reflect.Pointer {
   545  		z = reflect.New(typ.Elem())
   546  	} else {
   547  		z = reflect.Zero(typ)
   548  	}
   549  	// Catch panics calling the String method, which shouldn't prevent the
   550  	// usage message from being printed, but that we should report to the
   551  	// user so that they know to fix their code.
   552  	defer func() {
   553  		if e := recover(); e != nil {
   554  			if typ.Kind() == reflect.Pointer {
   555  				typ = typ.Elem()
   556  			}
   557  			err = fmt.Errorf("panic calling String method on zero %v for flag %s: %v", typ, flag.Name, e)
   558  		}
   559  	}()
   560  	return value == z.Interface().(Value).String(), nil
   561  }
   562  
   563  // UnquoteUsage extracts a back-quoted name from the usage
   564  // string for a flag and returns it and the un-quoted usage.
   565  // Given "a `name` to show" it returns ("name", "a name to show").
   566  // If there are no back quotes, the name is an educated guess of the
   567  // type of the flag's value, or the empty string if the flag is boolean.
   568  func UnquoteUsage(flag *Flag) (name string, usage string) {
   569  	// Look for a back-quoted name, but avoid the strings package.
   570  	usage = flag.Usage
   571  	for i := 0; i < len(usage); i++ {
   572  		if usage[i] == '`' {
   573  			for j := i + 1; j < len(usage); j++ {
   574  				if usage[j] == '`' {
   575  					name = usage[i+1 : j]
   576  					usage = usage[:i] + name + usage[j+1:]
   577  					return name, usage
   578  				}
   579  			}
   580  			break // Only one back quote; use type name.
   581  		}
   582  	}
   583  	// No explicit name, so use type if we can find one.
   584  	name = "value"
   585  	switch fv := flag.Value.(type) {
   586  	case boolFlag:
   587  		if fv.IsBoolFlag() {
   588  			name = ""
   589  		}
   590  	case *durationValue:
   591  		name = "duration"
   592  	case *float64Value:
   593  		name = "float"
   594  	case *intValue, *int64Value:
   595  		name = "int"
   596  	case *stringValue:
   597  		name = "string"
   598  	case *uintValue, *uint64Value:
   599  		name = "uint"
   600  	}
   601  	return
   602  }
   603  
   604  // PrintDefaults prints, to standard error unless configured otherwise, the
   605  // default values of all defined command-line flags in the set. See the
   606  // documentation for the global function PrintDefaults for more information.
   607  func (f *FlagSet) PrintDefaults() {
   608  	var isZeroValueErrs []error
   609  	f.VisitAll(func(flag *Flag) {
   610  		var b strings.Builder
   611  		fmt.Fprintf(&b, "  -%s", flag.Name) // Two spaces before -; see next two comments.
   612  		name, usage := UnquoteUsage(flag)
   613  		if len(name) > 0 {
   614  			b.WriteString(" ")
   615  			b.WriteString(name)
   616  		}
   617  		// Boolean flags of one ASCII letter are so common we
   618  		// treat them specially, putting their usage on the same line.
   619  		if b.Len() <= 4 { // space, space, '-', 'x'.
   620  			b.WriteString("\t")
   621  		} else {
   622  			// Four spaces before the tab triggers good alignment
   623  			// for both 4- and 8-space tab stops.
   624  			b.WriteString("\n    \t")
   625  		}
   626  		b.WriteString(strings.ReplaceAll(usage, "\n", "\n    \t"))
   627  
   628  		// Print the default value only if it differs to the zero value
   629  		// for this flag type.
   630  		if isZero, err := isZeroValue(flag, flag.DefValue); err != nil {
   631  			isZeroValueErrs = append(isZeroValueErrs, err)
   632  		} else if !isZero {
   633  			if _, ok := flag.Value.(*stringValue); ok {
   634  				// put quotes on the value
   635  				fmt.Fprintf(&b, " (default %q)", flag.DefValue)
   636  			} else {
   637  				fmt.Fprintf(&b, " (default %v)", flag.DefValue)
   638  			}
   639  		}
   640  		fmt.Fprint(f.Output(), b.String(), "\n")
   641  	})
   642  	// If calling String on any zero flag.Values triggered a panic, print
   643  	// the messages after the full set of defaults so that the programmer
   644  	// knows to fix the panic.
   645  	if errs := isZeroValueErrs; len(errs) > 0 {
   646  		fmt.Fprintln(f.Output())
   647  		for _, err := range errs {
   648  			fmt.Fprintln(f.Output(), err)
   649  		}
   650  	}
   651  }
   652  
   653  // PrintDefaults prints, to standard error unless configured otherwise,
   654  // a usage message showing the default settings of all defined
   655  // command-line flags.
   656  // For an integer valued flag x, the default output has the form
   657  //
   658  //	-x int
   659  //		usage-message-for-x (default 7)
   660  //
   661  // The usage message will appear on a separate line for anything but
   662  // a bool flag with a one-byte name. For bool flags, the type is
   663  // omitted and if the flag name is one byte the usage message appears
   664  // on the same line. The parenthetical default is omitted if the
   665  // default is the zero value for the type. The listed type, here int,
   666  // can be changed by placing a back-quoted name in the flag's usage
   667  // string; the first such item in the message is taken to be a parameter
   668  // name to show in the message and the back quotes are stripped from
   669  // the message when displayed. For instance, given
   670  //
   671  //	flag.String("I", "", "search `directory` for include files")
   672  //
   673  // the output will be
   674  //
   675  //	-I directory
   676  //		search directory for include files.
   677  //
   678  // To change the destination for flag messages, call [CommandLine].SetOutput.
   679  func PrintDefaults() {
   680  	CommandLine.PrintDefaults()
   681  }
   682  
   683  // defaultUsage is the default function to print a usage message.
   684  func (f *FlagSet) defaultUsage() {
   685  	if f.name == "" {
   686  		fmt.Fprintf(f.Output(), "Usage:\n")
   687  	} else {
   688  		fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name)
   689  	}
   690  	f.PrintDefaults()
   691  }
   692  
   693  // NOTE: Usage is not just defaultUsage(CommandLine)
   694  // because it serves (via godoc flag Usage) as the example
   695  // for how to write your own usage function.
   696  
   697  // Usage prints a usage message documenting all defined command-line flags
   698  // to [CommandLine]'s output, which by default is [os.Stderr].
   699  // It is called when an error occurs while parsing flags.
   700  // The function is a variable that may be changed to point to a custom function.
   701  // By default it prints a simple header and calls [PrintDefaults]; for details about the
   702  // format of the output and how to control it, see the documentation for [PrintDefaults].
   703  // Custom usage functions may choose to exit the program; by default exiting
   704  // happens anyway as the command line's error handling strategy is set to
   705  // [ExitOnError].
   706  var Usage = func() {
   707  	fmt.Fprintf(CommandLine.Output(), "Usage of %s:\n", os.Args[0])
   708  	PrintDefaults()
   709  }
   710  
   711  // NFlag returns the number of flags that have been set.
   712  func (f *FlagSet) NFlag() int { return len(f.actual) }
   713  
   714  // NFlag returns the number of command-line flags that have been set.
   715  func NFlag() int { return len(CommandLine.actual) }
   716  
   717  // Arg returns the i'th argument. Arg(0) is the first remaining argument
   718  // after flags have been processed. Arg returns an empty string if the
   719  // requested element does not exist.
   720  func (f *FlagSet) Arg(i int) string {
   721  	if i < 0 || i >= len(f.args) {
   722  		return ""
   723  	}
   724  	return f.args[i]
   725  }
   726  
   727  // Arg returns the i'th command-line argument. Arg(0) is the first remaining argument
   728  // after flags have been processed. Arg returns an empty string if the
   729  // requested element does not exist.
   730  func Arg(i int) string {
   731  	return CommandLine.Arg(i)
   732  }
   733  
   734  // NArg is the number of arguments remaining after flags have been processed.
   735  func (f *FlagSet) NArg() int { return len(f.args) }
   736  
   737  // NArg is the number of arguments remaining after flags have been processed.
   738  func NArg() int { return len(CommandLine.args) }
   739  
   740  // Args returns the non-flag arguments.
   741  func (f *FlagSet) Args() []string { return f.args }
   742  
   743  // Args returns the non-flag command-line arguments.
   744  func Args() []string { return CommandLine.args }
   745  
   746  // BoolVar defines a bool flag with specified name, default value, and usage string.
   747  // The argument p points to a bool variable in which to store the value of the flag.
   748  func (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string) {
   749  	f.Var(newBoolValue(value, p), name, usage)
   750  }
   751  
   752  // BoolVar defines a bool flag with specified name, default value, and usage string.
   753  // The argument p points to a bool variable in which to store the value of the flag.
   754  func BoolVar(p *bool, name string, value bool, usage string) {
   755  	CommandLine.Var(newBoolValue(value, p), name, usage)
   756  }
   757  
   758  // Bool defines a bool flag with specified name, default value, and usage string.
   759  // The return value is the address of a bool variable that stores the value of the flag.
   760  func (f *FlagSet) Bool(name string, value bool, usage string) *bool {
   761  	p := new(bool)
   762  	f.BoolVar(p, name, value, usage)
   763  	return p
   764  }
   765  
   766  // Bool defines a bool flag with specified name, default value, and usage string.
   767  // The return value is the address of a bool variable that stores the value of the flag.
   768  func Bool(name string, value bool, usage string) *bool {
   769  	return CommandLine.Bool(name, value, usage)
   770  }
   771  
   772  // IntVar defines an int flag with specified name, default value, and usage string.
   773  // The argument p points to an int variable in which to store the value of the flag.
   774  func (f *FlagSet) IntVar(p *int, name string, value int, usage string) {
   775  	f.Var(newIntValue(value, p), name, usage)
   776  }
   777  
   778  // IntVar defines an int flag with specified name, default value, and usage string.
   779  // The argument p points to an int variable in which to store the value of the flag.
   780  func IntVar(p *int, name string, value int, usage string) {
   781  	CommandLine.Var(newIntValue(value, p), name, usage)
   782  }
   783  
   784  // Int defines an int flag with specified name, default value, and usage string.
   785  // The return value is the address of an int variable that stores the value of the flag.
   786  func (f *FlagSet) Int(name string, value int, usage string) *int {
   787  	p := new(int)
   788  	f.IntVar(p, name, value, usage)
   789  	return p
   790  }
   791  
   792  // Int defines an int flag with specified name, default value, and usage string.
   793  // The return value is the address of an int variable that stores the value of the flag.
   794  func Int(name string, value int, usage string) *int {
   795  	return CommandLine.Int(name, value, usage)
   796  }
   797  
   798  // Int64Var defines an int64 flag with specified name, default value, and usage string.
   799  // The argument p points to an int64 variable in which to store the value of the flag.
   800  func (f *FlagSet) Int64Var(p *int64, name string, value int64, usage string) {
   801  	f.Var(newInt64Value(value, p), name, usage)
   802  }
   803  
   804  // Int64Var defines an int64 flag with specified name, default value, and usage string.
   805  // The argument p points to an int64 variable in which to store the value of the flag.
   806  func Int64Var(p *int64, name string, value int64, usage string) {
   807  	CommandLine.Var(newInt64Value(value, p), name, usage)
   808  }
   809  
   810  // Int64 defines an int64 flag with specified name, default value, and usage string.
   811  // The return value is the address of an int64 variable that stores the value of the flag.
   812  func (f *FlagSet) Int64(name string, value int64, usage string) *int64 {
   813  	p := new(int64)
   814  	f.Int64Var(p, name, value, usage)
   815  	return p
   816  }
   817  
   818  // Int64 defines an int64 flag with specified name, default value, and usage string.
   819  // The return value is the address of an int64 variable that stores the value of the flag.
   820  func Int64(name string, value int64, usage string) *int64 {
   821  	return CommandLine.Int64(name, value, usage)
   822  }
   823  
   824  // UintVar defines a uint flag with specified name, default value, and usage string.
   825  // The argument p points to a uint variable in which to store the value of the flag.
   826  func (f *FlagSet) UintVar(p *uint, name string, value uint, usage string) {
   827  	f.Var(newUintValue(value, p), name, usage)
   828  }
   829  
   830  // UintVar defines a uint flag with specified name, default value, and usage string.
   831  // The argument p points to a uint variable in which to store the value of the flag.
   832  func UintVar(p *uint, name string, value uint, usage string) {
   833  	CommandLine.Var(newUintValue(value, p), name, usage)
   834  }
   835  
   836  // Uint defines a uint flag with specified name, default value, and usage string.
   837  // The return value is the address of a uint variable that stores the value of the flag.
   838  func (f *FlagSet) Uint(name string, value uint, usage string) *uint {
   839  	p := new(uint)
   840  	f.UintVar(p, name, value, usage)
   841  	return p
   842  }
   843  
   844  // Uint defines a uint flag with specified name, default value, and usage string.
   845  // The return value is the address of a uint variable that stores the value of the flag.
   846  func Uint(name string, value uint, usage string) *uint {
   847  	return CommandLine.Uint(name, value, usage)
   848  }
   849  
   850  // Uint64Var defines a uint64 flag with specified name, default value, and usage string.
   851  // The argument p points to a uint64 variable in which to store the value of the flag.
   852  func (f *FlagSet) Uint64Var(p *uint64, name string, value uint64, usage string) {
   853  	f.Var(newUint64Value(value, p), name, usage)
   854  }
   855  
   856  // Uint64Var defines a uint64 flag with specified name, default value, and usage string.
   857  // The argument p points to a uint64 variable in which to store the value of the flag.
   858  func Uint64Var(p *uint64, name string, value uint64, usage string) {
   859  	CommandLine.Var(newUint64Value(value, p), name, usage)
   860  }
   861  
   862  // Uint64 defines a uint64 flag with specified name, default value, and usage string.
   863  // The return value is the address of a uint64 variable that stores the value of the flag.
   864  func (f *FlagSet) Uint64(name string, value uint64, usage string) *uint64 {
   865  	p := new(uint64)
   866  	f.Uint64Var(p, name, value, usage)
   867  	return p
   868  }
   869  
   870  // Uint64 defines a uint64 flag with specified name, default value, and usage string.
   871  // The return value is the address of a uint64 variable that stores the value of the flag.
   872  func Uint64(name string, value uint64, usage string) *uint64 {
   873  	return CommandLine.Uint64(name, value, usage)
   874  }
   875  
   876  // StringVar defines a string flag with specified name, default value, and usage string.
   877  // The argument p points to a string variable in which to store the value of the flag.
   878  func (f *FlagSet) StringVar(p *string, name string, value string, usage string) {
   879  	f.Var(newStringValue(value, p), name, usage)
   880  }
   881  
   882  // StringVar defines a string flag with specified name, default value, and usage string.
   883  // The argument p points to a string variable in which to store the value of the flag.
   884  func StringVar(p *string, name string, value string, usage string) {
   885  	CommandLine.Var(newStringValue(value, p), name, usage)
   886  }
   887  
   888  // String defines a string flag with specified name, default value, and usage string.
   889  // The return value is the address of a string variable that stores the value of the flag.
   890  func (f *FlagSet) String(name string, value string, usage string) *string {
   891  	p := new(string)
   892  	f.StringVar(p, name, value, usage)
   893  	return p
   894  }
   895  
   896  // String defines a string flag with specified name, default value, and usage string.
   897  // The return value is the address of a string variable that stores the value of the flag.
   898  func String(name string, value string, usage string) *string {
   899  	return CommandLine.String(name, value, usage)
   900  }
   901  
   902  // Float64Var defines a float64 flag with specified name, default value, and usage string.
   903  // The argument p points to a float64 variable in which to store the value of the flag.
   904  func (f *FlagSet) Float64Var(p *float64, name string, value float64, usage string) {
   905  	f.Var(newFloat64Value(value, p), name, usage)
   906  }
   907  
   908  // Float64Var defines a float64 flag with specified name, default value, and usage string.
   909  // The argument p points to a float64 variable in which to store the value of the flag.
   910  func Float64Var(p *float64, name string, value float64, usage string) {
   911  	CommandLine.Var(newFloat64Value(value, p), name, usage)
   912  }
   913  
   914  // Float64 defines a float64 flag with specified name, default value, and usage string.
   915  // The return value is the address of a float64 variable that stores the value of the flag.
   916  func (f *FlagSet) Float64(name string, value float64, usage string) *float64 {
   917  	p := new(float64)
   918  	f.Float64Var(p, name, value, usage)
   919  	return p
   920  }
   921  
   922  // Float64 defines a float64 flag with specified name, default value, and usage string.
   923  // The return value is the address of a float64 variable that stores the value of the flag.
   924  func Float64(name string, value float64, usage string) *float64 {
   925  	return CommandLine.Float64(name, value, usage)
   926  }
   927  
   928  // DurationVar defines a time.Duration flag with specified name, default value, and usage string.
   929  // The argument p points to a time.Duration variable in which to store the value of the flag.
   930  // The flag accepts a value acceptable to time.ParseDuration.
   931  func (f *FlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
   932  	f.Var(newDurationValue(value, p), name, 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 DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
   939  	CommandLine.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  // Duration defines a time.Duration flag with specified name, default value, and usage string.
   952  // The return value is the address of a time.Duration variable that stores the value of the flag.
   953  // The flag accepts a value acceptable to time.ParseDuration.
   954  func Duration(name string, value time.Duration, usage string) *time.Duration {
   955  	return CommandLine.Duration(name, value, usage)
   956  }
   957  
   958  // TextVar defines a flag with a specified name, default value, and usage string.
   959  // The argument p must be a pointer to a variable that will hold the value
   960  // of the flag, and p must implement encoding.TextUnmarshaler.
   961  // If the flag is used, the flag value will be passed to p's UnmarshalText method.
   962  // The type of the default value must be the same as the type of p.
   963  func (f *FlagSet) TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) {
   964  	f.Var(newTextValue(value, p), name, usage)
   965  }
   966  
   967  // TextVar defines a flag with a specified name, default value, and usage string.
   968  // The argument p must be a pointer to a variable that will hold the value
   969  // of the flag, and p must implement encoding.TextUnmarshaler.
   970  // If the flag is used, the flag value will be passed to p's UnmarshalText method.
   971  // The type of the default value must be the same as the type of p.
   972  func TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) {
   973  	CommandLine.Var(newTextValue(value, p), name, usage)
   974  }
   975  
   976  // Func defines a flag with the specified name and usage string.
   977  // Each time the flag is seen, fn is called with the value of the flag.
   978  // If fn returns a non-nil error, it will be treated as a flag value parsing error.
   979  func (f *FlagSet) Func(name, usage string, fn func(string) error) {
   980  	f.Var(funcValue(fn), name, usage)
   981  }
   982  
   983  // Func defines a flag with the specified name and usage string.
   984  // Each time the flag is seen, fn is called with the value of the flag.
   985  // If fn returns a non-nil error, it will be treated as a flag value parsing error.
   986  func Func(name, usage string, fn func(string) error) {
   987  	CommandLine.Func(name, usage, fn)
   988  }
   989  
   990  // BoolFunc defines a flag with the specified name and usage string without requiring values.
   991  // Each time the flag is seen, fn is called with the value of the flag.
   992  // If fn returns a non-nil error, it will be treated as a flag value parsing error.
   993  func (f *FlagSet) BoolFunc(name, usage string, fn func(string) error) {
   994  	f.Var(boolFuncValue(fn), name, usage)
   995  }
   996  
   997  // BoolFunc defines a flag with the specified name and usage string without requiring values.
   998  // Each time the flag is seen, fn is called with the value of the flag.
   999  // If fn returns a non-nil error, it will be treated as a flag value parsing error.
  1000  func BoolFunc(name, usage string, fn func(string) error) {
  1001  	CommandLine.BoolFunc(name, usage, fn)
  1002  }
  1003  
  1004  // Var defines a flag with the specified name and usage string. The type and
  1005  // value of the flag are represented by the first argument, of type [Value], which
  1006  // typically holds a user-defined implementation of [Value]. For instance, the
  1007  // caller could create a flag that turns a comma-separated string into a slice
  1008  // of strings by giving the slice the methods of [Value]; in particular, [Set] would
  1009  // decompose the comma-separated string into the slice.
  1010  func (f *FlagSet) Var(value Value, name string, usage string) {
  1011  	// Flag must not begin "-" or contain "=".
  1012  	if strings.HasPrefix(name, "-") {
  1013  		panic(f.sprintf("flag %q begins with -", name))
  1014  	} else if strings.Contains(name, "=") {
  1015  		panic(f.sprintf("flag %q contains =", name))
  1016  	}
  1017  
  1018  	// Remember the default value as a string; it won't change.
  1019  	flag := &Flag{name, usage, value, value.String()}
  1020  	_, alreadythere := f.formal[name]
  1021  	if alreadythere {
  1022  		var msg string
  1023  		if f.name == "" {
  1024  			msg = f.sprintf("flag redefined: %s", name)
  1025  		} else {
  1026  			msg = f.sprintf("%s flag redefined: %s", f.name, name)
  1027  		}
  1028  		panic(msg) // Happens only if flags are declared with identical names
  1029  	}
  1030  	if pos := f.undef[name]; pos != "" {
  1031  		panic(fmt.Sprintf("flag %s set at %s before being defined", name, pos))
  1032  	}
  1033  	if f.formal == nil {
  1034  		f.formal = make(map[string]*Flag)
  1035  	}
  1036  	f.formal[name] = flag
  1037  }
  1038  
  1039  // Var defines a flag with the specified name and usage string. The type and
  1040  // value of the flag are represented by the first argument, of type [Value], which
  1041  // typically holds a user-defined implementation of [Value]. For instance, the
  1042  // caller could create a flag that turns a comma-separated string into a slice
  1043  // of strings by giving the slice the methods of [Value]; in particular, [Set] would
  1044  // decompose the comma-separated string into the slice.
  1045  func Var(value Value, name string, usage string) {
  1046  	CommandLine.Var(value, name, usage)
  1047  }
  1048  
  1049  // sprintf formats the message, prints it to output, and returns it.
  1050  func (f *FlagSet) sprintf(format string, a ...any) string {
  1051  	msg := fmt.Sprintf(format, a...)
  1052  	fmt.Fprintln(f.Output(), msg)
  1053  	return msg
  1054  }
  1055  
  1056  // failf prints to standard error a formatted error and usage message and
  1057  // returns the error.
  1058  func (f *FlagSet) failf(format string, a ...any) error {
  1059  	msg := f.sprintf(format, a...)
  1060  	f.usage()
  1061  	return errors.New(msg)
  1062  }
  1063  
  1064  // usage calls the Usage method for the flag set if one is specified,
  1065  // or the appropriate default usage function otherwise.
  1066  func (f *FlagSet) usage() {
  1067  	if f.Usage == nil {
  1068  		f.defaultUsage()
  1069  	} else {
  1070  		f.Usage()
  1071  	}
  1072  }
  1073  
  1074  // parseOne parses one flag. It reports whether a flag was seen.
  1075  func (f *FlagSet) parseOne() (bool, error) {
  1076  	if len(f.args) == 0 {
  1077  		return false, nil
  1078  	}
  1079  	s := f.args[0]
  1080  	if len(s) < 2 || s[0] != '-' {
  1081  		return false, nil
  1082  	}
  1083  	numMinuses := 1
  1084  	if s[1] == '-' {
  1085  		numMinuses++
  1086  		if len(s) == 2 { // "--" terminates the flags
  1087  			f.args = f.args[1:]
  1088  			return false, nil
  1089  		}
  1090  	}
  1091  	name := s[numMinuses:]
  1092  	if len(name) == 0 || name[0] == '-' || name[0] == '=' {
  1093  		return false, f.failf("bad flag syntax: %s", s)
  1094  	}
  1095  
  1096  	// it's a flag. does it have an argument?
  1097  	f.args = f.args[1:]
  1098  	hasValue := false
  1099  	value := ""
  1100  	for i := 1; i < len(name); i++ { // equals cannot be first
  1101  		if name[i] == '=' {
  1102  			value = name[i+1:]
  1103  			hasValue = true
  1104  			name = name[0:i]
  1105  			break
  1106  		}
  1107  	}
  1108  
  1109  	flag, ok := f.formal[name]
  1110  	if !ok {
  1111  		if name == "help" || name == "h" { // special case for nice help message.
  1112  			f.usage()
  1113  			return false, ErrHelp
  1114  		}
  1115  		return false, f.failf("flag provided but not defined: -%s", name)
  1116  	}
  1117  
  1118  	if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg
  1119  		if hasValue {
  1120  			if err := fv.Set(value); err != nil {
  1121  				return false, f.failf("invalid boolean value %q for -%s: %v", value, name, err)
  1122  			}
  1123  		} else {
  1124  			if err := fv.Set("true"); err != nil {
  1125  				return false, f.failf("invalid boolean flag %s: %v", name, err)
  1126  			}
  1127  		}
  1128  	} else {
  1129  		// It must have a value, which might be the next argument.
  1130  		if !hasValue && len(f.args) > 0 {
  1131  			// value is the next arg
  1132  			hasValue = true
  1133  			value, f.args = f.args[0], f.args[1:]
  1134  		}
  1135  		if !hasValue {
  1136  			return false, f.failf("flag needs an argument: -%s", name)
  1137  		}
  1138  		if err := flag.Value.Set(value); err != nil {
  1139  			return false, f.failf("invalid value %q for flag -%s: %v", value, name, err)
  1140  		}
  1141  	}
  1142  	if f.actual == nil {
  1143  		f.actual = make(map[string]*Flag)
  1144  	}
  1145  	f.actual[name] = flag
  1146  	return true, nil
  1147  }
  1148  
  1149  // Parse parses flag definitions from the argument list, which should not
  1150  // include the command name. Must be called after all flags in the [FlagSet]
  1151  // are defined and before flags are accessed by the program.
  1152  // The return value will be [ErrHelp] if -help or -h were set but not defined.
  1153  func (f *FlagSet) Parse(arguments []string) error {
  1154  	f.parsed = true
  1155  	f.args = arguments
  1156  	for {
  1157  		seen, err := f.parseOne()
  1158  		if seen {
  1159  			continue
  1160  		}
  1161  		if err == nil {
  1162  			break
  1163  		}
  1164  		switch f.errorHandling {
  1165  		case ContinueOnError:
  1166  			return err
  1167  		case ExitOnError:
  1168  			if err == ErrHelp {
  1169  				os.Exit(0)
  1170  			}
  1171  			os.Exit(2)
  1172  		case PanicOnError:
  1173  			panic(err)
  1174  		}
  1175  	}
  1176  	return nil
  1177  }
  1178  
  1179  // Parsed reports whether f.Parse has been called.
  1180  func (f *FlagSet) Parsed() bool {
  1181  	return f.parsed
  1182  }
  1183  
  1184  // Parse parses the command-line flags from [os.Args][1:]. Must be called
  1185  // after all flags are defined and before flags are accessed by the program.
  1186  func Parse() {
  1187  	// Ignore errors; CommandLine is set for ExitOnError.
  1188  	CommandLine.Parse(os.Args[1:])
  1189  }
  1190  
  1191  // Parsed reports whether the command-line flags have been parsed.
  1192  func Parsed() bool {
  1193  	return CommandLine.Parsed()
  1194  }
  1195  
  1196  // CommandLine is the default set of command-line flags, parsed from [os.Args].
  1197  // The top-level functions such as [BoolVar], [Arg], and so on are wrappers for the
  1198  // methods of CommandLine.
  1199  var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
  1200  
  1201  func init() {
  1202  	// Override generic FlagSet default Usage with call to global Usage.
  1203  	// Note: This is not CommandLine.Usage = Usage,
  1204  	// because we want any eventual call to use any updated value of Usage,
  1205  	// not the value it has when this line is run.
  1206  	CommandLine.Usage = commandLineUsage
  1207  }
  1208  
  1209  func commandLineUsage() {
  1210  	Usage()
  1211  }
  1212  
  1213  // NewFlagSet returns a new, empty flag set with the specified name and
  1214  // error handling property. If the name is not empty, it will be printed
  1215  // in the default usage message and in error messages.
  1216  func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
  1217  	f := &FlagSet{
  1218  		name:          name,
  1219  		errorHandling: errorHandling,
  1220  	}
  1221  	f.Usage = f.defaultUsage
  1222  	return f
  1223  }
  1224  
  1225  // Init sets the name and error handling property for a flag set.
  1226  // By default, the zero [FlagSet] uses an empty name and the
  1227  // [ContinueOnError] error handling policy.
  1228  func (f *FlagSet) Init(name string, errorHandling ErrorHandling) {
  1229  	f.name = name
  1230  	f.errorHandling = errorHandling
  1231  }
  1232  

View as plain text