Skip to content

BoolWithInverseFlag does not honor explicitly set DefaultText #2402

Description

@lsg551

My urfave/cli version is

v3.10.1

Checklist

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

Dependency Management

  • My project is using go modules.
  • My project is automatically downloading the latest version.

Describe the bug

BoolWithInverseFlag does NOT honor its property DefaultText, which, if I am not mistaken, should override the (default: […]) output in the help message regardless of any actual value.

To reproduce

  1. Create a new Go module
  2. Add urfave/cli
  3. Copy/paste the following snippet and run it
package main

import (
	"context"
	"os"

	"github.com/urfave/cli/v3"
)

var cmd = &cli.Command{
	Name: "test",
	Flags: []cli.Flag{
		&cli.BoolFlag{
			Name:        "debug",
			Usage:       "set log level to DEBUG",
			Value:       true,
			DefaultText: "blabla", // for comparison
		},
                # control output color
		&cli.BoolWithInverseFlag{
			// accepts (true|false|auto) where "auto" is tty-aware
			// --color (not set) = auto
			// --color (set)     = ture
			// --no-color        = false
			Name:  "color",
			Usage: "colorise text output",
			// BUG: default text is not shown but the actual default value "false"
			DefaultText: "auto",
		},
	},
}

func main() {
	cmd.Run(context.Background(), os.Args)
}

Observed behavior

$ go run main.go
NAME:
   test - A new cli application

USAGE:
   test [global options]

GLOBAL OPTIONS:
   --debug           set log level to DEBUG (default: blabla)
   --[no-]color    colorise text output (default: false)
   --help, -h        show help

Expected behavior

I specified DefaultText: "auto" for the --[no-]color flag and expected the help message to print this value, regardless of the actual default value.

Additional context

I was basically trying to achieve a ternary state flag using BoolWithInverseFlag and Flag.IsSet, where the flag is not required and defaults to "auto":

  1. default (user did nothing) → "auto" (i.e., IsSet evaluates to false)
  2. user set --color → true
  3. user set --no-color → false

This flag would allow to explicitly control colour printing in the application's output. If left untouched (=auto), it would automatically check whether the output stream (usually STDERR) is a TTY, and then set a proper value (TTY→true, no TTY→false).

Reading #2214 (comment), the current behaviour I perceived as a bug could be intentional though, as boolean flags usually suggest to have a binary state only.

Want to fix this yourself?

I am not certain, but it appears that this method is the culprit:

func (bif *BoolWithInverseFlag) GetDefaultText() string {
if bif.Required {
return bif.DefaultText
}
return boolValue{}.ToString(bif.Value)
}

	if bif.Required {
		return bif.DefaultText
	}

is also a dead branch, because

https://github.com/urfave/cli/blob/main/docs.go#L108-L117

prevents the (default: […]) text from being rendered at all if the flag is required.

So the obvious solution could simply be:

func (bif *BoolWithInverseFlag) GetDefaultText() string {
	if bif.DefaultText != "" {
		return bif.DefaultText
	}
	return boolValue{}.ToString(bif.Value)
}

I changed that locally and modified/extended the tests accordingly. They pass but

  • with Required=true and no DefaultText, GetDefaultText() now returns "false" (was "" before)
  • the suppressing of the default text now depends on external factors (GetDefaultText probably should not handle that anyway)

Run go version and paste its output here

go version go1.26.5 darwin/arm64

Run go env and paste its output here

n/a

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/v3relates to / is being considered for v3kind/bugdescribes or fixes a bugstatus/triagemaintainers still need to look into this

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions