diff options
Diffstat (limited to 'libgo/go/flag/flag.go')
-rw-r--r-- | libgo/go/flag/flag.go | 151 |
1 files changed, 125 insertions, 26 deletions
diff --git a/libgo/go/flag/flag.go b/libgo/go/flag/flag.go index 60aef5d806c..3abc80e9c67 100644 --- a/libgo/go/flag/flag.go +++ b/libgo/go/flag/flag.go @@ -31,7 +31,7 @@ fmt.Println("ip has value ", *ip) fmt.Println("flagvar has value ", flagvar) - After parsing, the arguments after the flag are available as the + After parsing, the arguments following the flags are available as the slice flag.Args() or individually as flag.Arg(i). The arguments are indexed from 0 through flag.NArg()-1. @@ -235,6 +235,8 @@ func (d *durationValue) String() string { return (*time.Duration)(d).String() } // If a Value has an IsBoolFlag() bool method returning true, // the command-line parser makes -name equivalent to -name=true // rather than using the next command-line argument. +// +// Set is called once, in command line order, for each flag present. type Value interface { String() string Set(string) error @@ -249,13 +251,14 @@ type Getter interface { Get() interface{} } -// ErrorHandling defines how to handle flag parsing errors. +// ErrorHandling defines how FlagSet.Parse behaves if the parse fails. type ErrorHandling int +// These constants cause FlagSet.Parse to behave as described if the parse fails. const ( - ContinueOnError ErrorHandling = iota - ExitOnError - PanicOnError + ContinueOnError ErrorHandling = iota // Return a descriptive error. + ExitOnError // Call os.Exit(2). + PanicOnError // Call panic with a descriptive error. ) // A FlagSet represents a set of defined flags. The zero value of a FlagSet @@ -373,20 +376,110 @@ func Set(name, value string) error { return CommandLine.Set(name, value) } -// PrintDefaults prints, to standard error unless configured -// otherwise, the default values of all defined flags in the set. +// isZeroValue guesses whether the string represents the zero +// value for a flag. It is not accurate but in practice works OK. +func isZeroValue(value string) bool { + switch value { + case "false": + return true + case "": + return true + case "0": + return true + } + return false +} + +// UnquoteUsage extracts a back-quoted name from the usage +// string for a flag and returns it and the un-quoted usage. +// Given "a `name` to show" it returns ("name", "a name to show"). +// If there are no back quotes, the name is an educated guess of the +// type of the flag's value, or the empty string if the flag is boolean. +func UnquoteUsage(flag *Flag) (name string, usage string) { + // Look for a back-quoted name, but avoid the strings package. + usage = flag.Usage + for i := 0; i < len(usage); i++ { + if usage[i] == '`' { + for j := i + 1; j < len(usage); j++ { + if usage[j] == '`' { + name = usage[i+1 : j] + usage = usage[:i] + name + usage[j+1:] + return name, usage + } + } + break // Only one back quote; use type name. + } + } + // No explicit name, so use type if we can find one. + name = "value" + switch flag.Value.(type) { + case boolFlag: + name = "" + case *durationValue: + name = "duration" + case *float64Value: + name = "float" + case *intValue, *int64Value: + name = "int" + case *stringValue: + name = "string" + case *uintValue, *uint64Value: + name = "uint" + } + return +} + +// PrintDefaults prints to standard error the default values of all +// defined command-line flags in the set. See the documentation for +// the global function PrintDefaults for more information. func (f *FlagSet) PrintDefaults() { f.VisitAll(func(flag *Flag) { - format := " -%s=%s: %s\n" - if _, ok := flag.Value.(*stringValue); ok { - // put quotes on the value - format = " -%s=%q: %s\n" + s := fmt.Sprintf(" -%s", flag.Name) // Two spaces before -; see next two comments. + name, usage := UnquoteUsage(flag) + if len(name) > 0 { + s += " " + name + } + // Boolean flags of one ASCII letter are so common we + // treat them specially, putting their usage on the same line. + if len(s) <= 4 { // space, space, '-', 'x'. + s += "\t" + } else { + // Four spaces before the tab triggers good alignment + // for both 4- and 8-space tab stops. + s += "\n \t" } - fmt.Fprintf(f.out(), format, flag.Name, flag.DefValue, flag.Usage) + s += usage + if !isZeroValue(flag.DefValue) { + if _, ok := flag.Value.(*stringValue); ok { + // put quotes on the value + s += fmt.Sprintf(" (default %q)", flag.DefValue) + } else { + s += fmt.Sprintf(" (default %v)", flag.DefValue) + } + } + fmt.Fprint(f.out(), s, "\n") }) } -// PrintDefaults prints to standard error the default values of all defined command-line flags. +// PrintDefaults prints, to standard error unless configured otherwise, +// a usage message showing the default settings of all defined +// command-line flags. +// For an integer valued flag x, the default output has the form +// -x int +// usage-message-for-x (default 7) +// The usage message will appear on a separate line for anything but +// a bool flag with a one-byte name. For bool flags, the type is +// omitted and if the flag name is one byte the usage message appears +// on the same line. The parenthetical default is omitted if the +// default is the zero value for the type. The listed type, here int, +// can be changed by placing a back-quoted name in the flag's usage +// string; the first such item in the message is taken to be a parameter +// name to show in the message and the back quotes are stripped from +// the message when displayed. For instance, given +// flag.String("I", "", "search `directory` for include files") +// the output will be +// -I directory +// search directory for include files. func PrintDefaults() { CommandLine.PrintDefaults() } @@ -408,6 +501,8 @@ func defaultUsage(f *FlagSet) { // Usage prints to standard error a usage message documenting all defined command-line flags. // It is called when an error occurs while parsing flags. // The function is a variable that may be changed to point to a custom function. +// By default it prints a simple header and calls PrintDefaults; for details about the +// format of the output and how to control it, see the documentation for PrintDefaults. var Usage = func() { fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) PrintDefaults() @@ -420,7 +515,8 @@ func (f *FlagSet) NFlag() int { return len(f.actual) } func NFlag() int { return len(CommandLine.actual) } // Arg returns the i'th argument. Arg(0) is the first remaining argument -// after flags have been processed. +// after flags have been processed. Arg returns an empty string if the +// requested element does not exist. func (f *FlagSet) Arg(i int) string { if i < 0 || i >= len(f.args) { return "" @@ -429,7 +525,8 @@ func (f *FlagSet) Arg(i int) string { } // Arg returns the i'th command-line argument. Arg(0) is the first remaining argument -// after flags have been processed. +// after flags have been processed. Arg returns an empty string if the +// requested element does not exist. func Arg(i int) string { return CommandLine.Arg(i) } @@ -726,27 +823,27 @@ func (f *FlagSet) parseOne() (bool, error) { if len(s) == 0 || s[0] != '-' || len(s) == 1 { return false, nil } - num_minuses := 1 + numMinuses := 1 if s[1] == '-' { - num_minuses++ + numMinuses++ if len(s) == 2 { // "--" terminates the flags f.args = f.args[1:] return false, nil } } - name := s[num_minuses:] + name := s[numMinuses:] if len(name) == 0 || name[0] == '-' || name[0] == '=' { return false, f.failf("bad flag syntax: %s", s) } // it's a flag. does it have an argument? f.args = f.args[1:] - has_value := false + hasValue := false value := "" for i := 1; i < len(name); i++ { // equals cannot be first if name[i] == '=' { value = name[i+1:] - has_value = true + hasValue = true name = name[0:i] break } @@ -762,21 +859,23 @@ func (f *FlagSet) parseOne() (bool, error) { } if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg - if has_value { + if hasValue { if err := fv.Set(value); err != nil { return false, f.failf("invalid boolean value %q for -%s: %v", value, name, err) } } else { - fv.Set("true") + if err := fv.Set("true"); err != nil { + return false, f.failf("invalid boolean flag %s: %v", name, err) + } } } else { // It must have a value, which might be the next argument. - if !has_value && len(f.args) > 0 { + if !hasValue && len(f.args) > 0 { // value is the next arg - has_value = true + hasValue = true value, f.args = f.args[0], f.args[1:] } - if !has_value { + if !hasValue { return false, f.failf("flag needs an argument: -%s", name) } if err := flag.Value.Set(value); err != nil { @@ -829,7 +928,7 @@ func Parse() { CommandLine.Parse(os.Args[1:]) } -// Parsed returns true if the command-line flags have been parsed. +// Parsed reports whether the command-line flags have been parsed. func Parsed() bool { return CommandLine.Parsed() } |