golangflag.go (2813B)
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 package pflag 6 7 import ( 8 goflag "flag" 9 "reflect" 10 "strings" 11 ) 12 13 // flagValueWrapper implements pflag.Value around a flag.Value. The main 14 // difference here is the addition of the Type method that returns a string 15 // name of the type. As this is generally unknown, we approximate that with 16 // reflection. 17 type flagValueWrapper struct { 18 inner goflag.Value 19 flagType string 20 } 21 22 // We are just copying the boolFlag interface out of goflag as that is what 23 // they use to decide if a flag should get "true" when no arg is given. 24 type goBoolFlag interface { 25 goflag.Value 26 IsBoolFlag() bool 27 } 28 29 func wrapFlagValue(v goflag.Value) Value { 30 // If the flag.Value happens to also be a pflag.Value, just use it directly. 31 if pv, ok := v.(Value); ok { 32 return pv 33 } 34 35 pv := &flagValueWrapper{ 36 inner: v, 37 } 38 39 t := reflect.TypeOf(v) 40 if t.Kind() == reflect.Interface || t.Kind() == reflect.Ptr { 41 t = t.Elem() 42 } 43 44 pv.flagType = strings.TrimSuffix(t.Name(), "Value") 45 return pv 46 } 47 48 func (v *flagValueWrapper) String() string { 49 return v.inner.String() 50 } 51 52 func (v *flagValueWrapper) Set(s string) error { 53 return v.inner.Set(s) 54 } 55 56 func (v *flagValueWrapper) Type() string { 57 return v.flagType 58 } 59 60 // PFlagFromGoFlag will return a *pflag.Flag given a *flag.Flag 61 // If the *flag.Flag.Name was a single character (ex: `v`) it will be accessiblei 62 // with both `-v` and `--v` in flags. If the golang flag was more than a single 63 // character (ex: `verbose`) it will only be accessible via `--verbose` 64 func PFlagFromGoFlag(goflag *goflag.Flag) *Flag { 65 // Remember the default value as a string; it won't change. 66 flag := &Flag{ 67 Name: goflag.Name, 68 Usage: goflag.Usage, 69 Value: wrapFlagValue(goflag.Value), 70 // Looks like golang flags don't set DefValue correctly :-( 71 //DefValue: goflag.DefValue, 72 DefValue: goflag.Value.String(), 73 } 74 // Ex: if the golang flag was -v, allow both -v and --v to work 75 if len(flag.Name) == 1 { 76 flag.Shorthand = flag.Name 77 } 78 if fv, ok := goflag.Value.(goBoolFlag); ok && fv.IsBoolFlag() { 79 flag.NoOptDefVal = "true" 80 } 81 return flag 82 } 83 84 // AddGoFlag will add the given *flag.Flag to the pflag.FlagSet 85 func (f *FlagSet) AddGoFlag(goflag *goflag.Flag) { 86 if f.Lookup(goflag.Name) != nil { 87 return 88 } 89 newflag := PFlagFromGoFlag(goflag) 90 f.AddFlag(newflag) 91 } 92 93 // AddGoFlagSet will add the given *flag.FlagSet to the pflag.FlagSet 94 func (f *FlagSet) AddGoFlagSet(newSet *goflag.FlagSet) { 95 if newSet == nil { 96 return 97 } 98 newSet.VisitAll(func(goflag *goflag.Flag) { 99 f.AddGoFlag(goflag) 100 }) 101 if f.addedGoFlagSets == nil { 102 f.addedGoFlagSets = make([]*goflag.FlagSet, 0) 103 } 104 f.addedGoFlagSets = append(f.addedGoFlagSets, newSet) 105 }