golangflag.go 2.6 KB

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