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

v2 feature: Add option to prevent default to be printed for BoolFlag #1122

Open
nmeilick opened this issue Apr 30, 2020 · 2 comments · May be fixed by #1128
Open

v2 feature: Add option to prevent default to be printed for BoolFlag #1122

nmeilick opened this issue Apr 30, 2020 · 2 comments · May be fixed by #1128

Comments

@nmeilick
Copy link

@nmeilick nmeilick commented Apr 30, 2020

Checklist

  • Are you running the latest v2 release? The list of releases is here.
  • Did you check the manual for your release? The v2 manual is here
  • Did you perform a search about this feature? Here's the Github guide about searching.

What problem does this solve?

Since v2, the help output looks cluttered when bool flags are used, as these always get their default value appended with no apparent way to disable. The large majority of flags in applications are non-negatable or act as a form of command, so there's usually little benefit in showing the default.

From a current app of mine:

GLOBAL OPTIONS:
   --verbose, -v  Increase verbosity (default: false)
   --extract, -e  Extract only, do not execute the service (default: false)
   --keep, -k     Do not delete the temp dir after execution (default: false)
   --help, -h     show help (default: false)
   --version, -V  print the version (default: false)

Solution description

An option within BoolFlag to disable printing the default would be helpful.

@atif-konasl
Copy link

@atif-konasl atif-konasl commented May 2, 2020

@nmeilick , I have sloved this issue and submited RP.

Solution Approach :

  • Add an new option ShowDefaultValue in BoolFlag
  • If ShowDefaultValue option is true then print default value or if false then it does not print.

Modified files :

  1. flag_bool.go
  2. flag.go
  3. app_test.go

Before Changes :

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))
	}

	placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String())

	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 defaultValueString == formatDefault("") {
		defaultValueString = ""
	}

	if needsPlaceholder && placeholder == "" {
		placeholder = defaultPlaceholder
	}

	usageWithDefault := strings.TrimSpace(usage + defaultValueString)

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

After changes :


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))
	}

	placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String())

	needsPlaceholder := false
	defaultValueString := ""
	val := fv.FieldByName("Value")
	showDefaultValue := fv.FieldByName("ShowDefaultValue")
	if val.IsValid() {
		needsPlaceholder = val.Kind() != reflect.Bool
		defaultValueString = fmt.Sprintf(formatDefault("%v"), val.Interface())
		if val.Kind() == reflect.Bool && !showDefaultValue.Bool() {
			defaultValueString = ""
		}
		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 val.Kind() == reflect.Bool && !showDefaultValue.Bool() {
			defaultValueString = ""
		}
	}

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

	if needsPlaceholder && placeholder == "" {
		placeholder = defaultPlaceholder
	}

	usageWithDefault := strings.TrimSpace(usage + defaultValueString)

	return withEnvHint(flagStringSliceField(f, "EnvVars"),
		fmt.Sprintf("%s\t%s", prefixedNames(f.Names(), placeholder), usageWithDefault))
}
@GregoryDosh
Copy link

@GregoryDosh GregoryDosh commented May 18, 2020

I put this same comment on the PR for the BoolFlag, but putting it here for additional context/discussion.

Throwing this out there, it would be really nice if the ShowDefaultValue parameter existed for other options too. The reason I'm asking is because in a situation where a CLI app is picking up configuration from an environmental variable, it's too easy to accidentally expose that information.

I've got a situation where I'm using this library to create a containerized plugin for use within a CI environment, and it will get injected secrets through way of env variables, but if the user malforms their configuration, any of the set secrets will be exposed by the help menu. For now I'm just setting DefaultText to N/A so it doesn't appear, but this param would be nice to exist on all available flags.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

3 participants
You can’t perform that action at this time.