golangflag.go 2.6 KB

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