Revert "Remove all flag interfaces"

This reverts commit 268cb973f8.
This commit is contained in:
Naveen Gogineni 2022-10-08 09:47:46 -05:00
parent 9166808eb5
commit 1a31a6e2fc
27 changed files with 306 additions and 221 deletions

8
app.go
View File

@ -228,7 +228,9 @@ func (a *App) Setup() {
a.flagCategories = newFlagCategories() a.flagCategories = newFlagCategories()
for _, fl := range a.Flags { for _, fl := range a.Flags {
a.flagCategories.AddFlag(fl.GetCategory(), fl) if cf, ok := fl.(CategorizableFlag); ok {
a.flagCategories.AddFlag(cf.GetCategory(), cf)
}
} }
if a.Metadata == nil { if a.Metadata == nil {
@ -662,11 +664,13 @@ func runFlagActions(c *Context, fs []Flag) error {
} }
} }
if isSet { if isSet {
if err := f.RunAction(c); err != nil { if af, ok := f.(ActionableFlag); ok {
if err := af.RunAction(c); err != nil {
return err return err
} }
} }
} }
}
return nil return nil
} }

View File

@ -2386,10 +2386,6 @@ func (c *customBoolFlag) GetEnvVars() []string {
return nil return nil
} }
func (c *customBoolFlag) GetDefaultText() string {
return ""
}
func TestCustomFlagsUnused(t *testing.T) { func TestCustomFlagsUnused(t *testing.T) {
app := &App{ app := &App{
Flags: []Flag{&customBoolFlag{"custom"}}, Flags: []Flag{&customBoolFlag{"custom"}},

View File

@ -101,7 +101,9 @@ func newFlagCategories() FlagCategories {
func newFlagCategoriesFromFlags(fs []Flag) FlagCategories { func newFlagCategoriesFromFlags(fs []Flag) FlagCategories {
fc := newFlagCategories() fc := newFlagCategories()
for _, fl := range fs { for _, fl := range fs {
fc.AddFlag(fl.GetCategory(), fl) if cf, ok := fl.(CategorizableFlag); ok {
fc.AddFlag(cf.GetCategory(), cf)
}
} }
return fc return fc
@ -136,7 +138,7 @@ type VisibleFlagCategory interface {
// Name returns the category name string // Name returns the category name string
Name() string Name() string
// Flags returns a slice of VisibleFlag sorted by name // Flags returns a slice of VisibleFlag sorted by name
Flags() []Flag Flags() []VisibleFlag
} }
type defaultVisibleFlagCategory struct { type defaultVisibleFlagCategory struct {
@ -148,19 +150,21 @@ func (fc *defaultVisibleFlagCategory) Name() string {
return fc.name return fc.name
} }
func (fc *defaultVisibleFlagCategory) Flags() []Flag { func (fc *defaultVisibleFlagCategory) Flags() []VisibleFlag {
vfNames := []string{} vfNames := []string{}
for flName, fl := range fc.m { for flName, fl := range fc.m {
if fl.IsVisible() { if vf, ok := fl.(VisibleFlag); ok {
if vf.IsVisible() {
vfNames = append(vfNames, flName) vfNames = append(vfNames, flName)
} }
} }
}
sort.Strings(vfNames) sort.Strings(vfNames)
ret := make([]Flag, len(vfNames)) ret := make([]VisibleFlag, len(vfNames))
for i, flName := range vfNames { for i, flName := range vfNames {
ret[i] = fc.m[flName] ret[i] = fc.m[flName].(VisibleFlag)
} }
return ret return ret

View File

@ -75,16 +75,6 @@ func (f *{{.TypeName}}) TakesValue() bool {
return "{{.TypeName }}" != "BoolFlag" return "{{.TypeName }}" != "BoolFlag"
} }
{{if .GenerateDefaultText}}
// GetDefaultText returns the default text for this flag
func (f *{{.TypeName}}) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
{{end}}
{{end}}{{/* /if .GenerateFlagInterface */}} {{end}}{{/* /if .GenerateFlagInterface */}}
{{end}}{{/* /range .SortedFlagTypes */}} {{end}}{{/* /range .SortedFlagTypes */}}

View File

@ -12,13 +12,13 @@ func Test{{.TypeName}}_SatisfiesFlagInterface(t *testing.T) {
} }
func Test{{.TypeName}}_SatisfiesRequiredFlagInterface(t *testing.T) { func Test{{.TypeName}}_SatisfiesRequiredFlagInterface(t *testing.T) {
var f {{$.UrfaveCLITestNamespace}}Flag = &{{$.UrfaveCLITestNamespace}}{{.TypeName}}{} var f {{$.UrfaveCLITestNamespace}}RequiredFlag = &{{$.UrfaveCLITestNamespace}}{{.TypeName}}{}
_ = f.IsRequired() _ = f.IsRequired()
} }
func Test{{.TypeName}}_SatisfiesVisibleFlagInterface(t *testing.T) { func Test{{.TypeName}}_SatisfiesVisibleFlagInterface(t *testing.T) {
var f {{$.UrfaveCLITestNamespace}}Flag = &{{$.UrfaveCLITestNamespace}}{{.TypeName}}{} var f {{$.UrfaveCLITestNamespace}}VisibleFlag = &{{$.UrfaveCLITestNamespace}}{{.TypeName}}{}
_ = f.IsVisible() _ = f.IsVisible()
} }

View File

@ -300,7 +300,9 @@ func (c *Command) VisibleFlagCategories() []VisibleFlagCategory {
if c.flagCategories == nil { if c.flagCategories == nil {
c.flagCategories = newFlagCategories() c.flagCategories = newFlagCategories()
for _, fl := range c.Flags { for _, fl := range c.Flags {
c.flagCategories.AddFlag(fl.GetCategory(), fl) if cf, ok := fl.(CategorizableFlag); ok {
c.flagCategories.AddFlag(cf.GetCategory(), fl)
}
} }
} }
return c.flagCategories.VisibleCategories() return c.flagCategories.VisibleCategories()

View File

@ -180,7 +180,7 @@ func (cCtx *Context) lookupFlagSet(name string) *flag.FlagSet {
func (cCtx *Context) checkRequiredFlags(flags []Flag) requiredFlagsErr { func (cCtx *Context) checkRequiredFlags(flags []Flag) requiredFlagsErr {
var missingFlags []string var missingFlags []string
for _, f := range flags { for _, f := range flags {
if f.IsRequired() { if rf, ok := f.(RequiredFlag); ok && rf.IsRequired() {
var flagPresent bool var flagPresent bool
var flagName string var flagName string

View File

@ -116,7 +116,11 @@ func prepareFlags(
addDetails bool, addDetails bool,
) []string { ) []string {
args := []string{} args := []string{}
for _, flag := range flags { for _, f := range flags {
flag, ok := f.(DocGenerationFlag)
if !ok {
continue
}
modifiedArg := opener modifiedArg := opener
for _, s := range flag.Names() { for _, s := range flag.Names() {
@ -147,7 +151,7 @@ func prepareFlags(
} }
// flagDetails returns a string containing the flags metadata // flagDetails returns a string containing the flags metadata
func flagDetails(flag Flag) string { func flagDetails(flag DocGenerationFlag) string {
description := flag.GetUsage() description := flag.GetUsage()
value := flag.GetValue() value := flag.GetValue()
if value != "" { if value != "" {

View File

@ -114,7 +114,12 @@ func (a *App) prepareFishCommands(commands []*Command, allCommands *[]string, pr
func (a *App) prepareFishFlags(flags []Flag, previousCommands []string) []string { func (a *App) prepareFishFlags(flags []Flag, previousCommands []string) []string {
completions := []string{} completions := []string{}
for _, flag := range flags { for _, f := range flags {
flag, ok := f.(DocGenerationFlag)
if !ok {
continue
}
completion := &strings.Builder{} completion := &strings.Builder{}
completion.WriteString(fmt.Sprintf( completion.WriteString(fmt.Sprintf(
"complete -c %s -n '%s'", "complete -c %s -n '%s'",
@ -122,7 +127,7 @@ func (a *App) prepareFishFlags(flags []Flag, previousCommands []string) []string
a.fishSubcommandHelper(previousCommands), a.fishSubcommandHelper(previousCommands),
)) ))
fishAddFileFlag(flag, completion) fishAddFileFlag(f, completion)
for idx, opt := range flag.Names() { for idx, opt := range flag.Names() {
if idx == 0 { if idx == 0 {

72
flag.go
View File

@ -83,6 +83,12 @@ func (f FlagsByName) Swap(i, j int) {
f[i], f[j] = f[j], f[i] f[i], f[j] = f[j], f[i]
} }
// ActionableFlag is an interface that wraps Flag interface and RunAction operation.
type ActionableFlag interface {
Flag
RunAction(*Context) error
}
// Flag is a common interface related to parsing flags in cli. // Flag is a common interface related to parsing flags in cli.
// For more advanced flag parsing techniques, it is recommended that // For more advanced flag parsing techniques, it is recommended that
// this interface be implemented. // this interface be implemented.
@ -97,33 +103,36 @@ type Flag interface {
// Whether the flag has been set or not // Whether the flag has been set or not
IsSet() bool IsSet() bool
}
// RequiredFlag is an interface that allows us to mark flags as required
// it allows flags required flags to be backwards compatible with the Flag interface
type RequiredFlag interface {
Flag
// whether the flag is a required flag or not // whether the flag is a required flag or not
IsRequired() bool IsRequired() bool
}
// IsVisible returns true if the flag is not hidden, otherwise false // DocGenerationFlag is an interface that allows documentation generation for the flag
IsVisible() bool type DocGenerationFlag interface {
Flag
// Returns the category of the flag
GetCategory() string
// GetUsage returns the usage string for the flag
GetUsage() string
// GetEnvVars returns the env vars for this flag
GetEnvVars() []string
// TakesValue returns true if the flag takes a value, otherwise false // TakesValue returns true if the flag takes a value, otherwise false
TakesValue() bool TakesValue() bool
// GetDefaultText returns the default text for this flag // GetUsage returns the usage string for the flag
GetDefaultText() string GetUsage() string
// GetValue returns the flags value as string representation and an empty // GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all. // string if the flag takes no value at all.
GetValue() string GetValue() string
RunAction(*Context) error // GetDefaultText returns the default text for this flag
GetDefaultText() string
// GetEnvVars returns the env vars for this flag
GetEnvVars() []string
} }
// Countable is an interface to enable detection of flag values which support // Countable is an interface to enable detection of flag values which support
@ -132,6 +141,23 @@ type Countable interface {
Count() int Count() int
} }
// VisibleFlag is an interface that allows to check if a flag is visible
type VisibleFlag interface {
Flag
// IsVisible returns true if the flag is not hidden, otherwise false
IsVisible() bool
}
// CategorizableFlag is an interface that allows us to potentially
// use a flag in a categorized representation.
type CategorizableFlag interface {
VisibleFlag
// Returns the category of the flag
GetCategory() string
}
func flagSet(name string, flags []Flag) (*flag.FlagSet, error) { func flagSet(name string, flags []Flag) (*flag.FlagSet, error) {
set := flag.NewFlagSet(name, flag.ContinueOnError) set := flag.NewFlagSet(name, flag.ContinueOnError)
@ -189,7 +215,7 @@ func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
func visibleFlags(fl []Flag) []Flag { func visibleFlags(fl []Flag) []Flag {
var visible []Flag var visible []Flag
for _, f := range fl { for _, f := range fl {
if f.IsVisible() { if vf, ok := f.(VisibleFlag); ok && vf.IsVisible() {
visible = append(visible, f) visible = append(visible, f)
} }
} }
@ -285,8 +311,14 @@ func formatDefault(format string) string {
} }
func stringifyFlag(f Flag) string { func stringifyFlag(f Flag) string {
placeholder, usage := unquoteUsage(f.GetUsage()) // enforce DocGeneration interface on flags to avoid reflection
needsPlaceholder := f.TakesValue() df, ok := f.(DocGenerationFlag)
if !ok {
return ""
}
placeholder, usage := unquoteUsage(df.GetUsage())
needsPlaceholder := df.TakesValue()
if needsPlaceholder && placeholder == "" { if needsPlaceholder && placeholder == "" {
placeholder = defaultPlaceholder placeholder = defaultPlaceholder
@ -294,14 +326,14 @@ func stringifyFlag(f Flag) string {
defaultValueString := "" defaultValueString := ""
if s := f.GetDefaultText(); s != "" { if s := df.GetDefaultText(); s != "" {
defaultValueString = fmt.Sprintf(formatDefault("%s"), s) defaultValueString = fmt.Sprintf(formatDefault("%s"), s)
} }
usageWithDefault := strings.TrimSpace(usage + defaultValueString) usageWithDefault := strings.TrimSpace(usage + defaultValueString)
return withEnvHint(f.GetEnvVars(), return withEnvHint(df.GetEnvVars(),
fmt.Sprintf("%s\t%s", prefixedNames(f.Names(), placeholder), usageWithDefault)) fmt.Sprintf("%s\t%s", prefixedNames(df.Names(), placeholder), usageWithDefault))
} }
func stringifySliceFlag(usage string, names, defaultVals []string) string { func stringifySliceFlag(usage string, names, defaultVals []string) string {

View File

@ -12,6 +12,14 @@ func (f *DurationFlag) GetValue() string {
return f.Value.String() return f.Value.String()
} }
// GetDefaultText returns the default text for this flag
func (f *DurationFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *DurationFlag) Apply(set *flag.FlagSet) error { func (f *DurationFlag) Apply(set *flag.FlagSet) error {
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {

View File

@ -12,6 +12,14 @@ func (f *Float64Flag) GetValue() string {
return fmt.Sprintf("%v", 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()
}
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *Float64Flag) Apply(set *flag.FlagSet) error { func (f *Float64Flag) Apply(set *flag.FlagSet) error {
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {

View File

@ -95,6 +95,14 @@ func (f *Float64SliceFlag) GetValue() string {
return "" return ""
} }
// GetDefaultText returns the default text for this flag
func (f *Float64SliceFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error { func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error {
// apply any default // apply any default

View File

@ -20,6 +20,14 @@ func (f *GenericFlag) GetValue() string {
return "" return ""
} }
// GetDefaultText returns the default text for this flag
func (f *GenericFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// Apply takes the flagset and calls Set on the generic flag with the value // Apply takes the flagset and calls Set on the generic flag with the value
// provided by the user for parsing by the flag // provided by the user for parsing by the flag
func (f *GenericFlag) Apply(set *flag.FlagSet) error { func (f *GenericFlag) Apply(set *flag.FlagSet) error {

View File

@ -12,6 +12,14 @@ func (f *IntFlag) GetValue() string {
return fmt.Sprintf("%d", f.Value) return fmt.Sprintf("%d", f.Value)
} }
// GetDefaultText returns the default text for this flag
func (f *IntFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *IntFlag) Apply(set *flag.FlagSet) error { func (f *IntFlag) Apply(set *flag.FlagSet) error {
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {

View File

@ -12,6 +12,14 @@ func (f *Int64Flag) GetValue() string {
return fmt.Sprintf("%d", f.Value) return fmt.Sprintf("%d", f.Value)
} }
// GetDefaultText returns the default text for this flag
func (f *Int64Flag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *Int64Flag) Apply(set *flag.FlagSet) error { func (f *Int64Flag) Apply(set *flag.FlagSet) error {
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {

View File

@ -96,6 +96,14 @@ func (f *Int64SliceFlag) GetValue() string {
return "" return ""
} }
// GetDefaultText returns the default text for this flag
func (f *Int64SliceFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error { func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error {
// apply any default // apply any default

View File

@ -107,6 +107,14 @@ func (f *IntSliceFlag) GetValue() string {
return "" return ""
} }
// GetDefaultText returns the default text for this flag
func (f *IntSliceFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *IntSliceFlag) Apply(set *flag.FlagSet) error { func (f *IntSliceFlag) Apply(set *flag.FlagSet) error {
// apply any default // apply any default

View File

@ -86,6 +86,14 @@ func (f *StringSliceFlag) GetValue() string {
return "" return ""
} }
// GetDefaultText returns the default text for this flag
func (f *StringSliceFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *StringSliceFlag) Apply(set *flag.FlagSet) error { func (f *StringSliceFlag) Apply(set *flag.FlagSet) error {
// apply any default // apply any default

View File

@ -223,7 +223,10 @@ func TestFlagsFromEnv(t *testing.T) {
defer resetEnv(os.Environ()) defer resetEnv(os.Environ())
os.Clearenv() os.Clearenv()
f := test.flag f, ok := test.flag.(DocGenerationFlag)
if !ok {
t.Errorf("flag %v needs to implement DocGenerationFlag to retrieve env vars", test.flag)
}
envVarSlice := f.GetEnvVars() envVarSlice := f.GetEnvVars()
_ = os.Setenv(envVarSlice[0], test.input) _ = os.Setenv(envVarSlice[0], test.input)
@ -259,6 +262,12 @@ func TestFlagsFromEnv(t *testing.T) {
} }
} }
type nodocFlag struct {
Flag
Name string
}
func TestFlagStringifying(t *testing.T) { func TestFlagStringifying(t *testing.T) {
for _, tc := range []struct { for _, tc := range []struct {
name string name string
@ -435,6 +444,11 @@ func TestFlagStringifying(t *testing.T) {
fl: &UintFlag{Name: "tubes", DefaultText: "13"}, fl: &UintFlag{Name: "tubes", DefaultText: "13"},
expected: "--tubes value\t(default: 13)", expected: "--tubes value\t(default: 13)",
}, },
{
name: "nodoc-flag",
fl: &nodocFlag{Name: "scarecrow"},
expected: "",
},
} { } {
t.Run(tc.name, func(ct *testing.T) { t.Run(tc.name, func(ct *testing.T) {
s := stringifyFlag(tc.fl) s := stringifyFlag(tc.fl)

View File

@ -81,6 +81,14 @@ func (f *TimestampFlag) GetValue() string {
return "" return ""
} }
// GetDefaultText returns the default text for this flag
func (f *TimestampFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
func (f *TimestampFlag) Apply(set *flag.FlagSet) error { func (f *TimestampFlag) Apply(set *flag.FlagSet) error {
if f.Layout == "" { if f.Layout == "" {

View File

@ -37,6 +37,14 @@ func (f *UintFlag) GetValue() string {
return fmt.Sprintf("%d", f.Value) return fmt.Sprintf("%d", f.Value)
} }
// GetDefaultText returns the default text for this flag
func (f *UintFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// Get returns the flags value in the given Context. // Get returns the flags value in the given Context.
func (f *UintFlag) Get(ctx *Context) uint { func (f *UintFlag) Get(ctx *Context) uint {
return ctx.Uint(f.Name) return ctx.Uint(f.Name)

View File

@ -37,6 +37,14 @@ func (f *Uint64Flag) GetValue() string {
return fmt.Sprintf("%d", f.Value) return fmt.Sprintf("%d", f.Value)
} }
// GetDefaultText returns the default text for this flag
func (f *Uint64Flag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// Get returns the flags value in the given Context. // Get returns the flags value in the given Context.
func (f *Uint64Flag) Get(ctx *Context) uint64 { func (f *Uint64Flag) Get(ctx *Context) uint64 {
return ctx.Uint64(f.Name) return ctx.Uint64(f.Name)

View File

@ -247,6 +247,13 @@ TYPES
type ActionFunc func(*Context) error type ActionFunc func(*Context) error
ActionFunc is the action to execute when no subcommands are specified ActionFunc is the action to execute when no subcommands are specified
type ActionableFlag interface {
Flag
RunAction(*Context) error
}
ActionableFlag is an interface that wraps Flag interface and RunAction
operation.
type AfterFunc func(*Context) error type AfterFunc func(*Context) error
AfterFunc is an action to execute after any subcommands are run, but after AfterFunc is an action to execute after any subcommands are run, but after
the subcommand has finished it is run even if Action() panics the subcommand has finished it is run even if Action() panics
@ -499,6 +506,15 @@ func (f *BoolFlag) String() string
func (f *BoolFlag) TakesValue() bool func (f *BoolFlag) TakesValue() bool
TakesValue returns true if the flag takes a value, otherwise false TakesValue returns true if the flag takes a value, otherwise false
type CategorizableFlag interface {
VisibleFlag
// Returns the category of the flag
GetCategory() string
}
CategorizableFlag is an interface that allows us to potentially use a flag
in a categorized representation.
type Command struct { type Command struct {
// The name of the command // The name of the command
Name string Name string
@ -716,6 +732,28 @@ type Countable interface {
Countable is an interface to enable detection of flag values which support Countable is an interface to enable detection of flag values which support
repetitive flags repetitive flags
type DocGenerationFlag interface {
Flag
// TakesValue returns true if the flag takes a value, otherwise false
TakesValue() bool
// GetUsage returns the usage string for the flag
GetUsage() string
// 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
}
DocGenerationFlag is an interface that allows documentation generation for
the flag
type DurationFlag struct { type DurationFlag struct {
Name string Name string
@ -823,33 +861,6 @@ type Flag interface {
// Whether the flag has been set or not // Whether the flag has been set or not
IsSet() bool IsSet() bool
// whether the flag is a required flag or not
IsRequired() bool
// IsVisible returns true if the flag is not hidden, otherwise false
IsVisible() bool
// Returns the category of the flag
GetCategory() string
// GetUsage returns the usage string for the flag
GetUsage() string
// GetEnvVars returns the env vars for this flag
GetEnvVars() []string
// TakesValue returns true if the flag takes a value, otherwise false
TakesValue() bool
// GetDefaultText returns the default text for this flag
GetDefaultText() string
// GetValue returns the flags value as string representation and an empty
// string if the flag takes no value at all.
GetValue() string
RunAction(*Context) error
} }
Flag is a common interface related to parsing flags in cli. For more Flag is a common interface related to parsing flags in cli. For more
advanced flag parsing techniques, it is recommended that this interface be advanced flag parsing techniques, it is recommended that this interface be
@ -1586,6 +1597,16 @@ func (f *PathFlag) String() string
func (f *PathFlag) TakesValue() bool func (f *PathFlag) TakesValue() bool
TakesValue returns true if the flag takes a value, otherwise false TakesValue returns true if the flag takes a value, otherwise false
type RequiredFlag interface {
Flag
// whether the flag is a required flag or not
IsRequired() bool
}
RequiredFlag is an interface that allows us to mark flags as required
it allows flags required flags to be backwards compatible with the Flag
interface
type Serializer interface { type Serializer interface {
Serialize() string Serialize() string
} }
@ -1623,8 +1644,6 @@ func (x *SliceFlag[T, S, E]) IsVisible() bool
func (x *SliceFlag[T, S, E]) Names() []string func (x *SliceFlag[T, S, E]) Names() []string
func (x *SliceFlag[T, S, E]) RunAction(c *Context) error
func (x *SliceFlag[T, S, E]) SetDestination(slice S) func (x *SliceFlag[T, S, E]) SetDestination(slice S)
func (x *SliceFlag[T, S, E]) SetValue(slice S) func (x *SliceFlag[T, S, E]) SetValue(slice S)
@ -1635,6 +1654,10 @@ func (x *SliceFlag[T, S, E]) TakesValue() bool
type SliceFlagTarget[E any] interface { type SliceFlagTarget[E any] interface {
Flag Flag
RequiredFlag
DocGenerationFlag
VisibleFlag
CategorizableFlag
// SetValue should propagate the given slice to the target, ideally as a new value. // SetValue should propagate the given slice to the target, ideally as a new value.
// Note that a nil slice should nil/clear any existing value (modelled as ~[]E). // Note that a nil slice should nil/clear any existing value (modelled as ~[]E).
@ -2229,11 +2252,19 @@ func (f *UintSliceFlag) String() string
func (f *UintSliceFlag) TakesValue() bool func (f *UintSliceFlag) TakesValue() bool
TakesValue returns true of the flag takes a value, otherwise false TakesValue returns true of the flag takes a value, otherwise false
type VisibleFlag interface {
Flag
// IsVisible returns true if the flag is not hidden, otherwise false
IsVisible() bool
}
VisibleFlag is an interface that allows to check if a flag is visible
type VisibleFlagCategory interface { type VisibleFlagCategory interface {
// Name returns the category name string // Name returns the category name string
Name() string Name() string
// Flags returns a slice of VisibleFlag sorted by name // Flags returns a slice of VisibleFlag sorted by name
Flags() []Flag Flags() []VisibleFlag
} }
VisibleFlagCategory is a category containing flags. VisibleFlagCategory is a category containing flags.

View File

@ -21,6 +21,10 @@ type (
// update). // update).
SliceFlagTarget[E any] interface { SliceFlagTarget[E any] interface {
Flag Flag
RequiredFlag
DocGenerationFlag
VisibleFlag
CategorizableFlag
// SetValue should propagate the given slice to the target, ideally as a new value. // SetValue should propagate the given slice to the target, ideally as a new value.
// Note that a nil slice should nil/clear any existing value (modelled as ~[]E). // Note that a nil slice should nil/clear any existing value (modelled as ~[]E).
@ -121,7 +125,6 @@ func (x *SliceFlag[T, S, E]) GetDefaultText() string { return x.Target.GetDe
func (x *SliceFlag[T, S, E]) GetEnvVars() []string { return x.Target.GetEnvVars() } func (x *SliceFlag[T, S, E]) GetEnvVars() []string { return x.Target.GetEnvVars() }
func (x *SliceFlag[T, S, E]) IsVisible() bool { return x.Target.IsVisible() } func (x *SliceFlag[T, S, E]) IsVisible() bool { return x.Target.IsVisible() }
func (x *SliceFlag[T, S, E]) GetCategory() string { return x.Target.GetCategory() } func (x *SliceFlag[T, S, E]) GetCategory() string { return x.Target.GetCategory() }
func (x *SliceFlag[T, S, E]) RunAction(c *Context) error { return x.Target.RunAction(c) }
func (x *flagValueHook) Set(value string) error { func (x *flagValueHook) Set(value string) error {
if err := x.value.Set(value); err != nil { if err := x.value.Set(value); err != nil {

View File

@ -66,14 +66,6 @@ func (f *Float64SliceFlag) TakesValue() bool {
return "Float64SliceFlag" != "BoolFlag" return "Float64SliceFlag" != "BoolFlag"
} }
// GetDefaultText returns the default text for this flag
func (f *Float64SliceFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// GenericFlag is a flag with type Generic // GenericFlag is a flag with type Generic
type GenericFlag struct { type GenericFlag struct {
Name string Name string
@ -143,14 +135,6 @@ func (f *GenericFlag) TakesValue() bool {
return "GenericFlag" != "BoolFlag" return "GenericFlag" != "BoolFlag"
} }
// GetDefaultText returns the default text for this flag
func (f *GenericFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// Int64SliceFlag is a flag with type *Int64Slice // Int64SliceFlag is a flag with type *Int64Slice
type Int64SliceFlag struct { type Int64SliceFlag struct {
Name string Name string
@ -213,14 +197,6 @@ func (f *Int64SliceFlag) TakesValue() bool {
return "Int64SliceFlag" != "BoolFlag" return "Int64SliceFlag" != "BoolFlag"
} }
// GetDefaultText returns the default text for this flag
func (f *Int64SliceFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// IntSliceFlag is a flag with type *IntSlice // IntSliceFlag is a flag with type *IntSlice
type IntSliceFlag struct { type IntSliceFlag struct {
Name string Name string
@ -283,14 +259,6 @@ func (f *IntSliceFlag) TakesValue() bool {
return "IntSliceFlag" != "BoolFlag" return "IntSliceFlag" != "BoolFlag"
} }
// GetDefaultText returns the default text for this flag
func (f *IntSliceFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// PathFlag is a flag with type Path // PathFlag is a flag with type Path
type PathFlag struct { type PathFlag struct {
Name string Name string
@ -424,14 +392,6 @@ func (f *StringSliceFlag) TakesValue() bool {
return "StringSliceFlag" != "BoolFlag" return "StringSliceFlag" != "BoolFlag"
} }
// GetDefaultText returns the default text for this flag
func (f *StringSliceFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// TimestampFlag is a flag with type *Timestamp // TimestampFlag is a flag with type *Timestamp
type TimestampFlag struct { type TimestampFlag struct {
Name string Name string
@ -503,14 +463,6 @@ func (f *TimestampFlag) TakesValue() bool {
return "TimestampFlag" != "BoolFlag" return "TimestampFlag" != "BoolFlag"
} }
// GetDefaultText returns the default text for this flag
func (f *TimestampFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// Uint64SliceFlag is a flag with type *Uint64Slice // Uint64SliceFlag is a flag with type *Uint64Slice
type Uint64SliceFlag struct { type Uint64SliceFlag struct {
Name string Name string
@ -731,14 +683,6 @@ func (f *Float64Flag) TakesValue() bool {
return "Float64Flag" != "BoolFlag" return "Float64Flag" != "BoolFlag"
} }
// GetDefaultText returns the default text for this flag
func (f *Float64Flag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// IntFlag is a flag with type int // IntFlag is a flag with type int
type IntFlag struct { type IntFlag struct {
Name string Name string
@ -808,14 +752,6 @@ func (f *IntFlag) TakesValue() bool {
return "IntFlag" != "BoolFlag" return "IntFlag" != "BoolFlag"
} }
// GetDefaultText returns the default text for this flag
func (f *IntFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// Int64Flag is a flag with type int64 // Int64Flag is a flag with type int64
type Int64Flag struct { type Int64Flag struct {
Name string Name string
@ -885,14 +821,6 @@ func (f *Int64Flag) TakesValue() bool {
return "Int64Flag" != "BoolFlag" return "Int64Flag" != "BoolFlag"
} }
// GetDefaultText returns the default text for this flag
func (f *Int64Flag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// StringFlag is a flag with type string // StringFlag is a flag with type string
type StringFlag struct { type StringFlag struct {
Name string Name string
@ -1029,14 +957,6 @@ func (f *DurationFlag) TakesValue() bool {
return "DurationFlag" != "BoolFlag" return "DurationFlag" != "BoolFlag"
} }
// GetDefaultText returns the default text for this flag
func (f *DurationFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// UintFlag is a flag with type uint // UintFlag is a flag with type uint
type UintFlag struct { type UintFlag struct {
Name string Name string
@ -1106,14 +1026,6 @@ func (f *UintFlag) TakesValue() bool {
return "UintFlag" != "BoolFlag" return "UintFlag" != "BoolFlag"
} }
// GetDefaultText returns the default text for this flag
func (f *UintFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// Uint64Flag is a flag with type uint64 // Uint64Flag is a flag with type uint64
type Uint64Flag struct { type Uint64Flag struct {
Name string Name string
@ -1183,12 +1095,4 @@ func (f *Uint64Flag) TakesValue() bool {
return "Uint64Flag" != "BoolFlag" return "Uint64Flag" != "BoolFlag"
} }
// GetDefaultText returns the default text for this flag
func (f *Uint64Flag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// vim:ro // vim:ro

View File

@ -17,13 +17,13 @@ func TestFloat64SliceFlag_SatisfiesFlagInterface(t *testing.T) {
} }
func TestFloat64SliceFlag_SatisfiesRequiredFlagInterface(t *testing.T) { func TestFloat64SliceFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
var f cli.Flag = &cli.Float64SliceFlag{} var f cli.RequiredFlag = &cli.Float64SliceFlag{}
_ = f.IsRequired() _ = f.IsRequired()
} }
func TestFloat64SliceFlag_SatisfiesVisibleFlagInterface(t *testing.T) { func TestFloat64SliceFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
var f cli.Flag = &cli.Float64SliceFlag{} var f cli.VisibleFlag = &cli.Float64SliceFlag{}
_ = f.IsVisible() _ = f.IsVisible()
} }
@ -36,13 +36,13 @@ func TestGenericFlag_SatisfiesFlagInterface(t *testing.T) {
} }
func TestGenericFlag_SatisfiesRequiredFlagInterface(t *testing.T) { func TestGenericFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
var f cli.Flag = &cli.GenericFlag{} var f cli.RequiredFlag = &cli.GenericFlag{}
_ = f.IsRequired() _ = f.IsRequired()
} }
func TestGenericFlag_SatisfiesVisibleFlagInterface(t *testing.T) { func TestGenericFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
var f cli.Flag = &cli.GenericFlag{} var f cli.VisibleFlag = &cli.GenericFlag{}
_ = f.IsVisible() _ = f.IsVisible()
} }
@ -61,13 +61,13 @@ func TestInt64SliceFlag_SatisfiesFlagInterface(t *testing.T) {
} }
func TestInt64SliceFlag_SatisfiesRequiredFlagInterface(t *testing.T) { func TestInt64SliceFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
var f cli.Flag = &cli.Int64SliceFlag{} var f cli.RequiredFlag = &cli.Int64SliceFlag{}
_ = f.IsRequired() _ = f.IsRequired()
} }
func TestInt64SliceFlag_SatisfiesVisibleFlagInterface(t *testing.T) { func TestInt64SliceFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
var f cli.Flag = &cli.Int64SliceFlag{} var f cli.VisibleFlag = &cli.Int64SliceFlag{}
_ = f.IsVisible() _ = f.IsVisible()
} }
@ -80,13 +80,13 @@ func TestIntSliceFlag_SatisfiesFlagInterface(t *testing.T) {
} }
func TestIntSliceFlag_SatisfiesRequiredFlagInterface(t *testing.T) { func TestIntSliceFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
var f cli.Flag = &cli.IntSliceFlag{} var f cli.RequiredFlag = &cli.IntSliceFlag{}
_ = f.IsRequired() _ = f.IsRequired()
} }
func TestIntSliceFlag_SatisfiesVisibleFlagInterface(t *testing.T) { func TestIntSliceFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
var f cli.Flag = &cli.IntSliceFlag{} var f cli.VisibleFlag = &cli.IntSliceFlag{}
_ = f.IsVisible() _ = f.IsVisible()
} }
@ -99,13 +99,13 @@ func TestPathFlag_SatisfiesFlagInterface(t *testing.T) {
} }
func TestPathFlag_SatisfiesRequiredFlagInterface(t *testing.T) { func TestPathFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
var f cli.Flag = &cli.PathFlag{} var f cli.RequiredFlag = &cli.PathFlag{}
_ = f.IsRequired() _ = f.IsRequired()
} }
func TestPathFlag_SatisfiesVisibleFlagInterface(t *testing.T) { func TestPathFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
var f cli.Flag = &cli.PathFlag{} var f cli.VisibleFlag = &cli.PathFlag{}
_ = f.IsVisible() _ = f.IsVisible()
} }
@ -124,13 +124,13 @@ func TestStringSliceFlag_SatisfiesFlagInterface(t *testing.T) {
} }
func TestStringSliceFlag_SatisfiesRequiredFlagInterface(t *testing.T) { func TestStringSliceFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
var f cli.Flag = &cli.StringSliceFlag{} var f cli.RequiredFlag = &cli.StringSliceFlag{}
_ = f.IsRequired() _ = f.IsRequired()
} }
func TestStringSliceFlag_SatisfiesVisibleFlagInterface(t *testing.T) { func TestStringSliceFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
var f cli.Flag = &cli.StringSliceFlag{} var f cli.VisibleFlag = &cli.StringSliceFlag{}
_ = f.IsVisible() _ = f.IsVisible()
} }
@ -143,13 +143,13 @@ func TestTimestampFlag_SatisfiesFlagInterface(t *testing.T) {
} }
func TestTimestampFlag_SatisfiesRequiredFlagInterface(t *testing.T) { func TestTimestampFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
var f cli.Flag = &cli.TimestampFlag{} var f cli.RequiredFlag = &cli.TimestampFlag{}
_ = f.IsRequired() _ = f.IsRequired()
} }
func TestTimestampFlag_SatisfiesVisibleFlagInterface(t *testing.T) { func TestTimestampFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
var f cli.Flag = &cli.TimestampFlag{} var f cli.VisibleFlag = &cli.TimestampFlag{}
_ = f.IsVisible() _ = f.IsVisible()
} }
@ -182,13 +182,13 @@ func TestBoolFlag_SatisfiesFlagInterface(t *testing.T) {
} }
func TestBoolFlag_SatisfiesRequiredFlagInterface(t *testing.T) { func TestBoolFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
var f cli.Flag = &cli.BoolFlag{} var f cli.RequiredFlag = &cli.BoolFlag{}
_ = f.IsRequired() _ = f.IsRequired()
} }
func TestBoolFlag_SatisfiesVisibleFlagInterface(t *testing.T) { func TestBoolFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
var f cli.Flag = &cli.BoolFlag{} var f cli.VisibleFlag = &cli.BoolFlag{}
_ = f.IsVisible() _ = f.IsVisible()
} }
@ -207,13 +207,13 @@ func TestFloat64Flag_SatisfiesFlagInterface(t *testing.T) {
} }
func TestFloat64Flag_SatisfiesRequiredFlagInterface(t *testing.T) { func TestFloat64Flag_SatisfiesRequiredFlagInterface(t *testing.T) {
var f cli.Flag = &cli.Float64Flag{} var f cli.RequiredFlag = &cli.Float64Flag{}
_ = f.IsRequired() _ = f.IsRequired()
} }
func TestFloat64Flag_SatisfiesVisibleFlagInterface(t *testing.T) { func TestFloat64Flag_SatisfiesVisibleFlagInterface(t *testing.T) {
var f cli.Flag = &cli.Float64Flag{} var f cli.VisibleFlag = &cli.Float64Flag{}
_ = f.IsVisible() _ = f.IsVisible()
} }
@ -232,13 +232,13 @@ func TestIntFlag_SatisfiesFlagInterface(t *testing.T) {
} }
func TestIntFlag_SatisfiesRequiredFlagInterface(t *testing.T) { func TestIntFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
var f cli.Flag = &cli.IntFlag{} var f cli.RequiredFlag = &cli.IntFlag{}
_ = f.IsRequired() _ = f.IsRequired()
} }
func TestIntFlag_SatisfiesVisibleFlagInterface(t *testing.T) { func TestIntFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
var f cli.Flag = &cli.IntFlag{} var f cli.VisibleFlag = &cli.IntFlag{}
_ = f.IsVisible() _ = f.IsVisible()
} }
@ -257,13 +257,13 @@ func TestInt64Flag_SatisfiesFlagInterface(t *testing.T) {
} }
func TestInt64Flag_SatisfiesRequiredFlagInterface(t *testing.T) { func TestInt64Flag_SatisfiesRequiredFlagInterface(t *testing.T) {
var f cli.Flag = &cli.Int64Flag{} var f cli.RequiredFlag = &cli.Int64Flag{}
_ = f.IsRequired() _ = f.IsRequired()
} }
func TestInt64Flag_SatisfiesVisibleFlagInterface(t *testing.T) { func TestInt64Flag_SatisfiesVisibleFlagInterface(t *testing.T) {
var f cli.Flag = &cli.Int64Flag{} var f cli.VisibleFlag = &cli.Int64Flag{}
_ = f.IsVisible() _ = f.IsVisible()
} }
@ -282,13 +282,13 @@ func TestStringFlag_SatisfiesFlagInterface(t *testing.T) {
} }
func TestStringFlag_SatisfiesRequiredFlagInterface(t *testing.T) { func TestStringFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
var f cli.Flag = &cli.StringFlag{} var f cli.RequiredFlag = &cli.StringFlag{}
_ = f.IsRequired() _ = f.IsRequired()
} }
func TestStringFlag_SatisfiesVisibleFlagInterface(t *testing.T) { func TestStringFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
var f cli.Flag = &cli.StringFlag{} var f cli.VisibleFlag = &cli.StringFlag{}
_ = f.IsVisible() _ = f.IsVisible()
} }
@ -307,13 +307,13 @@ func TestDurationFlag_SatisfiesFlagInterface(t *testing.T) {
} }
func TestDurationFlag_SatisfiesRequiredFlagInterface(t *testing.T) { func TestDurationFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
var f cli.Flag = &cli.DurationFlag{} var f cli.RequiredFlag = &cli.DurationFlag{}
_ = f.IsRequired() _ = f.IsRequired()
} }
func TestDurationFlag_SatisfiesVisibleFlagInterface(t *testing.T) { func TestDurationFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
var f cli.Flag = &cli.DurationFlag{} var f cli.VisibleFlag = &cli.DurationFlag{}
_ = f.IsVisible() _ = f.IsVisible()
} }
@ -332,13 +332,13 @@ func TestUintFlag_SatisfiesFlagInterface(t *testing.T) {
} }
func TestUintFlag_SatisfiesRequiredFlagInterface(t *testing.T) { func TestUintFlag_SatisfiesRequiredFlagInterface(t *testing.T) {
var f cli.Flag = &cli.UintFlag{} var f cli.RequiredFlag = &cli.UintFlag{}
_ = f.IsRequired() _ = f.IsRequired()
} }
func TestUintFlag_SatisfiesVisibleFlagInterface(t *testing.T) { func TestUintFlag_SatisfiesVisibleFlagInterface(t *testing.T) {
var f cli.Flag = &cli.UintFlag{} var f cli.VisibleFlag = &cli.UintFlag{}
_ = f.IsVisible() _ = f.IsVisible()
} }
@ -357,13 +357,13 @@ func TestUint64Flag_SatisfiesFlagInterface(t *testing.T) {
} }
func TestUint64Flag_SatisfiesRequiredFlagInterface(t *testing.T) { func TestUint64Flag_SatisfiesRequiredFlagInterface(t *testing.T) {
var f cli.Flag = &cli.Uint64Flag{} var f cli.RequiredFlag = &cli.Uint64Flag{}
_ = f.IsRequired() _ = f.IsRequired()
} }
func TestUint64Flag_SatisfiesVisibleFlagInterface(t *testing.T) { func TestUint64Flag_SatisfiesVisibleFlagInterface(t *testing.T) {
var f cli.Flag = &cli.Uint64Flag{} var f cli.VisibleFlag = &cli.Uint64Flag{}
_ = f.IsVisible() _ = f.IsVisible()
} }