Skip to content

Commit

Permalink
Merge pull request #1361 from urfave/dearchap-remove_reflect
Browse files Browse the repository at this point in the history
Remove reflect calls for doc generation (#1259)
  • Loading branch information
meatballhat committed Apr 22, 2022
2 parents 372ee0a + 9fd3cc9 commit f04607a
Show file tree
Hide file tree
Showing 18 changed files with 418 additions and 49 deletions.
58 changes: 19 additions & 39 deletions flag.go
Expand Up @@ -117,6 +117,12 @@ type DocGenerationFlag interface {
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
GetValue() string

// GetDefaultText returns the default text for this flag
GetDefaultText() string

// GetEnvVars returns the env vars for this flag
GetEnvVars() []string
}

// VisibleFlag is an interface that allows to check if a flag is visible
Expand Down Expand Up @@ -299,55 +305,29 @@ func formatDefault(format string) string {
}

func stringifyFlag(f Flag) string {
fv := flagValue(f)

switch f := f.(type) {
case *IntSliceFlag:
return withEnvHint(flagStringSliceField(f, "EnvVars"),
stringifyIntSliceFlag(f))
case *Int64SliceFlag:
return withEnvHint(flagStringSliceField(f, "EnvVars"),
stringifyInt64SliceFlag(f))
case *Float64SliceFlag:
return withEnvHint(flagStringSliceField(f, "EnvVars"),
stringifyFloat64SliceFlag(f))
case *StringSliceFlag:
return withEnvHint(flagStringSliceField(f, "EnvVars"),
stringifyStringSliceFlag(f))
// enforce DocGeneration interface on flags to avoid reflection
df, ok := f.(DocGenerationFlag)
if !ok {
return ""
}

placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String())
placeholder, usage := unquoteUsage(df.GetUsage())
needsPlaceholder := df.TakesValue()

needsPlaceholder := false
defaultValueString := ""
val := fv.FieldByName("Value")
if val.IsValid() {
needsPlaceholder = val.Kind() != reflect.Bool
defaultValueString = fmt.Sprintf(formatDefault("%v"), val.Interface())

if val.Kind() == reflect.String && val.String() != "" {
defaultValueString = fmt.Sprintf(formatDefault("%q"), val.String())
}
}

helpText := fv.FieldByName("DefaultText")
if helpText.IsValid() && helpText.String() != "" {
needsPlaceholder = val.Kind() != reflect.Bool
defaultValueString = fmt.Sprintf(formatDefault("%s"), helpText.String())
if needsPlaceholder && placeholder == "" {
placeholder = defaultPlaceholder
}

if defaultValueString == formatDefault("") {
defaultValueString = ""
}
defaultValueString := ""

if needsPlaceholder && placeholder == "" {
placeholder = defaultPlaceholder
if s := df.GetDefaultText(); s != "" {
defaultValueString = fmt.Sprintf(formatDefault("%s"), s)
}

usageWithDefault := strings.TrimSpace(usage + defaultValueString)

return withEnvHint(flagStringSliceField(f, "EnvVars"),
fmt.Sprintf("%s\t%s", prefixedNames(f.Names(), placeholder), usageWithDefault))
return withEnvHint(df.GetEnvVars(),
fmt.Sprintf("%s\t%s", prefixedNames(df.Names(), placeholder), usageWithDefault))
}

func stringifyIntSliceFlag(f *IntSliceFlag) string {
Expand Down
13 changes: 13 additions & 0 deletions flag_bool.go
Expand Up @@ -63,6 +63,19 @@ func (f *BoolFlag) IsVisible() bool {
return !f.Hidden
}

// GetDefaultText returns the default text for this flag
func (f *BoolFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return fmt.Sprintf("%v", f.Value)
}

// GetEnvVars returns the env vars for this flag
func (f *BoolFlag) GetEnvVars() []string {
return f.EnvVars
}

// Apply populates the flag given the flag set and environment
func (f *BoolFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
Expand Down
13 changes: 13 additions & 0 deletions flag_duration.go
Expand Up @@ -63,6 +63,19 @@ func (f *DurationFlag) IsVisible() bool {
return !f.Hidden
}

// GetDefaultText returns the default text for this flag
func (f *DurationFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}

// GetEnvVars returns the env vars for this flag
func (f *DurationFlag) GetEnvVars() []string {
return f.EnvVars
}

// Apply populates the flag given the flag set and environment
func (f *DurationFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
Expand Down
15 changes: 14 additions & 1 deletion flag_float64.go
Expand Up @@ -55,7 +55,20 @@ func (f *Float64Flag) GetUsage() string {
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
func (f *Float64Flag) GetValue() string {
return fmt.Sprintf("%f", f.Value)
return fmt.Sprintf("%v", f.Value)
}

// GetDefaultText returns the default text for this flag
func (f *Float64Flag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}

// GetEnvVars returns the env vars for this flag
func (f *Float64Flag) GetEnvVars() []string {
return f.EnvVars
}

// IsVisible returns true if the flag is not hidden, otherwise false
Expand Down
15 changes: 14 additions & 1 deletion flag_float64_slice.go
Expand Up @@ -95,7 +95,7 @@ func (f *Float64SliceFlag) IsSet() bool {
// String returns a readable representation of this value
// (for usage defaults)
func (f *Float64SliceFlag) String() string {
return FlagStringer(f)
return withEnvHint(f.GetEnvVars(), stringifyFloat64SliceFlag(f))
}

// Names returns the names of the flag
Expand Down Expand Up @@ -132,6 +132,19 @@ func (f *Float64SliceFlag) IsVisible() bool {
return !f.Hidden
}

// GetDefaultText returns the default text for this flag
func (f *Float64SliceFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}

// GetEnvVars returns the env vars for this flag
func (f *Float64SliceFlag) GetEnvVars() []string {
return f.EnvVars
}

// Apply populates the flag given the flag set and environment
func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
Expand Down
13 changes: 13 additions & 0 deletions flag_generic.go
Expand Up @@ -71,6 +71,19 @@ func (f *GenericFlag) IsVisible() bool {
return !f.Hidden
}

// GetDefaultText returns the default text for this flag
func (f *GenericFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}

// GetEnvVars returns the env vars for this flag
func (f *GenericFlag) GetEnvVars() []string {
return f.EnvVars
}

// Apply takes the flagset and calls Set on the generic flag with the value
// provided by the user for parsing by the flag
func (f GenericFlag) Apply(set *flag.FlagSet) error {
Expand Down
13 changes: 13 additions & 0 deletions flag_int.go
Expand Up @@ -63,6 +63,19 @@ func (f *IntFlag) IsVisible() bool {
return !f.Hidden
}

// GetDefaultText returns the default text for this flag
func (f *IntFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}

// GetEnvVars returns the env vars for this flag
func (f *IntFlag) GetEnvVars() []string {
return f.EnvVars
}

// Apply populates the flag given the flag set and environment
func (f *IntFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
Expand Down
13 changes: 13 additions & 0 deletions flag_int64.go
Expand Up @@ -63,6 +63,19 @@ func (f *Int64Flag) IsVisible() bool {
return !f.Hidden
}

// GetDefaultText returns the default text for this flag
func (f *Int64Flag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}

// GetEnvVars returns the env vars for this flag
func (f *Int64Flag) GetEnvVars() []string {
return f.EnvVars
}

// Apply populates the flag given the flag set and environment
func (f *Int64Flag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
Expand Down
15 changes: 14 additions & 1 deletion flag_int64_slice.go
Expand Up @@ -96,7 +96,7 @@ func (f *Int64SliceFlag) IsSet() bool {
// String returns a readable representation of this value
// (for usage defaults)
func (f *Int64SliceFlag) String() string {
return FlagStringer(f)
return withEnvHint(f.GetEnvVars(), stringifyInt64SliceFlag(f))
}

// Names returns the names of the flag
Expand Down Expand Up @@ -133,6 +133,19 @@ func (f *Int64SliceFlag) IsVisible() bool {
return !f.Hidden
}

// GetDefaultText returns the default text for this flag
func (f *Int64SliceFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}

// GetEnvVars returns the env vars for this flag
func (f *Int64SliceFlag) GetEnvVars() []string {
return f.EnvVars
}

// Apply populates the flag given the flag set and environment
func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
Expand Down
15 changes: 14 additions & 1 deletion flag_int_slice.go
Expand Up @@ -107,7 +107,7 @@ func (f *IntSliceFlag) IsSet() bool {
// String returns a readable representation of this value
// (for usage defaults)
func (f *IntSliceFlag) String() string {
return FlagStringer(f)
return withEnvHint(f.GetEnvVars(), stringifyIntSliceFlag(f))
}

// Names returns the names of the flag
Expand Down Expand Up @@ -144,6 +144,19 @@ func (f *IntSliceFlag) IsVisible() bool {
return !f.Hidden
}

// GetDefaultText returns the default text for this flag
func (f *IntSliceFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}

// GetEnvVars returns the env vars for this flag
func (f *IntSliceFlag) GetEnvVars() []string {
return f.EnvVars
}

// Apply populates the flag given the flag set and environment
func (f *IntSliceFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
Expand Down
21 changes: 20 additions & 1 deletion flag_path.go
@@ -1,6 +1,9 @@
package cli

import "flag"
import (
"flag"
"fmt"
)

type PathFlag struct {
Name string
Expand Down Expand Up @@ -59,6 +62,22 @@ func (f *PathFlag) IsVisible() bool {
return !f.Hidden
}

// GetDefaultText returns the default text for this flag
func (f *PathFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
if f.Value == "" {
return f.Value
}
return fmt.Sprintf("%q", f.Value)
}

// GetEnvVars returns the env vars for this flag
func (f *PathFlag) GetEnvVars() []string {
return f.EnvVars
}

// Apply populates the flag given the flag set and environment
func (f *PathFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
Expand Down
21 changes: 20 additions & 1 deletion flag_string.go
@@ -1,6 +1,9 @@
package cli

import "flag"
import (
"flag"
"fmt"
)

// StringFlag is a flag with type string
type StringFlag struct {
Expand Down Expand Up @@ -60,6 +63,22 @@ func (f *StringFlag) IsVisible() bool {
return !f.Hidden
}

// GetDefaultText returns the default text for this flag
func (f *StringFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
if f.Value == "" {
return f.Value
}
return fmt.Sprintf("%q", f.Value)
}

// GetEnvVars returns the env vars for this flag
func (f *StringFlag) GetEnvVars() []string {
return f.EnvVars
}

// Apply populates the flag given the flag set and environment
func (f *StringFlag) Apply(set *flag.FlagSet) error {
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
Expand Down
15 changes: 14 additions & 1 deletion flag_string_slice.go
Expand Up @@ -92,7 +92,7 @@ func (f *StringSliceFlag) IsSet() bool {
// String returns a readable representation of this value
// (for usage defaults)
func (f *StringSliceFlag) String() string {
return FlagStringer(f)
return withEnvHint(f.GetEnvVars(), stringifyStringSliceFlag(f))
}

// Names returns the names of the flag
Expand Down Expand Up @@ -129,6 +129,19 @@ func (f *StringSliceFlag) IsVisible() bool {
return !f.Hidden
}

// GetDefaultText returns the default text for this flag
func (f *StringSliceFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}

// GetEnvVars returns the env vars for this flag
func (f *StringSliceFlag) GetEnvVars() []string {
return f.EnvVars
}

// Apply populates the flag given the flag set and environment
func (f *StringSliceFlag) Apply(set *flag.FlagSet) error {

Expand Down

0 comments on commit f04607a

Please sign in to comment.