Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove reflect calls for doc generation #1259

Merged
merged 4 commits into from Apr 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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