Merge remote-tracking branch 'ogier/master' into merge Conflicts: bool_test.go flag.go flag_test.go
diff --git a/bool.go b/bool.go index 617971a..70e2e0a 100644 --- a/bool.go +++ b/bool.go
@@ -26,6 +26,10 @@ return err } +func (b *boolValue) Type() string { + return "bool" +} + func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) } func (b *boolValue) IsBoolFlag() bool { return true }
diff --git a/duration.go b/duration.go index db59463..66ed7ac 100644 --- a/duration.go +++ b/duration.go
@@ -16,15 +16,12 @@ return err } -func (d *durationValue) String() string { return (*time.Duration)(d).String() } - -// Value is the interface to the dynamic value stored in a flag. -// (The default value is represented as a string.) -type Value interface { - String() string - Set(string) error +func (d *durationValue) Type() string { + return "duration" } +func (d *durationValue) String() string { return (*time.Duration)(d).String() } + // DurationVar defines a time.Duration flag with specified name, default value, and usage string. // The argument p points to a time.Duration variable in which to store the value of the flag. func (f *FlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
diff --git a/example_test.go b/example_test.go index 03ebeaa..9be7a49 100644 --- a/example_test.go +++ b/example_test.go
@@ -11,7 +11,7 @@ "strings" "time" - flag "github.com/ogier/pflag" + flag "github.com/spf13/pflag" ) // Example 1: A single string flag called "species" with default value "gopher". @@ -29,6 +29,10 @@ return fmt.Sprint(*i) } +func (i *interval) Type() string { + return "interval" +} + // Set is the method to set the flag value, part of the flag.Value interface. // Set's argument is a string to be parsed to set the flag. // It's a comma-separated list, so we split it.
diff --git a/flag.go b/flag.go index f383058..55594df 100644 --- a/flag.go +++ b/flag.go
@@ -99,6 +99,7 @@ package pflag import ( + "bytes" "errors" "fmt" "io" @@ -119,6 +120,10 @@ PanicOnError ) +// NormalizedName is a flag name that has been normalized according to rules +// for the FlagSet (e.g. making '-' and '_' equivalent). +type NormalizedName string + // A FlagSet represents a set of defined flags. type FlagSet struct { // Usage is the function called when an error occurs while parsing flags. @@ -126,43 +131,75 @@ // a custom error handler. Usage func() - name string - parsed bool - actual map[string]*Flag - formal map[string]*Flag - shorthands map[byte]*Flag - args []string // arguments after flags - exitOnError bool // does the program exit if there's an error? - errorHandling ErrorHandling - output io.Writer // nil means stderr; use out() accessor - interspersed bool // allow interspersed option/non-option args + name string + parsed bool + actual map[NormalizedName]*Flag + formal map[NormalizedName]*Flag + shorthands map[byte]*Flag + args []string // arguments after flags + exitOnError bool // does the program exit if there's an error? + errorHandling ErrorHandling + output io.Writer // nil means stderr; use out() accessor + interspersed bool // allow interspersed option/non-option args + normalizeNameFunc func(f *FlagSet, name string) NormalizedName } // A Flag represents the state of a flag. type Flag struct { - Name string // name as it appears on command line - Shorthand string // one-letter abbreviated flag - Usage string // help message - Value Value // value as set - DefValue string // default value (as text); for usage message + Name string // name as it appears on command line + Shorthand string // one-letter abbreviated flag + Usage string // help message + Value Value // value as set + DefValue string // default value (as text); for usage message + Changed bool // If the user set the value (or if left to default) + Deprecated string // If this flag is deprecated, this string is the new or now thing to use + Annotations map[string][]string // used by cobra.Command bash autocomple code +} + +// Value is the interface to the dynamic value stored in a flag. +// (The default value is represented as a string.) +type Value interface { + String() string + Set(string) error + Type() string } // sortFlags returns the flags as a slice in lexicographical sorted order. -func sortFlags(flags map[string]*Flag) []*Flag { +func sortFlags(flags map[NormalizedName]*Flag) []*Flag { list := make(sort.StringSlice, len(flags)) i := 0 - for _, f := range flags { - list[i] = f.Name + for k := range flags { + list[i] = string(k) i++ } list.Sort() result := make([]*Flag, len(list)) for i, name := range list { - result[i] = flags[name] + result[i] = flags[NormalizedName(name)] } return result } +func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) { + f.normalizeNameFunc = n + for k, v := range f.formal { + delete(f.formal, k) + f.formal[f.normalizeFlagName(string(k))] = v + } +} + +func (f *FlagSet) GetNormalizeFunc() func(f *FlagSet, name string) NormalizedName { + if f.normalizeNameFunc != nil { + return f.normalizeNameFunc + } + return func(f *FlagSet, name string) NormalizedName { return NormalizedName(name) } +} + +func (f *FlagSet) normalizeFlagName(name string) NormalizedName { + n := f.GetNormalizeFunc() + return n(f, name) +} + func (f *FlagSet) out() io.Writer { if f.output == nil { return os.Stderr @@ -184,6 +221,10 @@ } } +func (f *FlagSet) HasFlags() bool { + return len(f.formal) > 0 +} + // VisitAll visits the command-line flags in lexicographical order, calling // fn for each. It visits all flags, even those not set. func VisitAll(fn func(*Flag)) { @@ -206,18 +247,34 @@ // Lookup returns the Flag structure of the named flag, returning nil if none exists. func (f *FlagSet) Lookup(name string) *Flag { + return f.lookup(f.normalizeFlagName(name)) +} + +// lookup returns the Flag structure of the named flag, returning nil if none exists. +func (f *FlagSet) lookup(name NormalizedName) *Flag { return f.formal[name] } +// Mark a flag deprecated in your program +func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error { + flag := f.Lookup(name) + if flag == nil { + return fmt.Errorf("flag %q does not exist", name) + } + flag.Deprecated = usageMessage + return nil +} + // Lookup returns the Flag structure of the named command-line flag, // returning nil if none exists. func Lookup(name string) *Flag { - return CommandLine.formal[name] + return CommandLine.Lookup(name) } // Set sets the value of the named flag. func (f *FlagSet) Set(name, value string) error { - flag, ok := f.formal[name] + normalName := f.normalizeFlagName(name) + flag, ok := f.formal[normalName] if !ok { return fmt.Errorf("no such flag -%v", name) } @@ -226,9 +283,13 @@ return err } if f.actual == nil { - f.actual = make(map[string]*Flag) + f.actual = make(map[NormalizedName]*Flag) } - f.actual[name] = flag + f.actual[normalName] = flag + flag.Changed = true + if len(flag.Deprecated) > 0 { + fmt.Fprintf(os.Stderr, "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) + } return nil } @@ -241,6 +302,9 @@ // otherwise, the default values of all defined flags in the set. func (f *FlagSet) PrintDefaults() { f.VisitAll(func(flag *Flag) { + if len(flag.Deprecated) > 0 { + return + } format := "--%s=%s: %s\n" if _, ok := flag.Value.(*stringValue); ok { // put quotes on the value @@ -255,6 +319,29 @@ }) } +func (f *FlagSet) FlagUsages() string { + x := new(bytes.Buffer) + + f.VisitAll(func(flag *Flag) { + if len(flag.Deprecated) > 0 { + return + } + format := "--%s=%s: %s\n" + if _, ok := flag.Value.(*stringValue); ok { + // put quotes on the value + format = "--%s=%q: %s\n" + } + if len(flag.Shorthand) > 0 { + format = " -%s, " + format + } else { + format = " %s " + format + } + fmt.Fprintf(x, format, flag.Shorthand, flag.Name, flag.DefValue, flag.Usage) + }) + + return x.String() +} + // PrintDefaults prints to standard error the default values of all defined command-line flags. func PrintDefaults() { CommandLine.PrintDefaults() @@ -323,32 +410,42 @@ // Like Var, but accepts a shorthand letter that can be used after a single dash. func (f *FlagSet) VarP(value Value, name, shorthand, usage string) { // Remember the default value as a string; it won't change. - flag := &Flag{name, shorthand, usage, value, value.String()} - _, alreadythere := f.formal[name] + flag := &Flag{ + Name: name, + Shorthand: shorthand, + Usage: usage, + Value: value, + DefValue: value.String(), + } + f.AddFlag(flag) +} + +func (f *FlagSet) AddFlag(flag *Flag) { + _, alreadythere := f.formal[f.normalizeFlagName(flag.Name)] if alreadythere { - msg := fmt.Sprintf("%s flag redefined: %s", f.name, name) + msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name) fmt.Fprintln(f.out(), msg) panic(msg) // Happens only if flags are declared with identical names } if f.formal == nil { - f.formal = make(map[string]*Flag) + f.formal = make(map[NormalizedName]*Flag) } - f.formal[name] = flag + f.formal[f.normalizeFlagName(flag.Name)] = flag - if len(shorthand) == 0 { + if len(flag.Shorthand) == 0 { return } - if len(shorthand) > 1 { - fmt.Fprintf(f.out(), "%s shorthand more than ASCII character: %s\n", f.name, shorthand) + if len(flag.Shorthand) > 1 { + fmt.Fprintf(f.out(), "%s shorthand more than ASCII character: %s\n", f.name, flag.Shorthand) panic("shorthand is more than one character") } if f.shorthands == nil { f.shorthands = make(map[byte]*Flag) } - c := shorthand[0] + c := flag.Shorthand[0] old, alreadythere := f.shorthands[c] if alreadythere { - fmt.Fprintf(f.out(), "%s shorthand reused: %q for %s already used for %s\n", f.name, c, name, old.Name) + fmt.Fprintf(f.out(), "%s shorthand reused: %q for %s already used for %s\n", f.name, c, flag.Name, old.Name) panic("shorthand redefinition") } f.shorthands[c] = flag @@ -396,14 +493,104 @@ } // mark as visited for Visit() if f.actual == nil { - f.actual = make(map[string]*Flag) + f.actual = make(map[NormalizedName]*Flag) } - f.actual[flag.Name] = flag - + f.actual[f.normalizeFlagName(flag.Name)] = flag + flag.Changed = true + if len(flag.Deprecated) > 0 { + fmt.Fprintf(os.Stderr, "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) + } return nil } -func (f *FlagSet) parseArgs(args []string) error { +func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error) { + a = args + if len(s) == 2 { // "--" terminates the flags + f.args = append(f.args, args...) + return + } + name := s[2:] + if len(name) == 0 || name[0] == '-' || name[0] == '=' { + err = f.failf("bad flag syntax: %s", s) + return + } + split := strings.SplitN(name, "=", 2) + name = split[0] + m := f.formal + flag, alreadythere := m[f.normalizeFlagName(name)] // BUG + if !alreadythere { + if name == "help" { // special case for nice help message. + f.usage() + return args, ErrHelp + } + err = f.failf("unknown flag: --%s", name) + return + } + if len(split) == 1 { + if bv, ok := flag.Value.(boolFlag); !ok || !bv.IsBoolFlag() { + err = f.failf("flag needs an argument: %s", s) + return + } + f.setFlag(flag, "true", s) + } else { + if e := f.setFlag(flag, split[1], s); e != nil { + err = e + return + } + } + return args, nil +} + +func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error) { + a = args + shorthands := s[1:] + + for i := 0; i < len(shorthands); i++ { + c := shorthands[i] + flag, alreadythere := f.shorthands[c] + if !alreadythere { + if c == 'h' { // special case for nice help message. + f.usage() + err = ErrHelp + return + } + //TODO continue on error + err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands) + if len(args) == 0 { + return + } + return + } + if alreadythere { + if bv, ok := flag.Value.(boolFlag); ok && bv.IsBoolFlag() { + f.setFlag(flag, "true", s) + continue + } + if i < len(shorthands)-1 { + v := strings.TrimPrefix(shorthands[i+1:], "=") + if e := f.setFlag(flag, v, s); e != nil { + err = e + return + } + break + } + if len(args) == 0 { + err = f.failf("flag needs an argument: %q in -%s", c, shorthands) + return + } + if e := f.setFlag(flag, args[0], s); e != nil { + err = e + return + } + } + a = args[1:] + break // should be unnecessary + } + + return +} + +func (f *FlagSet) parseArgs(args []string) (err error) { for len(args) > 0 { s := args[0] args = args[1:] @@ -418,69 +605,20 @@ } if s[1] == '-' { - if len(s) == 2 { // "--" terminates the flags - f.args = append(f.args, args...) - return nil - } - name := s[2:] - if len(name) == 0 || name[0] == '-' || name[0] == '=' { - return f.failf("bad flag syntax: %s", s) - } - split := strings.SplitN(name, "=", 2) - name = split[0] - m := f.formal - flag, alreadythere := m[name] // BUG - if !alreadythere { - if name == "help" { // special case for nice help message. - f.usage() - return ErrHelp - } - return f.failf("unknown flag: --%s", name) - } - if len(split) == 1 { - if bv, ok := flag.Value.(boolFlag); !ok || !bv.IsBoolFlag() { - return f.failf("flag needs an argument: %s", s) - } - f.setFlag(flag, "true", s) - } else { - if err := f.setFlag(flag, split[1], s); err != nil { - return err - } + args, err = f.parseLongArg(s, args) + + if len(s) == 2 { + // stop parsing after -- + break } } else { - shorthands := s[1:] - for i := 0; i < len(shorthands); i++ { - c := shorthands[i] - flag, alreadythere := f.shorthands[c] - if !alreadythere { - if c == 'h' { // special case for nice help message. - f.usage() - return ErrHelp - } - return f.failf("unknown shorthand flag: %q in -%s", c, shorthands) - } - if bv, ok := flag.Value.(boolFlag); ok && bv.IsBoolFlag() { - f.setFlag(flag, "true", s) - continue - } - if i < len(shorthands)-1 { - if err := f.setFlag(flag, shorthands[i+1:], s); err != nil { - return err - } - break - } - if len(args) == 0 { - return f.failf("flag needs an argument: %q in -%s", c, shorthands) - } - if err := f.setFlag(flag, args[0], s); err != nil { - return err - } - args = args[1:] - break // should be unnecessary - } + args, err = f.parseShortArg(s, args) + } + if err != nil { + return } } - return nil + return } // Parse parses flag definitions from the argument list, which should not
diff --git a/flag_test.go b/flag_test.go index 82f7fae..7d114b2 100644 --- a/flag_test.go +++ b/flag_test.go
@@ -7,6 +7,8 @@ import ( "bytes" "fmt" + "io" + "io/ioutil" "os" "sort" "strings" @@ -182,7 +184,8 @@ boolaFlag := f.BoolP("boola", "a", false, "bool value") boolbFlag := f.BoolP("boolb", "b", false, "bool2 value") boolcFlag := f.BoolP("boolc", "c", false, "bool3 value") - stringFlag := f.StringP("string", "s", "0", "string value") + stringaFlag := f.StringP("stringa", "s", "0", "string value") + stringzFlag := f.StringP("stringz", "z", "0", "string value") extra := "interspersed-argument" notaflag := "--i-look-like-a-flag" args := []string{ @@ -190,11 +193,13 @@ extra, "-cs", "hello", + "-z=something", "--", notaflag, } + f.SetOutput(ioutil.Discard) if err := f.Parse(args); err != nil { - t.Fatal(err) + t.Error("expected no error, got ", err) } if !f.Parsed() { t.Error("f.Parse() = false after Parse") @@ -208,8 +213,11 @@ if *boolcFlag != true { t.Error("boolc flag should be true, is ", *boolcFlag) } - if *stringFlag != "hello" { - t.Error("string flag should be `hello`, is ", *stringFlag) + if *stringaFlag != "hello" { + t.Error("stringa flag should be `hello`, is ", *stringaFlag) + } + if *stringzFlag != "something" { + t.Error("stringz flag should be `something`, is ", *stringzFlag) } if len(f.Args()) != 2 { t.Error("expected one argument, got", len(f.Args())) @@ -229,6 +237,110 @@ testParse(NewFlagSet("test", ContinueOnError), t) } +func replaceSeparators(name string, from []string, to string) string { + result := name + for _, sep := range from { + result = strings.Replace(result, sep, to, -1) + } + // Type convert to indicate normalization has been done. + return result +} + +func wordSepNormalizeFunc(f *FlagSet, name string) NormalizedName { + seps := []string{"-", "_"} + name = replaceSeparators(name, seps, ".") + return NormalizedName(name) +} + +func testWordSepNormalizedNames(args []string, t *testing.T) { + f := NewFlagSet("normalized", ContinueOnError) + if f.Parsed() { + t.Error("f.Parse() = true before Parse") + } + withDashFlag := f.Bool("with-dash-flag", false, "bool value") + // Set this after some flags have been added and before others. + f.SetNormalizeFunc(wordSepNormalizeFunc) + withUnderFlag := f.Bool("with_under_flag", false, "bool value") + withBothFlag := f.Bool("with-both_flag", false, "bool value") + if err := f.Parse(args); err != nil { + t.Fatal(err) + } + if !f.Parsed() { + t.Error("f.Parse() = false after Parse") + } + if *withDashFlag != true { + t.Error("withDashFlag flag should be true, is ", *withDashFlag) + } + if *withUnderFlag != true { + t.Error("withUnderFlag flag should be true, is ", *withUnderFlag) + } + if *withBothFlag != true { + t.Error("withBothFlag flag should be true, is ", *withBothFlag) + } +} + +func TestWordSepNormalizedNames(t *testing.T) { + args := []string{ + "--with-dash-flag", + "--with-under-flag", + "--with-both-flag", + } + testWordSepNormalizedNames(args, t) + + args = []string{ + "--with_dash_flag", + "--with_under_flag", + "--with_both_flag", + } + testWordSepNormalizedNames(args, t) + + args = []string{ + "--with-dash_flag", + "--with-under_flag", + "--with-both_flag", + } + testWordSepNormalizedNames(args, t) +} + +func aliasAndWordSepFlagNames(f *FlagSet, name string) NormalizedName { + seps := []string{"-", "_"} + + oldName := replaceSeparators("old-valid_flag", seps, ".") + newName := replaceSeparators("valid-flag", seps, ".") + + name = replaceSeparators(name, seps, ".") + switch name { + case oldName: + name = newName + break + } + + return NormalizedName(name) +} + +func TestCustomNormalizedNames(t *testing.T) { + f := NewFlagSet("normalized", ContinueOnError) + if f.Parsed() { + t.Error("f.Parse() = true before Parse") + } + + validFlag := f.Bool("valid-flag", false, "bool value") + f.SetNormalizeFunc(aliasAndWordSepFlagNames) + someOtherFlag := f.Bool("some-other-flag", false, "bool value") + + args := []string{"--old_valid_flag", "--some-other_flag"} + if err := f.Parse(args); err != nil { + t.Fatal(err) + } + + if *validFlag != true { + t.Errorf("validFlag is %v even though we set the alias --old_valid_falg", *validFlag) + } + if *someOtherFlag != true { + t.Error("someOtherFlag should be true, is ", *someOtherFlag) + } +} + // Declare a user-defined flag type. type flagVar []string @@ -241,6 +353,10 @@ return nil } +func (f *flagVar) Type() string { + return "flagVar" +} + func TestUserDefined(t *testing.T) { var flags FlagSet flags.Init("test", ContinueOnError) @@ -348,3 +464,108 @@ t.Fatal("expected interspersed options/non-options to fail") } } + +func TestTermination(t *testing.T) { + f := NewFlagSet("termination", ContinueOnError) + boolFlag := f.BoolP("bool", "l", false, "bool value") + if f.Parsed() { + t.Error("f.Parse() = true before Parse") + } + arg1 := "ls" + arg2 := "-l" + args := []string{ + "--", + arg1, + arg2, + } + f.SetOutput(ioutil.Discard) + if err := f.Parse(args); err != nil { + t.Fatal("expected no error; got ", err) + } + if !f.Parsed() { + t.Error("f.Parse() = false after Parse") + } + if *boolFlag { + t.Error("expected boolFlag=false, got true") + } + if len(f.Args()) != 2 { + t.Errorf("expected 2 arguments, got %d: %v", len(f.Args()), f.Args()) + } + if f.Args()[0] != arg1 { + t.Errorf("expected argument %q got %q", arg1, f.Args()[0]) + } + if f.Args()[1] != arg2 { + t.Errorf("expected argument %q got %q", arg2, f.Args()[1]) + } +} + +func TestDeprecatedFlagInDocs(t *testing.T) { + f := NewFlagSet("bob", ContinueOnError) + f.Bool("badflag", true, "always true") + f.MarkDeprecated("badflag", "use --good-flag instead") + + out := new(bytes.Buffer) + f.SetOutput(out) + f.PrintDefaults() + + if strings.Contains(out.String(), "badflag") { + t.Errorf("found deprecated flag in usage!") + } +} + +func parseReturnStderr(t *testing.T, f *FlagSet, args []string) (string, error) { + oldStderr := os.Stderr + r, w, _ := os.Pipe() + os.Stderr = w + + err := f.Parse(args) + + outC := make(chan string) + // copy the output in a separate goroutine so printing can't block indefinitely + go func() { + var buf bytes.Buffer + io.Copy(&buf, r) + outC <- buf.String() + }() + + w.Close() + os.Stderr = oldStderr + out := <-outC + + return out, err +} + +func TestDeprecatedFlagUsage(t *testing.T) { + f := NewFlagSet("bob", ContinueOnError) + f.Bool("badflag", true, "always true") + usageMsg := "use --good-flag instead" + f.MarkDeprecated("badflag", usageMsg) + + args := []string{"--badflag"} + out, err := parseReturnStderr(t, f, args) + if err != nil { + t.Fatal("expected no error; got ", err) + } + + if !strings.Contains(out, usageMsg) { + t.Errorf("usageMsg not printed when using a deprecated flag!") + } +} + +func TestDeprecatedFlagUsageNormalized(t *testing.T) { + f := NewFlagSet("bob", ContinueOnError) + f.Bool("bad-double_flag", true, "always true") + f.SetNormalizeFunc(wordSepNormalizeFunc) + usageMsg := "use --good-flag instead" + f.MarkDeprecated("bad_double-flag", usageMsg) + + args := []string{"--bad_double_flag"} + out, err := parseReturnStderr(t, f, args) + if err != nil { + t.Fatal("expected no error; got ", err) + } + + if !strings.Contains(out, usageMsg) { + t.Errorf("usageMsg not printed when using a deprecated flag!") + } +}
diff --git a/float32.go b/float32.go index a0041e2..b7ad67d 100644 --- a/float32.go +++ b/float32.go
@@ -19,6 +19,10 @@ return err } +func (f *float32Value) Type() string { + return "float32" +} + func (f *float32Value) String() string { return fmt.Sprintf("%v", *f) } // Float32Var defines a float32 flag with specified name, default value, and usage string.
diff --git a/float64.go b/float64.go index 8d79be0..0315512 100644 --- a/float64.go +++ b/float64.go
@@ -19,6 +19,10 @@ return err } +func (f *float64Value) Type() string { + return "float64" +} + func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) } // Float64Var defines a float64 flag with specified name, default value, and usage string.
diff --git a/int.go b/int.go index cb85e14..dca9da6 100644 --- a/int.go +++ b/int.go
@@ -19,6 +19,10 @@ return err } +func (i *intValue) Type() string { + return "int" +} + func (i *intValue) String() string { return fmt.Sprintf("%v", *i) } // IntVar defines an int flag with specified name, default value, and usage string.
diff --git a/int32.go b/int32.go index 2e1a317..18eaacd 100644 --- a/int32.go +++ b/int32.go
@@ -19,6 +19,10 @@ return err } +func (i *int32Value) Type() string { + return "int32" +} + func (i *int32Value) String() string { return fmt.Sprintf("%v", *i) } // Int32Var defines an int32 flag with specified name, default value, and usage string.
diff --git a/int64.go b/int64.go index 43aeced..0114aaa 100644 --- a/int64.go +++ b/int64.go
@@ -19,6 +19,10 @@ return err } +func (i *int64Value) Type() string { + return "int64" +} + func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) } // Int64Var defines an int64 flag with specified name, default value, and usage string.
diff --git a/int8.go b/int8.go index 539c4eb..aab1022 100644 --- a/int8.go +++ b/int8.go
@@ -19,6 +19,10 @@ return err } +func (i *int8Value) Type() string { + return "int8" +} + func (i *int8Value) String() string { return fmt.Sprintf("%v", *i) } // Int8Var defines an int8 flag with specified name, default value, and usage string.
diff --git a/ip.go b/ip.go index 3a411fc..9d53bd3 100644 --- a/ip.go +++ b/ip.go
@@ -26,6 +26,10 @@ return net.IP(*i) } +func (i *ipValue) Type() string { + return "ip" +} + // IPVar defines an net.IP flag with specified name, default value, and usage string. // The argument p points to an net.IP variable in which to store the value of the flag. func (f *FlagSet) IPVar(p *net.IP, name string, value net.IP, usage string) {
diff --git a/ipmask.go b/ipmask.go index b8a164a..6f85be9 100644 --- a/ipmask.go +++ b/ipmask.go
@@ -26,6 +26,10 @@ return net.IPMask(*i) } +func (i *ipMaskValue) Type() string { + return "ipMask" +} + // Parse IPv4 netmask written in IP form (e.g. 255.255.255.0). // This function should really belong to the net package. func ParseIPv4Mask(s string) net.IPMask {
diff --git a/string.go b/string.go index 65c0cb7..362fbf8 100644 --- a/string.go +++ b/string.go
@@ -14,6 +14,9 @@ *s = stringValue(val) return nil } +func (s *stringValue) Type() string { + return "string" +} func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) }
diff --git a/uint.go b/uint.go index 40b9ebb..c063fe7 100644 --- a/uint.go +++ b/uint.go
@@ -19,6 +19,10 @@ return err } +func (i *uintValue) Type() string { + return "uint" +} + func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) } // UintVar defines a uint flag with specified name, default value, and usage string.
diff --git a/uint16.go b/uint16.go index 182dc40..ec14ab0 100644 --- a/uint16.go +++ b/uint16.go
@@ -18,10 +18,15 @@ *i = uint16Value(v) return err } + func (i *uint16Value) Get() interface{} { return uint16(*i) } +func (i *uint16Value) Type() string { + return "uint16" +} + // Uint16Var defines a uint flag with specified name, default value, and usage string. // The argument p points to a uint variable in which to store the value of the flag. func (f *FlagSet) Uint16Var(p *uint16, name string, value uint16, usage string) {
diff --git a/uint32.go b/uint32.go index 165c8b2..05bc3bd 100644 --- a/uint32.go +++ b/uint32.go
@@ -22,6 +22,10 @@ return uint32(*i) } +func (i *uint32Value) Type() string { + return "uint32" +} + // Uint32Var defines a uint32 flag with specified name, default value, and usage string. // The argument p points to a uint32 variable in which to store the value of the flag. func (f *FlagSet) Uint32Var(p *uint32, name string, value uint32, usage string) {
diff --git a/uint64.go b/uint64.go index f41c5a2..99c7e80 100644 --- a/uint64.go +++ b/uint64.go
@@ -19,6 +19,10 @@ return err } +func (i *uint64Value) Type() string { + return "uint64" +} + func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) } // Uint64Var defines a uint64 flag with specified name, default value, and usage string.
diff --git a/uint8.go b/uint8.go index 174f99c..6fef508 100644 --- a/uint8.go +++ b/uint8.go
@@ -19,6 +19,10 @@ return err } +func (i *uint8Value) Type() string { + return "uint8" +} + func (i *uint8Value) String() string { return fmt.Sprintf("%v", *i) } // Uint8Var defines a uint8 flag with specified name, default value, and usage string.