From 38abd8db414366b62ee0ed394a00c4b7395e9816 Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Thu, 29 Sep 2022 11:31:40 -0400 Subject: [PATCH 01/18] Ensure "generate" step runs in CI prior to diff check --- .github/workflows/cli.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index 5caeafe5ac..e9c0236dd9 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -40,6 +40,7 @@ jobs: GFLAGS: -tags urfave_cli_no_docs - run: make check-binary-size - run: make yamlfmt + - run: make generate - run: make diffcheck - if: matrix.go == '1.19.x' && matrix.os == 'ubuntu-latest' run: make v2diff From cb040b67a0d1a4e348b7b2a392096c4b3912ca0e Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Thu, 29 Sep 2022 20:44:37 -0400 Subject: [PATCH 02/18] Only run generate on go 1.19 --- .github/workflows/cli.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index e9c0236dd9..ef5195c241 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -40,7 +40,8 @@ jobs: GFLAGS: -tags urfave_cli_no_docs - run: make check-binary-size - run: make yamlfmt - - run: make generate + - if: matrix.go == '1.19.x' && matrix.os == 'ubuntu-latest' + run: make generate - run: make diffcheck - if: matrix.go == '1.19.x' && matrix.os == 'ubuntu-latest' run: make v2diff From d4a5c397f4e0cd5b586463600e18a79812638d04 Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Thu, 29 Sep 2022 20:46:53 -0400 Subject: [PATCH 03/18] Accept current godoc for v2 --- godoc-current.txt | 42 +++++++++++++++++++++++++++++++++-------- testdata/godoc-v2.x.txt | 42 +++++++++++++++++++++++++++++++++-------- 2 files changed, 68 insertions(+), 16 deletions(-) diff --git a/godoc-current.txt b/godoc-current.txt index 3d5cb9a298..efbac4d1e8 100644 --- a/godoc-current.txt +++ b/godoc-current.txt @@ -458,6 +458,8 @@ type BoolFlag struct { EnvVars []string Count *int + + Action func(*Context, bool) error } BoolFlag is a flag with type bool @@ -565,7 +567,6 @@ type Command struct { // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. CustomHelpTemplate string - // Has unexported fields. } Command is a subcommand for a cli.App. @@ -584,13 +585,6 @@ func (c *Command) Run(ctx *Context) (err error) Run invokes the command given the context, parses ctx.Args() to generate command-specific flags -func (c *Command) VisibleCategories() []CommandCategory - VisibleCategories returns a slice of categories and commands that are - Hidden=false - -func (c *Command) VisibleCommands() []*Command - VisibleCommands returns a slice of the Commands with Hidden=false - func (c *Command) VisibleFlagCategories() []VisibleFlagCategory VisibleFlagCategories returns a slice containing all the visible flag categories with the flags they contain @@ -776,6 +770,8 @@ type DurationFlag struct { Aliases []string EnvVars []string + + Action func(*Context, time.Duration) error } DurationFlag is a flag with type time.Duration @@ -952,6 +948,8 @@ type Float64Flag struct { Aliases []string EnvVars []string + + Action func(*Context, float64) error } Float64Flag is a flag with type float64 @@ -1038,6 +1036,8 @@ type Float64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []float64) error } Float64SliceFlag is a flag with type *Float64Slice @@ -1115,6 +1115,8 @@ type GenericFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, interface{}) error } GenericFlag is a flag with type Generic @@ -1181,6 +1183,8 @@ type Int64Flag struct { EnvVars []string Base int + + Action func(*Context, int64) error } Int64Flag is a flag with type int64 @@ -1267,6 +1271,8 @@ type Int64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []int64) error } Int64SliceFlag is a flag with type *Int64Slice @@ -1338,6 +1344,8 @@ type IntFlag struct { EnvVars []string Base int + + Action func(*Context, int) error } IntFlag is a flag with type int @@ -1428,6 +1436,8 @@ type IntSliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []int) error } IntSliceFlag is a flag with type *IntSlice @@ -1533,6 +1543,8 @@ type PathFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, Path) error } PathFlag is a flag with type Path @@ -1673,6 +1685,8 @@ type StringFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, string) error } StringFlag is a flag with type string @@ -1761,6 +1775,8 @@ type StringSliceFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, []string) error } StringSliceFlag is a flag with type *StringSlice @@ -1867,6 +1883,8 @@ type TimestampFlag struct { Layout string Timezone *time.Location + + Action func(*Context, *time.Time) error } TimestampFlag is a flag with type *Timestamp @@ -1932,6 +1950,8 @@ type Uint64Flag struct { EnvVars []string Base int + + Action func(*Context, uint64) error } Uint64Flag is a flag with type uint64 @@ -2018,6 +2038,8 @@ type Uint64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []uint64) error } Uint64SliceFlag is a flag with type *Uint64Slice @@ -2080,6 +2102,8 @@ type UintFlag struct { EnvVars []string Base int + + Action func(*Context, uint) error } UintFlag is a flag with type uint @@ -2170,6 +2194,8 @@ type UintSliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []uint) error } UintSliceFlag is a flag with type *UintSlice diff --git a/testdata/godoc-v2.x.txt b/testdata/godoc-v2.x.txt index 3d5cb9a298..efbac4d1e8 100644 --- a/testdata/godoc-v2.x.txt +++ b/testdata/godoc-v2.x.txt @@ -458,6 +458,8 @@ type BoolFlag struct { EnvVars []string Count *int + + Action func(*Context, bool) error } BoolFlag is a flag with type bool @@ -565,7 +567,6 @@ type Command struct { // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. CustomHelpTemplate string - // Has unexported fields. } Command is a subcommand for a cli.App. @@ -584,13 +585,6 @@ func (c *Command) Run(ctx *Context) (err error) Run invokes the command given the context, parses ctx.Args() to generate command-specific flags -func (c *Command) VisibleCategories() []CommandCategory - VisibleCategories returns a slice of categories and commands that are - Hidden=false - -func (c *Command) VisibleCommands() []*Command - VisibleCommands returns a slice of the Commands with Hidden=false - func (c *Command) VisibleFlagCategories() []VisibleFlagCategory VisibleFlagCategories returns a slice containing all the visible flag categories with the flags they contain @@ -776,6 +770,8 @@ type DurationFlag struct { Aliases []string EnvVars []string + + Action func(*Context, time.Duration) error } DurationFlag is a flag with type time.Duration @@ -952,6 +948,8 @@ type Float64Flag struct { Aliases []string EnvVars []string + + Action func(*Context, float64) error } Float64Flag is a flag with type float64 @@ -1038,6 +1036,8 @@ type Float64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []float64) error } Float64SliceFlag is a flag with type *Float64Slice @@ -1115,6 +1115,8 @@ type GenericFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, interface{}) error } GenericFlag is a flag with type Generic @@ -1181,6 +1183,8 @@ type Int64Flag struct { EnvVars []string Base int + + Action func(*Context, int64) error } Int64Flag is a flag with type int64 @@ -1267,6 +1271,8 @@ type Int64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []int64) error } Int64SliceFlag is a flag with type *Int64Slice @@ -1338,6 +1344,8 @@ type IntFlag struct { EnvVars []string Base int + + Action func(*Context, int) error } IntFlag is a flag with type int @@ -1428,6 +1436,8 @@ type IntSliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []int) error } IntSliceFlag is a flag with type *IntSlice @@ -1533,6 +1543,8 @@ type PathFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, Path) error } PathFlag is a flag with type Path @@ -1673,6 +1685,8 @@ type StringFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, string) error } StringFlag is a flag with type string @@ -1761,6 +1775,8 @@ type StringSliceFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, []string) error } StringSliceFlag is a flag with type *StringSlice @@ -1867,6 +1883,8 @@ type TimestampFlag struct { Layout string Timezone *time.Location + + Action func(*Context, *time.Time) error } TimestampFlag is a flag with type *Timestamp @@ -1932,6 +1950,8 @@ type Uint64Flag struct { EnvVars []string Base int + + Action func(*Context, uint64) error } Uint64Flag is a flag with type uint64 @@ -2018,6 +2038,8 @@ type Uint64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []uint64) error } Uint64SliceFlag is a flag with type *Uint64Slice @@ -2080,6 +2102,8 @@ type UintFlag struct { EnvVars []string Base int + + Action func(*Context, uint) error } UintFlag is a flag with type uint @@ -2170,6 +2194,8 @@ type UintSliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []uint) error } UintSliceFlag is a flag with type *UintSlice From 72cbb3db6a3d0cc07e305a5d2ca26221153751a9 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Fri, 30 Sep 2022 15:01:22 +0200 Subject: [PATCH 04/18] Call FlagStringer in String() method of slice flags The default help template relies on the String() method of Flag to render the flag. For most flag types, String() indirects through FlagStringer, so that is the best place to customize flag rendering. FlagStringer was not called for slice flags because their help output differs from other flags in two ways: there can be multiple default values, and the flag name is shown two times to indicate that the flag can be specified multiple times. To make multiple values work in the FlagStringer, I simply changed GetValue() to return all values. Showing the flag more than once is achieved through a new interface, DocGenerationSliceFlag, which the FlagStringer uses to decide whether the flag is a slice flag type. --- flag.go | 29 +++++++++++++---------------- flag_float64_slice.go | 28 ++++++++++++---------------- flag_int64_slice.go | 27 ++++++++++++--------------- flag_int_slice.go | 27 ++++++++++++--------------- flag_string_slice.go | 31 ++++++++++++++----------------- flag_test.go | 20 ++++++++++---------- flag_uint64_slice.go | 27 ++++++++++++--------------- flag_uint_slice.go | 27 ++++++++++++--------------- 8 files changed, 97 insertions(+), 119 deletions(-) diff --git a/flag.go b/flag.go index 7b5ec498c7..a6fea1c493 100644 --- a/flag.go +++ b/flag.go @@ -129,6 +129,14 @@ type DocGenerationFlag interface { GetEnvVars() []string } +// DocGenerationSliceFlag extends DocGenerationFlag for slice-based flags. +type DocGenerationSliceFlag interface { + DocGenerationFlag + + // IsSliceFlag returns true for flags that can be given multiple times. + IsSliceFlag() bool +} + // VisibleFlag is an interface that allows to check if a flag is visible type VisibleFlag interface { Flag @@ -325,24 +333,13 @@ func stringifyFlag(f Flag) string { usageWithDefault := strings.TrimSpace(usage + defaultValueString) - return withEnvHint(df.GetEnvVars(), - fmt.Sprintf("%s\t%s", prefixedNames(df.Names(), placeholder), usageWithDefault)) -} - -func stringifySliceFlag(usage string, names, defaultVals []string) string { - placeholder, usage := unquoteUsage(usage) - if placeholder == "" { - placeholder = defaultPlaceholder - } - - defaultVal := "" - if len(defaultVals) > 0 { - defaultVal = fmt.Sprintf(formatDefault("%s"), strings.Join(defaultVals, ", ")) + pn := prefixedNames(df.Names(), placeholder) + sliceFlag, ok := f.(DocGenerationSliceFlag) + if ok && sliceFlag.IsSliceFlag() { + pn = pn + " [ " + pn + " ]" } - usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultVal)) - pn := prefixedNames(names, placeholder) - return fmt.Sprintf("%s [ %s ]\t%s", pn, pn, usageWithDefault) + return withEnvHint(df.GetEnvVars(), fmt.Sprintf("%s\t%s", pn, usageWithDefault)) } func hasFlag(flags []Flag, fl Flag) bool { diff --git a/flag_float64_slice.go b/flag_float64_slice.go index 2cb5e4adfa..413aa50e9f 100644 --- a/flag_float64_slice.go +++ b/flag_float64_slice.go @@ -83,7 +83,7 @@ func (f *Float64Slice) Get() interface{} { // String returns a readable representation of this value // (for usage defaults) func (f *Float64SliceFlag) String() string { - return withEnvHint(f.GetEnvVars(), f.stringify()) + return FlagStringer(f) } // TakesValue returns true if the flag takes a value, otherwise false @@ -104,10 +104,13 @@ func (f *Float64SliceFlag) GetCategory() string { // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *Float64SliceFlag) GetValue() string { - if f.Value != nil { - return f.Value.String() + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strings.TrimRight(strings.TrimRight(fmt.Sprintf("%f", i), "0"), ".")) + } } - return "" + return strings.Join(defaultVals, ", ") } // GetDefaultText returns the default text for this flag @@ -123,6 +126,11 @@ func (f *Float64SliceFlag) GetEnvVars() []string { return f.EnvVars } +// IsSliceFlag implements DocGenerationSliceFlag. +func (f *Float64SliceFlag) IsSliceFlag() bool { + return true +} + // Apply populates the flag given the flag set and environment func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error { // apply any default @@ -169,18 +177,6 @@ func (f *Float64SliceFlag) Get(ctx *Context) []float64 { return ctx.Float64Slice(f.Name) } -func (f *Float64SliceFlag) stringify() string { - var defaultVals []string - - if f.Value != nil && len(f.Value.Value()) > 0 { - for _, i := range f.Value.Value() { - defaultVals = append(defaultVals, strings.TrimRight(strings.TrimRight(fmt.Sprintf("%f", i), "0"), ".")) - } - } - - return stringifySliceFlag(f.Usage, f.Names(), defaultVals) -} - // RunAction executes flag action if set func (f *Float64SliceFlag) RunAction(c *Context) error { if f.Action != nil { diff --git a/flag_int64_slice.go b/flag_int64_slice.go index d4a11b6a81..c45c43d3ab 100644 --- a/flag_int64_slice.go +++ b/flag_int64_slice.go @@ -84,7 +84,7 @@ func (i *Int64Slice) Get() interface{} { // String returns a readable representation of this value // (for usage defaults) func (f *Int64SliceFlag) String() string { - return withEnvHint(f.GetEnvVars(), f.stringify()) + return FlagStringer(f) } // TakesValue returns true of the flag takes a value, otherwise false @@ -105,10 +105,13 @@ func (f *Int64SliceFlag) GetCategory() string { // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *Int64SliceFlag) GetValue() string { - if f.Value != nil { - return f.Value.String() + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strconv.FormatInt(i, 10)) + } } - return "" + return strings.Join(defaultVals, ", ") } // GetDefaultText returns the default text for this flag @@ -124,6 +127,11 @@ func (f *Int64SliceFlag) GetEnvVars() []string { return f.EnvVars } +// IsSliceFlag implements DocGenerationSliceFlag. +func (f *Int64SliceFlag) IsSliceFlag() bool { + return true +} + // Apply populates the flag given the flag set and environment func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error { // apply any default @@ -168,17 +176,6 @@ func (f *Int64SliceFlag) Get(ctx *Context) []int64 { return ctx.Int64Slice(f.Name) } -func (f *Int64SliceFlag) stringify() string { - var defaultVals []string - if f.Value != nil && len(f.Value.Value()) > 0 { - for _, i := range f.Value.Value() { - defaultVals = append(defaultVals, strconv.FormatInt(i, 10)) - } - } - - return stringifySliceFlag(f.Usage, f.Names(), defaultVals) -} - // RunAction executes flag action if set func (f *Int64SliceFlag) RunAction(c *Context) error { if f.Action != nil { diff --git a/flag_int_slice.go b/flag_int_slice.go index 2cabe7202f..d4006e594c 100644 --- a/flag_int_slice.go +++ b/flag_int_slice.go @@ -95,7 +95,7 @@ func (i *IntSlice) Get() interface{} { // String returns a readable representation of this value // (for usage defaults) func (f *IntSliceFlag) String() string { - return withEnvHint(f.GetEnvVars(), f.stringify()) + return FlagStringer(f) } // TakesValue returns true of the flag takes a value, otherwise false @@ -116,10 +116,13 @@ func (f *IntSliceFlag) GetCategory() string { // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *IntSliceFlag) GetValue() string { - if f.Value != nil { - return f.Value.String() + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strconv.Itoa(i)) + } } - return "" + return strings.Join(defaultVals, ", ") } // GetDefaultText returns the default text for this flag @@ -135,6 +138,11 @@ func (f *IntSliceFlag) GetEnvVars() []string { return f.EnvVars } +// IsSliceFlag implements DocGenerationSliceFlag. +func (f *IntSliceFlag) IsSliceFlag() bool { + return true +} + // Apply populates the flag given the flag set and environment func (f *IntSliceFlag) Apply(set *flag.FlagSet) error { // apply any default @@ -188,17 +196,6 @@ func (f *IntSliceFlag) RunAction(c *Context) error { return nil } -func (f *IntSliceFlag) stringify() string { - var defaultVals []string - if f.Value != nil && len(f.Value.Value()) > 0 { - for _, i := range f.Value.Value() { - defaultVals = append(defaultVals, strconv.Itoa(i)) - } - } - - return stringifySliceFlag(f.Usage, f.Names(), defaultVals) -} - // IntSlice looks up the value of a local IntSliceFlag, returns // nil if not found func (cCtx *Context) IntSlice(name string) []int { diff --git a/flag_string_slice.go b/flag_string_slice.go index 7b46a24742..baca2a2fb9 100644 --- a/flag_string_slice.go +++ b/flag_string_slice.go @@ -74,7 +74,7 @@ func (s *StringSlice) Get() interface{} { // String returns a readable representation of this value // (for usage defaults) func (f *StringSliceFlag) String() string { - return withEnvHint(f.GetEnvVars(), f.stringify()) + return FlagStringer(f) } // TakesValue returns true of the flag takes a value, otherwise false @@ -95,10 +95,15 @@ func (f *StringSliceFlag) GetCategory() string { // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *StringSliceFlag) GetValue() string { - if f.Value != nil { - return f.Value.String() + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, s := range f.Value.Value() { + if len(s) > 0 { + defaultVals = append(defaultVals, strconv.Quote(s)) + } + } } - return "" + return strings.Join(defaultVals, ", ") } // GetDefaultText returns the default text for this flag @@ -114,6 +119,11 @@ func (f *StringSliceFlag) GetEnvVars() []string { return f.EnvVars } +// IsSliceFlag implements DocGenerationSliceFlag. +func (f *StringSliceFlag) IsSliceFlag() bool { + return true +} + // Apply populates the flag given the flag set and environment func (f *StringSliceFlag) Apply(set *flag.FlagSet) error { // apply any default @@ -158,19 +168,6 @@ func (f *StringSliceFlag) Get(ctx *Context) []string { return ctx.StringSlice(f.Name) } -func (f *StringSliceFlag) stringify() string { - var defaultVals []string - if f.Value != nil && len(f.Value.Value()) > 0 { - for _, s := range f.Value.Value() { - if len(s) > 0 { - defaultVals = append(defaultVals, strconv.Quote(s)) - } - } - } - - return stringifySliceFlag(f.Usage, f.Names(), defaultVals) -} - // RunAction executes flag action if set func (f *StringSliceFlag) RunAction(c *Context) error { if f.Action != nil { diff --git a/flag_test.go b/flag_test.go index ddd3e67e49..06f948c86f 100644 --- a/flag_test.go +++ b/flag_test.go @@ -307,12 +307,12 @@ func TestFlagStringifying(t *testing.T) { { name: "float64-slice-flag", fl: &Float64SliceFlag{Name: "pizzas"}, - expected: "--pizzas value\t", + expected: "--pizzas value [ --pizzas value ]\t", }, { name: "float64-slice-flag-with-default-text", fl: &Float64SliceFlag{Name: "pepperonis", DefaultText: "shaved"}, - expected: "--pepperonis value\t(default: shaved)", + expected: "--pepperonis value [ --pepperonis value ]\t(default: shaved)", }, { name: "generic-flag", @@ -337,7 +337,7 @@ func TestFlagStringifying(t *testing.T) { { name: "int-slice-flag", fl: &IntSliceFlag{Name: "pencils"}, - expected: "--pencils value\t", + expected: "--pencils value [ --pencils value ]\t", }, { name: "int-slice-flag-with-default-text", @@ -347,7 +347,7 @@ func TestFlagStringifying(t *testing.T) { { name: "uint-slice-flag", fl: &UintSliceFlag{Name: "pencils"}, - expected: "--pencils value\t", + expected: "--pencils value [ --pencils value ]\t", }, { name: "uint-slice-flag-with-default-text", @@ -367,22 +367,22 @@ func TestFlagStringifying(t *testing.T) { { name: "int64-slice-flag", fl: &Int64SliceFlag{Name: "drawers"}, - expected: "--drawers value\t", + expected: "--drawers value [ --drawers value ]\t", }, { name: "int64-slice-flag-with-default-text", fl: &Int64SliceFlag{Name: "handles", DefaultText: "-2"}, - expected: "--handles value\t(default: -2)", + expected: "--handles value [ --handles value ]\t(default: -2)", }, { name: "uint64-slice-flag", fl: &Uint64SliceFlag{Name: "drawers"}, - expected: "--drawers value\t", + expected: "--drawers value [ --drawers value ]\t", }, { name: "uint64-slice-flag-with-default-text", fl: &Uint64SliceFlag{Name: "handles", DefaultText: "-2"}, - expected: "--handles value\t(default: -2)", + expected: "--handles value [ --handles value ]\t(default: -2)", }, { name: "path-flag", @@ -407,12 +407,12 @@ func TestFlagStringifying(t *testing.T) { { name: "string-slice-flag", fl: &StringSliceFlag{Name: "meow-sounds"}, - expected: "--meow-sounds value\t", + expected: "--meow-sounds value [ --meow-sounds value ]\t", }, { name: "string-slice-flag-with-default-text", fl: &StringSliceFlag{Name: "moo-sounds", DefaultText: "awoo"}, - expected: "--moo-sounds value\t(default: awoo)", + expected: "--moo-sounds value [ --moo-sounds value ]\t(default: awoo)", }, { name: "timestamp-flag", diff --git a/flag_uint64_slice.go b/flag_uint64_slice.go index e60c3ea8af..61bb30b551 100644 --- a/flag_uint64_slice.go +++ b/flag_uint64_slice.go @@ -88,7 +88,7 @@ func (i *Uint64Slice) Get() interface{} { // String returns a readable representation of this value // (for usage defaults) func (f *Uint64SliceFlag) String() string { - return withEnvHint(f.GetEnvVars(), f.stringify()) + return FlagStringer(f) } // TakesValue returns true of the flag takes a value, otherwise false @@ -109,10 +109,13 @@ func (f *Uint64SliceFlag) GetCategory() string { // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *Uint64SliceFlag) GetValue() string { - if f.Value != nil { - return f.Value.String() + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strconv.FormatUint(i, 10)) + } } - return "" + return strings.Join(defaultVals, ", ") } // GetDefaultText returns the default text for this flag @@ -128,6 +131,11 @@ func (f *Uint64SliceFlag) GetEnvVars() []string { return f.EnvVars } +// IsSliceFlag implements DocGenerationSliceFlag. +func (f *Uint64SliceFlag) IsSliceFlag() bool { + return true +} + // Apply populates the flag given the flag set and environment func (f *Uint64SliceFlag) Apply(set *flag.FlagSet) error { // apply any default @@ -172,17 +180,6 @@ func (f *Uint64SliceFlag) Get(ctx *Context) []uint64 { return ctx.Uint64Slice(f.Name) } -func (f *Uint64SliceFlag) stringify() string { - var defaultVals []string - if f.Value != nil && len(f.Value.Value()) > 0 { - for _, i := range f.Value.Value() { - defaultVals = append(defaultVals, strconv.FormatUint(i, 10)) - } - } - - return stringifySliceFlag(f.Usage, f.Names(), defaultVals) -} - // Uint64Slice looks up the value of a local Uint64SliceFlag, returns // nil if not found func (cCtx *Context) Uint64Slice(name string) []uint64 { diff --git a/flag_uint_slice.go b/flag_uint_slice.go index 350b29ccf0..363aa657f3 100644 --- a/flag_uint_slice.go +++ b/flag_uint_slice.go @@ -99,7 +99,7 @@ func (i *UintSlice) Get() interface{} { // String returns a readable representation of this value // (for usage defaults) func (f *UintSliceFlag) String() string { - return withEnvHint(f.GetEnvVars(), f.stringify()) + return FlagStringer(f) } // TakesValue returns true of the flag takes a value, otherwise false @@ -120,10 +120,13 @@ func (f *UintSliceFlag) GetCategory() string { // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *UintSliceFlag) GetValue() string { - if f.Value != nil { - return f.Value.String() + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strconv.FormatUint(uint64(i), 10)) + } } - return "" + return strings.Join(defaultVals, ", ") } // GetDefaultText returns the default text for this flag @@ -139,6 +142,11 @@ func (f *UintSliceFlag) GetEnvVars() []string { return f.EnvVars } +// IsSliceFlag implements DocGenerationSliceFlag. +func (f *UintSliceFlag) IsSliceFlag() bool { + return true +} + // Apply populates the flag given the flag set and environment func (f *UintSliceFlag) Apply(set *flag.FlagSet) error { // apply any default @@ -183,17 +191,6 @@ func (f *UintSliceFlag) Get(ctx *Context) []uint { return ctx.UintSlice(f.Name) } -func (f *UintSliceFlag) stringify() string { - var defaultVals []string - if f.Value != nil && len(f.Value.Value()) > 0 { - for _, i := range f.Value.Value() { - defaultVals = append(defaultVals, strconv.FormatUint(uint64(i), 10)) - } - } - - return stringifySliceFlag(f.Usage, f.Names(), defaultVals) -} - // UintSlice looks up the value of a local UintSliceFlag, returns // nil if not found func (cCtx *Context) UintSlice(name string) []uint { From 2ee25484767bd563966c237cb5f74eb13d31874b Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Thu, 29 Sep 2022 20:49:22 -0400 Subject: [PATCH 05/18] Fix:(issue_1505) Fix flag alignment in help --- template.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/template.go b/template.go index 9e13604f35..53a76b74cf 100644 --- a/template.go +++ b/template.go @@ -56,8 +56,8 @@ OPTIONS:{{range .VisibleFlagCategories}} {{if .Name}}{{.Name}} {{end}}{{range .Flags}}{{.}}{{end}}{{end}}{{else}}{{if .VisibleFlags}} -OPTIONS: - {{range .VisibleFlags}}{{.}}{{end}}{{end}}{{end}} +OPTIONS:{{range .VisibleFlags}} + {{.}}{{end}}{{end}}{{end}} ` // SubcommandHelpTemplate is the text template for the subcommand help topic. @@ -70,15 +70,24 @@ USAGE: {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}} + {{wrap .Description 3}}{{end}}{{if .VisibleCommands}} COMMANDS:{{range .VisibleCategories}}{{if .Name}} {{.Name}}:{{range .VisibleCommands}} {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} + {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} -OPTIONS: - {{range .VisibleFlags}}{{.}}{{end}}{{end}} +COMMANDS:{{range .VisibleCategories}}{{if .Name}} + {{.Name}}:{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} + {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} + +OPTIONS:{{range .VisibleFlagCategories}} + {{if .Name}}{{.Name}}{{end}}{{range .Flags}}{{.}} + {{end}}{{end}}{{else}}{{if .VisibleFlags}} + +OPTIONS:{{range $index, $option := .VisibleFlags}}{{if $index}}{{end}} + {{wrap $option.String 6}}{{end}}{{end}}{{end}} ` var MarkdownDocTemplate = `{{if gt .SectionNum 0}}% {{ .App.Name }} {{ .SectionNum }} From 2da6e685553ebc07aad40c14a3f1b1ead317bcfe Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Thu, 29 Sep 2022 21:06:07 -0400 Subject: [PATCH 06/18] Fix command help subcommand --- command.go | 11 +++++++++++ template.go | 11 ++--------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/command.go b/command.go index d24b61e239..e66985e71f 100644 --- a/command.go +++ b/command.go @@ -295,6 +295,17 @@ func (c *Command) startApp(ctx *Context) error { return app.RunAsSubcommand(ctx) } +// VisibleCommands returns a slice of the Commands with Hidden=false +func (c *Command) VisibleCommands() []*Command { + var ret []*Command + for _, command := range c.Subcommands { + if !command.Hidden { + ret = append(ret, command) + } + } + return ret +} + // VisibleFlagCategories returns a slice containing all the visible flag categories with the flags they contain func (c *Command) VisibleFlagCategories() []VisibleFlagCategory { if c.flagCategories == nil { diff --git a/template.go b/template.go index 53a76b74cf..bb9cbc42b8 100644 --- a/template.go +++ b/template.go @@ -72,16 +72,9 @@ USAGE: DESCRIPTION: {{wrap .Description 3}}{{end}}{{if .VisibleCommands}} -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} +COMMANDS:{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} + {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{if .VisibleFlagCategories}} -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} - OPTIONS:{{range .VisibleFlagCategories}} {{if .Name}}{{.Name}}{{end}}{{range .Flags}}{{.}} {{end}}{{end}}{{else}}{{if .VisibleFlags}} From 6504da449b46d7af9c37346e58e9673054d4f33c Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Fri, 30 Sep 2022 08:23:18 -0400 Subject: [PATCH 07/18] Add test case --- app_test.go | 2 +- help.go | 6 +++- help_test.go | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ template.go | 8 +++--- 4 files changed, 89 insertions(+), 6 deletions(-) diff --git a/app_test.go b/app_test.go index f7ecd135fc..d3fa3dfdad 100644 --- a/app_test.go +++ b/app_test.go @@ -177,7 +177,7 @@ func ExampleApp_Run_commandHelp() { // greet describeit - use it to see a description // // USAGE: - // greet describeit [command options] [arguments...] + // greet describeit [arguments...] // // DESCRIPTION: // This is how we describe describeit the function diff --git a/help.go b/help.go index 6929a226ab..45e6f2b3cd 100644 --- a/help.go +++ b/help.go @@ -242,7 +242,11 @@ func ShowCommandHelp(ctx *Context, command string) error { c.Subcommands = append(c.Subcommands, helpCommandDontUse) } if !ctx.App.HideHelp && HelpFlag != nil { - c.appendFlag(HelpFlag) + if c.flagCategories == nil { + c.flagCategories = newFlagCategoriesFromFlags([]Flag{HelpFlag}) + } else { + c.flagCategories.AddFlag("", HelpFlag) + } } templ := c.CustomHelpTemplate if templ == "" { diff --git a/help_test.go b/help_test.go index d7cdfa2d8f..6b1e8c6b4e 100644 --- a/help_test.go +++ b/help_test.go @@ -1367,6 +1367,7 @@ DESCRIPTION: OPTIONS: --help, -h show help (default: false) + ` if output.String() != expected { @@ -1436,6 +1437,84 @@ USAGE: OPTIONS: --help, -h show help (default: false) + +` + + if output.String() != expected { + t.Errorf("Unexpected wrapping, got:\n%s\nexpected: %s", + output.String(), expected) + } +} + +func TestWrappedHelpSubcommand(t *testing.T) { + + // Reset HelpPrinter after this test. + defer func(old helpPrinter) { + HelpPrinter = old + }(HelpPrinter) + + output := new(bytes.Buffer) + app := &App{ + Name: "cli.test", + Writer: output, + Commands: []*Command{ + { + Name: "bar", + Aliases: []string{"a"}, + Usage: "add a task to the list", + UsageText: "this is an even longer way of describing adding a task to the list", + Description: "and a description long enough to wrap in this test case", + Action: func(c *Context) error { + return nil + }, + Subcommands: []*Command{ + { + Name: "grok", + Usage: "remove an existing template", + UsageText: "longer usage text goes here, la la la, hopefully this is long enough to wrap even more", + Action: func(c *Context) error { + return nil + }, + Flags: []Flag{ + &StringFlag{ + Name: "test-f", + Usage: "my test usage", + }, + }, + }, + }, + }, + }, + } + + HelpPrinter = func(w io.Writer, templ string, data interface{}) { + funcMap := map[string]interface{}{ + "wrapAt": func() int { + return 30 + }, + } + + HelpPrinterCustom(w, templ, data, funcMap) + } + + _ = app.Run([]string{"foo", "bar", "help", "grok"}) + + expected := `NAME: + cli.test bar grok - remove + an + existing + template + +USAGE: + longer usage text goes + here, la la la, hopefully + this is long enough to wrap + even more + +OPTIONS: + --help, -h show help (default: false) + --test-f value my test usage + ` if output.String() != expected { diff --git a/template.go b/template.go index bb9cbc42b8..d67931bba0 100644 --- a/template.go +++ b/template.go @@ -54,10 +54,10 @@ DESCRIPTION: OPTIONS:{{range .VisibleFlagCategories}} {{if .Name}}{{.Name}} - {{end}}{{range .Flags}}{{.}}{{end}}{{end}}{{else}}{{if .VisibleFlags}} - -OPTIONS:{{range .VisibleFlags}} - {{.}}{{end}}{{end}}{{end}} + {{end}}{{range .Flags}}{{.}} + {{end}}{{end}}{{else}}{{if .VisibleFlags}} +OPTIONS:{{range $index, $option := .VisibleFlags}}{{if $index}}{{end}} + {{wrap $option.String 6}}{{end}}{{end}}{{end}} ` // SubcommandHelpTemplate is the text template for the subcommand help topic. From 8f6acfe15d2c4ff62094c6cf15613607729599e2 Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Fri, 30 Sep 2022 12:12:41 -0400 Subject: [PATCH 08/18] Componentize template --- help.go | 11 +++++++ help_test.go | 9 ++---- template.go | 81 ++++++++++++++++++++++++++++------------------------ 3 files changed, 58 insertions(+), 43 deletions(-) diff --git a/help.go b/help.go index 45e6f2b3cd..d78444a0c6 100644 --- a/help.go +++ b/help.go @@ -362,6 +362,17 @@ func printHelpCustom(out io.Writer, templ string, data interface{}, customFuncs w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0) t := template.Must(template.New("help").Funcs(funcMap).Parse(templ)) + t.New("helpNameTemplate").Parse(helpNameTemplate) + t.New("usageTemplate").Parse(usageTemplate) + t.New("descriptionTemplate").Parse(descriptionTemplate) + t.New("visibleCommandTemplate").Parse(visibleCommandTemplate) + t.New("copyrightTemplate").Parse(copyrightTemplate) + t.New("versionTemplate").Parse(versionTemplate) + t.New("visibleFlagCategoryTemplate").Parse(visibleFlagCategoryTemplate) + t.New("visibleFlagTemplate").Parse(visibleFlagTemplate) + t.New("visibleGlobalFlagCategoryTemplate").Parse(strings.Replace(visibleFlagCategoryTemplate, "OPTIONS", "GLOBAL OPTIONS", -1)) + t.New("authorsTemplate").Parse(authorsTemplate) + t.New("visibleCommandCategoryTemplate").Parse(visibleCommandCategoryTemplate) err := t.Execute(w, data) if err != nil { diff --git a/help_test.go b/help_test.go index 6b1e8c6b4e..de8e2f0cd9 100644 --- a/help_test.go +++ b/help_test.go @@ -1367,8 +1367,7 @@ DESCRIPTION: OPTIONS: --help, -h show help (default: false) - -` + ` if output.String() != expected { t.Errorf("Unexpected wrapping, got:\n%s\nexpected:\n%s", @@ -1437,8 +1436,7 @@ USAGE: OPTIONS: --help, -h show help (default: false) - -` + ` if output.String() != expected { t.Errorf("Unexpected wrapping, got:\n%s\nexpected: %s", @@ -1514,8 +1512,7 @@ USAGE: OPTIONS: --help, -h show help (default: false) --test-f value my test usage - -` + ` if output.String() != expected { t.Errorf("Unexpected wrapping, got:\n%s\nexpected: %s", diff --git a/template.go b/template.go index d67931bba0..dfdd434cce 100644 --- a/template.go +++ b/template.go @@ -1,10 +1,36 @@ package cli +var helpNameTemplate = `{{$v := offset .HelpName 6}}{{wrap .HelpName 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}}` +var usageTemplate = `{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}` +var descriptionTemplate = `{{wrap .Description 3}}` +var authorsTemplate = `{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: + {{range $index, $author := .Authors}}{{if $index}} + {{end}}{{$author}}{{end}}` +var visibleCommandTemplate = `{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} + {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}` +var visibleCommandCategoryTemplate = `{{range .VisibleCategories}}{{if .Name}} + {{.Name}}:{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{template "visibleCommandTemplate" .}}{{end}}{{end}}` +var visibleFlagCategoryTemplate = `{{range .VisibleFlagCategories}} + {{if .Name}}{{.Name}} + {{end}}{{range .Flags}}{{.}} + {{end}}{{end}}` + +var visibleFlagTemplate = `{{range $index, $option := .VisibleFlags}}{{if $index}}{{end}} + {{wrap $option.String 6}}{{end}}` + +var versionTemplate = `{{if .Version}}{{if not .HideVersion}} + +VERSION: + {{.Version}}{{end}}{{end}}` + +var copyrightTemplate = `{{wrap .Copyright 3}}` + // AppHelpTemplate is the text template for the Default help topic. // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. var AppHelpTemplate = `NAME: - {{$v := offset .Name 6}}{{wrap .Name 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}} + {{template "helpNameTemplate" .}} USAGE: {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} @@ -13,75 +39,56 @@ VERSION: {{.Version}}{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}}{{if len .Authors}} + {{template "descriptionTemplate" .}}{{end}}{{if len .Authors}} -AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: - {{range $index, $author := .Authors}}{{if $index}} - {{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}} +AUTHOR{{template "authorsTemplate" .}}{{end}}{{if .VisibleCommands}} -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} +COMMANDS:{{template "visibleCommandCategoryTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -GLOBAL OPTIONS:{{range .VisibleFlagCategories}} - {{if .Name}}{{.Name}} - {{end}}{{range .Flags}}{{.}} - {{end}}{{end}}{{else}}{{if .VisibleFlags}} +GLOBAL OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -GLOBAL OPTIONS: - {{range $index, $option := .VisibleFlags}}{{if $index}} - {{end}}{{wrap $option.String 6}}{{end}}{{end}}{{end}}{{if .Copyright}} +GLOBAL OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}{{if .Copyright}} COPYRIGHT: - {{wrap .Copyright 3}}{{end}} + {{template "copyrightTemplate" .}}{{end}} ` // CommandHelpTemplate is the text template for the command help topic. // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. var CommandHelpTemplate = `NAME: - {{$v := offset .HelpName 6}}{{wrap .HelpName 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}} + {{template "helpNameTemplate" .}} USAGE: - {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}} + {{template "usageTemplate" .}}{{if .Category}} CATEGORY: {{.Category}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}}{{if .VisibleFlagCategories}} + {{template "descriptionTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -OPTIONS:{{range .VisibleFlagCategories}} - {{if .Name}}{{.Name}} - {{end}}{{range .Flags}}{{.}} - {{end}}{{end}}{{else}}{{if .VisibleFlags}} -OPTIONS:{{range $index, $option := .VisibleFlags}}{{if $index}}{{end}} - {{wrap $option.String 6}}{{end}}{{end}}{{end}} -` +OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} + +OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}` // SubcommandHelpTemplate is the text template for the subcommand help topic. // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. var SubcommandHelpTemplate = `NAME: - {{.HelpName}} - {{.Usage}} + {{template "helpNameTemplate" .}} USAGE: {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}}{{if .VisibleCommands}} + {{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}} -COMMANDS:{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{if .VisibleFlagCategories}} +COMMANDS:{{template "visibleCommandTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -OPTIONS:{{range .VisibleFlagCategories}} - {{if .Name}}{{.Name}}{{end}}{{range .Flags}}{{.}} - {{end}}{{end}}{{else}}{{if .VisibleFlags}} +OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -OPTIONS:{{range $index, $option := .VisibleFlags}}{{if $index}}{{end}} - {{wrap $option.String 6}}{{end}}{{end}}{{end}} -` +OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}` var MarkdownDocTemplate = `{{if gt .SectionNum 0}}% {{ .App.Name }} {{ .SectionNum }} From 0b2aca7ccc3d689b941e73179c7cafd37fe1f77d Mon Sep 17 00:00:00 2001 From: dearchap Date: Wed, 5 Oct 2022 08:35:11 -0400 Subject: [PATCH 09/18] Update template.go Co-authored-by: Anatoli Babenia --- template.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/template.go b/template.go index dfdd434cce..f48e5099f3 100644 --- a/template.go +++ b/template.go @@ -39,7 +39,8 @@ VERSION: {{.Version}}{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{template "descriptionTemplate" .}}{{end}}{{if len .Authors}} + {{template "descriptionTemplate" .}}{{end}} +{{- if len .Authors}} AUTHOR{{template "authorsTemplate" .}}{{end}}{{if .VisibleCommands}} From 05db729d667f9f6339010c34709ebdfe2f3176df Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Wed, 5 Oct 2022 10:00:37 -0400 Subject: [PATCH 10/18] Do make v2approve --- godoc-current.txt | 93 +++++++++++++++++++++++------------------ testdata/godoc-v2.x.txt | 93 +++++++++++++++++++++++------------------ 2 files changed, 106 insertions(+), 80 deletions(-) diff --git a/godoc-current.txt b/godoc-current.txt index 3d5cb9a298..73e3419efa 100644 --- a/godoc-current.txt +++ b/godoc-current.txt @@ -32,7 +32,7 @@ var ( SuggestDidYouMeanTemplate string = suggestDidYouMeanTemplate ) var AppHelpTemplate = `NAME: - {{$v := offset .Name 6}}{{wrap .Name 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}} + {{template "helpNameTemplate" .}} USAGE: {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} @@ -41,52 +41,39 @@ VERSION: {{.Version}}{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}}{{if len .Authors}} + {{template "descriptionTemplate" .}}{{end}} +{{- if len .Authors}} -AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: - {{range $index, $author := .Authors}}{{if $index}} - {{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}} +AUTHOR{{template "authorsTemplate" .}}{{end}}{{if .VisibleCommands}} -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} +COMMANDS:{{template "visibleCommandCategoryTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -GLOBAL OPTIONS:{{range .VisibleFlagCategories}} - {{if .Name}}{{.Name}} - {{end}}{{range .Flags}}{{.}} - {{end}}{{end}}{{else}}{{if .VisibleFlags}} +GLOBAL OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -GLOBAL OPTIONS: - {{range $index, $option := .VisibleFlags}}{{if $index}} - {{end}}{{wrap $option.String 6}}{{end}}{{end}}{{end}}{{if .Copyright}} +GLOBAL OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}{{if .Copyright}} COPYRIGHT: - {{wrap .Copyright 3}}{{end}} + {{template "copyrightTemplate" .}}{{end}} ` AppHelpTemplate is the text template for the Default help topic. cli.go uses text/template to render templates. You can render custom help text by setting this variable. var CommandHelpTemplate = `NAME: - {{$v := offset .HelpName 6}}{{wrap .HelpName 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}} + {{template "helpNameTemplate" .}} USAGE: - {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}} + {{template "usageTemplate" .}}{{if .Category}} CATEGORY: {{.Category}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}}{{if .VisibleFlagCategories}} + {{template "descriptionTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -OPTIONS:{{range .VisibleFlagCategories}} - {{if .Name}}{{.Name}} - {{end}}{{range .Flags}}{{.}}{{end}}{{end}}{{else}}{{if .VisibleFlags}} +OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -OPTIONS: - {{range .VisibleFlags}}{{.}}{{end}}{{end}}{{end}} -` +OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}` CommandHelpTemplate is the text template for the command help topic. cli.go uses text/template to render templates. You can render custom help text by setting this variable. @@ -145,22 +132,19 @@ var OsExiter = os.Exit os.Exit. var SubcommandHelpTemplate = `NAME: - {{.HelpName}} - {{.Usage}} + {{template "helpNameTemplate" .}} USAGE: {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}} + {{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}} -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} +COMMANDS:{{template "visibleCommandTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -OPTIONS: - {{range .VisibleFlags}}{{.}}{{end}}{{end}} -` +OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} + +OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}` SubcommandHelpTemplate is the text template for the subcommand help topic. cli.go uses text/template to render templates. You can render custom help text by setting this variable. @@ -458,6 +442,8 @@ type BoolFlag struct { EnvVars []string Count *int + + Action func(*Context, bool) error } BoolFlag is a flag with type bool @@ -565,7 +551,6 @@ type Command struct { // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. CustomHelpTemplate string - // Has unexported fields. } Command is a subcommand for a cli.App. @@ -584,10 +569,6 @@ func (c *Command) Run(ctx *Context) (err error) Run invokes the command given the context, parses ctx.Args() to generate command-specific flags -func (c *Command) VisibleCategories() []CommandCategory - VisibleCategories returns a slice of categories and commands that are - Hidden=false - func (c *Command) VisibleCommands() []*Command VisibleCommands returns a slice of the Commands with Hidden=false @@ -776,6 +757,8 @@ type DurationFlag struct { Aliases []string EnvVars []string + + Action func(*Context, time.Duration) error } DurationFlag is a flag with type time.Duration @@ -952,6 +935,8 @@ type Float64Flag struct { Aliases []string EnvVars []string + + Action func(*Context, float64) error } Float64Flag is a flag with type float64 @@ -1038,6 +1023,8 @@ type Float64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []float64) error } Float64SliceFlag is a flag with type *Float64Slice @@ -1115,6 +1102,8 @@ type GenericFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, interface{}) error } GenericFlag is a flag with type Generic @@ -1181,6 +1170,8 @@ type Int64Flag struct { EnvVars []string Base int + + Action func(*Context, int64) error } Int64Flag is a flag with type int64 @@ -1267,6 +1258,8 @@ type Int64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []int64) error } Int64SliceFlag is a flag with type *Int64Slice @@ -1338,6 +1331,8 @@ type IntFlag struct { EnvVars []string Base int + + Action func(*Context, int) error } IntFlag is a flag with type int @@ -1428,6 +1423,8 @@ type IntSliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []int) error } IntSliceFlag is a flag with type *IntSlice @@ -1533,6 +1530,8 @@ type PathFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, Path) error } PathFlag is a flag with type Path @@ -1673,6 +1672,8 @@ type StringFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, string) error } StringFlag is a flag with type string @@ -1761,6 +1762,8 @@ type StringSliceFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, []string) error } StringSliceFlag is a flag with type *StringSlice @@ -1867,6 +1870,8 @@ type TimestampFlag struct { Layout string Timezone *time.Location + + Action func(*Context, *time.Time) error } TimestampFlag is a flag with type *Timestamp @@ -1932,6 +1937,8 @@ type Uint64Flag struct { EnvVars []string Base int + + Action func(*Context, uint64) error } Uint64Flag is a flag with type uint64 @@ -2018,6 +2025,8 @@ type Uint64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []uint64) error } Uint64SliceFlag is a flag with type *Uint64Slice @@ -2080,6 +2089,8 @@ type UintFlag struct { EnvVars []string Base int + + Action func(*Context, uint) error } UintFlag is a flag with type uint @@ -2170,6 +2181,8 @@ type UintSliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []uint) error } UintSliceFlag is a flag with type *UintSlice diff --git a/testdata/godoc-v2.x.txt b/testdata/godoc-v2.x.txt index 3d5cb9a298..73e3419efa 100644 --- a/testdata/godoc-v2.x.txt +++ b/testdata/godoc-v2.x.txt @@ -32,7 +32,7 @@ var ( SuggestDidYouMeanTemplate string = suggestDidYouMeanTemplate ) var AppHelpTemplate = `NAME: - {{$v := offset .Name 6}}{{wrap .Name 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}} + {{template "helpNameTemplate" .}} USAGE: {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} @@ -41,52 +41,39 @@ VERSION: {{.Version}}{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}}{{if len .Authors}} + {{template "descriptionTemplate" .}}{{end}} +{{- if len .Authors}} -AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: - {{range $index, $author := .Authors}}{{if $index}} - {{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}} +AUTHOR{{template "authorsTemplate" .}}{{end}}{{if .VisibleCommands}} -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}} +COMMANDS:{{template "visibleCommandCategoryTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -GLOBAL OPTIONS:{{range .VisibleFlagCategories}} - {{if .Name}}{{.Name}} - {{end}}{{range .Flags}}{{.}} - {{end}}{{end}}{{else}}{{if .VisibleFlags}} +GLOBAL OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -GLOBAL OPTIONS: - {{range $index, $option := .VisibleFlags}}{{if $index}} - {{end}}{{wrap $option.String 6}}{{end}}{{end}}{{end}}{{if .Copyright}} +GLOBAL OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}{{if .Copyright}} COPYRIGHT: - {{wrap .Copyright 3}}{{end}} + {{template "copyrightTemplate" .}}{{end}} ` AppHelpTemplate is the text template for the Default help topic. cli.go uses text/template to render templates. You can render custom help text by setting this variable. var CommandHelpTemplate = `NAME: - {{$v := offset .HelpName 6}}{{wrap .HelpName 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}} + {{template "helpNameTemplate" .}} USAGE: - {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}} + {{template "usageTemplate" .}}{{if .Category}} CATEGORY: {{.Category}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}}{{if .VisibleFlagCategories}} + {{template "descriptionTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -OPTIONS:{{range .VisibleFlagCategories}} - {{if .Name}}{{.Name}} - {{end}}{{range .Flags}}{{.}}{{end}}{{end}}{{else}}{{if .VisibleFlags}} +OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -OPTIONS: - {{range .VisibleFlags}}{{.}}{{end}}{{end}}{{end}} -` +OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}` CommandHelpTemplate is the text template for the command help topic. cli.go uses text/template to render templates. You can render custom help text by setting this variable. @@ -145,22 +132,19 @@ var OsExiter = os.Exit os.Exit. var SubcommandHelpTemplate = `NAME: - {{.HelpName}} - {{.Usage}} + {{template "helpNameTemplate" .}} USAGE: {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{wrap .Description 3}}{{end}} + {{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}} -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} - {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} +COMMANDS:{{template "visibleCommandTemplate" .}}{{end}}{{if .VisibleFlagCategories}} -OPTIONS: - {{range .VisibleFlags}}{{.}}{{end}}{{end}} -` +OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} + +OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}` SubcommandHelpTemplate is the text template for the subcommand help topic. cli.go uses text/template to render templates. You can render custom help text by setting this variable. @@ -458,6 +442,8 @@ type BoolFlag struct { EnvVars []string Count *int + + Action func(*Context, bool) error } BoolFlag is a flag with type bool @@ -565,7 +551,6 @@ type Command struct { // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. CustomHelpTemplate string - // Has unexported fields. } Command is a subcommand for a cli.App. @@ -584,10 +569,6 @@ func (c *Command) Run(ctx *Context) (err error) Run invokes the command given the context, parses ctx.Args() to generate command-specific flags -func (c *Command) VisibleCategories() []CommandCategory - VisibleCategories returns a slice of categories and commands that are - Hidden=false - func (c *Command) VisibleCommands() []*Command VisibleCommands returns a slice of the Commands with Hidden=false @@ -776,6 +757,8 @@ type DurationFlag struct { Aliases []string EnvVars []string + + Action func(*Context, time.Duration) error } DurationFlag is a flag with type time.Duration @@ -952,6 +935,8 @@ type Float64Flag struct { Aliases []string EnvVars []string + + Action func(*Context, float64) error } Float64Flag is a flag with type float64 @@ -1038,6 +1023,8 @@ type Float64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []float64) error } Float64SliceFlag is a flag with type *Float64Slice @@ -1115,6 +1102,8 @@ type GenericFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, interface{}) error } GenericFlag is a flag with type Generic @@ -1181,6 +1170,8 @@ type Int64Flag struct { EnvVars []string Base int + + Action func(*Context, int64) error } Int64Flag is a flag with type int64 @@ -1267,6 +1258,8 @@ type Int64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []int64) error } Int64SliceFlag is a flag with type *Int64Slice @@ -1338,6 +1331,8 @@ type IntFlag struct { EnvVars []string Base int + + Action func(*Context, int) error } IntFlag is a flag with type int @@ -1428,6 +1423,8 @@ type IntSliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []int) error } IntSliceFlag is a flag with type *IntSlice @@ -1533,6 +1530,8 @@ type PathFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, Path) error } PathFlag is a flag with type Path @@ -1673,6 +1672,8 @@ type StringFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, string) error } StringFlag is a flag with type string @@ -1761,6 +1762,8 @@ type StringSliceFlag struct { EnvVars []string TakesFile bool + + Action func(*Context, []string) error } StringSliceFlag is a flag with type *StringSlice @@ -1867,6 +1870,8 @@ type TimestampFlag struct { Layout string Timezone *time.Location + + Action func(*Context, *time.Time) error } TimestampFlag is a flag with type *Timestamp @@ -1932,6 +1937,8 @@ type Uint64Flag struct { EnvVars []string Base int + + Action func(*Context, uint64) error } Uint64Flag is a flag with type uint64 @@ -2018,6 +2025,8 @@ type Uint64SliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []uint64) error } Uint64SliceFlag is a flag with type *Uint64Slice @@ -2080,6 +2089,8 @@ type UintFlag struct { EnvVars []string Base int + + Action func(*Context, uint) error } UintFlag is a flag with type uint @@ -2170,6 +2181,8 @@ type UintSliceFlag struct { Aliases []string EnvVars []string + + Action func(*Context, []uint) error } UintSliceFlag is a flag with type *UintSlice From d5a1252ef3d30a4ed4e2c9424a5322df44c713a0 Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Wed, 5 Oct 2022 13:52:05 -0400 Subject: [PATCH 11/18] Add test coverage for Command.VisibleCommands() --- command_test.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/command_test.go b/command_test.go index 9dfd46f476..a953e943cd 100644 --- a/command_test.go +++ b/command_test.go @@ -422,3 +422,30 @@ func TestCommand_CanAddVFlagOnCommands(t *testing.T) { err := app.Run([]string{"foo", "bar"}) expect(t, err, nil) } + +func TestCommand_VisibleSubcCommands(t *testing.T) { + + subc1 := &Command{ + Name: "subc1", + Usage: "subc1 command1", + } + subc3 := &Command{ + Name: "subc3", + Usage: "subc3 command2", + } + c := &Command{ + Name: "bar", + Usage: "this is for testing", + Subcommands: []*Command{ + subc1, + { + Name: "subc2", + Usage: "subc2 command2", + Hidden: true, + }, + subc3, + }, + } + + expect(t, c.VisibleCommands(), []*Command{subc1, subc3}) +} From 194ed2bb9b5e6ed113b30a51165291fd8e1ad8d5 Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Wed, 5 Oct 2022 14:40:59 -0400 Subject: [PATCH 12/18] Remove extra 3 spaces in last line --- help_test.go | 6 +++--- template.go | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/help_test.go b/help_test.go index de8e2f0cd9..37410a5449 100644 --- a/help_test.go +++ b/help_test.go @@ -1367,7 +1367,7 @@ DESCRIPTION: OPTIONS: --help, -h show help (default: false) - ` +` if output.String() != expected { t.Errorf("Unexpected wrapping, got:\n%s\nexpected:\n%s", @@ -1436,7 +1436,7 @@ USAGE: OPTIONS: --help, -h show help (default: false) - ` +` if output.String() != expected { t.Errorf("Unexpected wrapping, got:\n%s\nexpected: %s", @@ -1512,7 +1512,7 @@ USAGE: OPTIONS: --help, -h show help (default: false) --test-f value my test usage - ` +` if output.String() != expected { t.Errorf("Unexpected wrapping, got:\n%s\nexpected: %s", diff --git a/template.go b/template.go index f48e5099f3..1133b8907c 100644 --- a/template.go +++ b/template.go @@ -13,8 +13,10 @@ var visibleCommandCategoryTemplate = `{{range .VisibleCategories}}{{if .Name}} {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{template "visibleCommandTemplate" .}}{{end}}{{end}}` var visibleFlagCategoryTemplate = `{{range .VisibleFlagCategories}} {{if .Name}}{{.Name}} - {{end}}{{range .Flags}}{{.}} - {{end}}{{end}}` + + {{end}}{{$flglen := len .Flags}}{{range $i, $e := .Flags}}{{if eq (subtract $flglen $i) 1}}{{$e}} +{{else}}{{$e}} + {{end}}{{end}}{{end}}` var visibleFlagTemplate = `{{range $index, $option := .VisibleFlags}}{{if $index}}{{end}} {{wrap $option.String 6}}{{end}}` From 891ffb017b0946dca5f095853e52f82b57f34d93 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Tue, 26 Jul 2022 16:13:05 +0200 Subject: [PATCH 13/18] Add DestinationPointer for flags generator In this commit I added a DestinationPointer variable that should be set if the `Destination` should be configured as a pointer for a specific flag type. It is expected that Generic type which is an interface will not be a pointer but a struct. Before this change the code compilation was failing with `type *Generic is pointer to interface, not interface`. See https://github.com/urfave/cli/issues/1441 --- cmd/urfave-cli-genflags/generated.gotmpl | 4 + cmd/urfave-cli-genflags/main_test.go | 20 +++- flag-spec.yaml | 27 ++++++ internal/genflags/spec.go | 117 +++++++++++++++++++++++ 4 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 internal/genflags/spec.go diff --git a/cmd/urfave-cli-genflags/generated.gotmpl b/cmd/urfave-cli-genflags/generated.gotmpl index 91312f8d5a..d8c67432ee 100644 --- a/cmd/urfave-cli-genflags/generated.gotmpl +++ b/cmd/urfave-cli-genflags/generated.gotmpl @@ -17,7 +17,11 @@ type {{.TypeName}} struct { HasBeenSet bool Value {{if .ValuePointer}}*{{end}}{{.GoType}} +<<<<<<< HEAD:cmd/urfave-cli-genflags/generated.gotmpl Destination {{if .NoDestinationPointer}}{{else}}*{{end}}{{.GoType}} +======= + Destination {{if .DestinationPointer}}*{{end}}{{.GoType}} +>>>>>>> Add DestinationPointer for flags generator:internal/genflags/generated.gotmpl Aliases []string EnvVars []string diff --git a/cmd/urfave-cli-genflags/main_test.go b/cmd/urfave-cli-genflags/main_test.go index b5c9fee8ca..61563b1513 100644 --- a/cmd/urfave-cli-genflags/main_test.go +++ b/cmd/urfave-cli-genflags/main_test.go @@ -80,8 +80,9 @@ func genFlagType() *main.FlagType { Type: "bool", }, }, - TypeName: "YeOldeBlerfFlag", - ValuePointer: true, + TypeName: "YeOldeBlerfFlag", + ValuePointer: true, + DestinationPointer: true, }, } } @@ -115,6 +116,21 @@ func TestFlagType_ValuePointer(t *testing.T) { } } +func TestFlagType_DestinationPointer(t *testing.T) { + ft := genFlagType() + + if !ft.DestinationPointer() { + t.Errorf("expected DestinationPointer to be true") + return + } + + ft.Config = nil + + if ft.DestinationPointer() { + t.Errorf("expected DestinationPointer to be false") + } +} + func TestFlagType_GenerateFmtStringerInterface(t *testing.T) { ft := genFlagType() diff --git a/flag-spec.yaml b/flag-spec.yaml index 76480ba47c..9a68cddb8f 100644 --- a/flag-spec.yaml +++ b/flag-spec.yaml @@ -2,6 +2,7 @@ # ./cmd/urfave-cli-genflags/main.go which uses the # `Spec` type that maps to this file structure. flag_types: +<<<<<<< HEAD bool: struct_fields: - name: Count @@ -13,8 +14,30 @@ flag_types: struct_fields: - name: Action type: "func(*Context, float64) error" +======= + bool: {} + float64: {} + int64: {} + int: {} + time.Duration: {} + uint64: {} + uint: {} + + string: + destination_pointer: true + struct_fields: + - { name: TakesFile, type: bool } + Generic: + struct_fields: + - { name: TakesFile, type: bool } + Path: + destination_pointer: true + struct_fields: + - { name: TakesFile, type: bool } +>>>>>>> Add DestinationPointer for flags generator Float64Slice: value_pointer: true + destination_pointer: true skip_interfaces: - fmt.Stringer struct_fields: @@ -41,6 +64,7 @@ flag_types: type: "func(*Context, int64) error" Int64Slice: value_pointer: true + destination_pointer: true skip_interfaces: - fmt.Stringer struct_fields: @@ -54,6 +78,7 @@ flag_types: type: "func(*Context, uint) error" UintSlice: value_pointer: true + destination_pointer: true skip_interfaces: - fmt.Stringer struct_fields: @@ -80,6 +105,7 @@ flag_types: type: "func(*Context, string) error" StringSlice: value_pointer: true + destination_pointer: true skip_interfaces: - fmt.Stringer struct_fields: @@ -93,6 +119,7 @@ flag_types: type: "func(*Context, time.Duration) error" Timestamp: value_pointer: true + destination_pointer: true struct_fields: - name: Layout type: string diff --git a/internal/genflags/spec.go b/internal/genflags/spec.go new file mode 100644 index 0000000000..deff8c9307 --- /dev/null +++ b/internal/genflags/spec.go @@ -0,0 +1,117 @@ +package genflags + +import ( + "sort" + "strings" +) + +type Spec struct { + FlagTypes map[string]*FlagTypeConfig `yaml:"flag_types"` + PackageName string `yaml:"package_name"` + TestPackageName string `yaml:"test_package_name"` + UrfaveCLINamespace string `yaml:"urfave_cli_namespace"` + UrfaveCLITestNamespace string `yaml:"urfave_cli_test_namespace"` +} + +func (gfs *Spec) SortedFlagTypes() []*FlagType { + typeNames := []string{} + + for name := range gfs.FlagTypes { + if strings.HasPrefix(name, "[]") { + name = strings.TrimPrefix(name, "[]") + "Slice" + } + + typeNames = append(typeNames, name) + } + + sort.Strings(typeNames) + + ret := make([]*FlagType, len(typeNames)) + + for i, typeName := range typeNames { + ret[i] = &FlagType{ + GoType: typeName, + Config: gfs.FlagTypes[typeName], + } + } + + return ret +} + +type FlagTypeConfig struct { + SkipInterfaces []string `yaml:"skip_interfaces"` + StructFields []*FlagStructField `yaml:"struct_fields"` + TypeName string `yaml:"type_name"` + ValuePointer bool `yaml:"value_pointer"` + DestinationPointer bool `yaml:"destination_pointer"` +} + +type FlagStructField struct { + Name string + Type string +} + +type FlagType struct { + GoType string + Config *FlagTypeConfig +} + +func (ft *FlagType) StructFields() []*FlagStructField { + if ft.Config == nil || ft.Config.StructFields == nil { + return []*FlagStructField{} + } + + return ft.Config.StructFields +} + +func (ft *FlagType) ValuePointer() bool { + if ft.Config == nil { + return false + } + + return ft.Config.ValuePointer +} + +func (ft *FlagType) DestinationPointer() bool { + if ft.Config == nil { + return false + } + + return ft.Config.DestinationPointer +} + +func (ft *FlagType) TypeName() string { + return TypeName(ft.GoType, ft.Config) +} + +func (ft *FlagType) GenerateFmtStringerInterface() bool { + return ft.skipInterfaceNamed("fmt.Stringer") +} + +func (ft *FlagType) GenerateFlagInterface() bool { + return ft.skipInterfaceNamed("Flag") +} + +func (ft *FlagType) GenerateRequiredFlagInterface() bool { + return ft.skipInterfaceNamed("RequiredFlag") +} + +func (ft *FlagType) GenerateVisibleFlagInterface() bool { + return ft.skipInterfaceNamed("VisibleFlag") +} + +func (ft *FlagType) skipInterfaceNamed(name string) bool { + if ft.Config == nil { + return true + } + + lowName := strings.ToLower(name) + + for _, interfaceName := range ft.Config.SkipInterfaces { + if strings.ToLower(interfaceName) == lowName { + return false + } + } + + return true +} From a2541e0fe4d67b0112b2bc2d56d9350edd21bfb1 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Tue, 26 Jul 2022 16:16:02 +0200 Subject: [PATCH 14/18] Set destination in GenericFlag apply function The function was missing destination configuration. --- flag_generic.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flag_generic.go b/flag_generic.go index 5034728c42..358bd966e0 100644 --- a/flag_generic.go +++ b/flag_generic.go @@ -62,6 +62,10 @@ func (f *GenericFlag) Apply(set *flag.FlagSet) error { } for _, name := range f.Names() { + if f.Destination != nil { + set.Var(f.Destination, name, f.Usage) + continue + } set.Var(f.Value, name, f.Usage) } From c472192257b94d5418ef7d626c197ac318681e9e Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Tue, 26 Jul 2022 16:16:43 +0200 Subject: [PATCH 15/18] Add unit test for GenericFlag Destination parsing The test checks if Destination provided in GenericFlag is being set as expected. --- flag_test.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/flag_test.go b/flag_test.go index 06f948c86f..3aafa8bea2 100644 --- a/flag_test.go +++ b/flag_test.go @@ -2724,6 +2724,53 @@ func TestParseGeneric(t *testing.T) { }).Run([]string{"run", "-s", "10,20"}) } +type genericType struct { + s []string +} + +func (g *genericType) Set(value string) error { + g.s = strings.Split(value, "-") + return nil +} + +func (g *genericType) String() string { + return strings.Join(g.s, "-") +} + +func TestParseDestinationGeneric(t *testing.T) { + expectedString := "abc1-123d" + expectedGeneric := &genericType{[]string{"abc1", "123d"}} + dest := &genericType{} + + _ = (&App{ + Flags: []Flag{ + &GenericFlag{ + Name: "dest", + Destination: dest, + }, + }, + Action: func(ctx *Context) error { + + if !reflect.DeepEqual(dest, expectedGeneric) { + t.Errorf( + "expected destination generic: %+v, actual: %+v", + expectedGeneric, + dest, + ) + } + + if dest.String() != expectedString { + t.Errorf( + "expected destination string: %s, actual: %s", + expectedString, + dest.String(), + ) + } + return nil + }, + }).Run([]string{"run", "--dest", expectedString}) +} + func TestParseGenericFromEnv(t *testing.T) { defer resetEnv(os.Environ()) os.Clearenv() From d724a6314490fb03989d150b462fcc1cc453d29c Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Wed, 5 Oct 2022 22:10:22 -0400 Subject: [PATCH 16/18] After rebase --- cmd/urfave-cli-genflags/generated.gotmpl | 4 ---- flag-spec.yaml | 27 ------------------------ godoc-current.txt | 26 +++++++++++++++++++++++ internal/genflags/spec.go | 12 +++++------ 4 files changed, 32 insertions(+), 37 deletions(-) diff --git a/cmd/urfave-cli-genflags/generated.gotmpl b/cmd/urfave-cli-genflags/generated.gotmpl index d8c67432ee..91312f8d5a 100644 --- a/cmd/urfave-cli-genflags/generated.gotmpl +++ b/cmd/urfave-cli-genflags/generated.gotmpl @@ -17,11 +17,7 @@ type {{.TypeName}} struct { HasBeenSet bool Value {{if .ValuePointer}}*{{end}}{{.GoType}} -<<<<<<< HEAD:cmd/urfave-cli-genflags/generated.gotmpl Destination {{if .NoDestinationPointer}}{{else}}*{{end}}{{.GoType}} -======= - Destination {{if .DestinationPointer}}*{{end}}{{.GoType}} ->>>>>>> Add DestinationPointer for flags generator:internal/genflags/generated.gotmpl Aliases []string EnvVars []string diff --git a/flag-spec.yaml b/flag-spec.yaml index 9a68cddb8f..76480ba47c 100644 --- a/flag-spec.yaml +++ b/flag-spec.yaml @@ -2,7 +2,6 @@ # ./cmd/urfave-cli-genflags/main.go which uses the # `Spec` type that maps to this file structure. flag_types: -<<<<<<< HEAD bool: struct_fields: - name: Count @@ -14,30 +13,8 @@ flag_types: struct_fields: - name: Action type: "func(*Context, float64) error" -======= - bool: {} - float64: {} - int64: {} - int: {} - time.Duration: {} - uint64: {} - uint: {} - - string: - destination_pointer: true - struct_fields: - - { name: TakesFile, type: bool } - Generic: - struct_fields: - - { name: TakesFile, type: bool } - Path: - destination_pointer: true - struct_fields: - - { name: TakesFile, type: bool } ->>>>>>> Add DestinationPointer for flags generator Float64Slice: value_pointer: true - destination_pointer: true skip_interfaces: - fmt.Stringer struct_fields: @@ -64,7 +41,6 @@ flag_types: type: "func(*Context, int64) error" Int64Slice: value_pointer: true - destination_pointer: true skip_interfaces: - fmt.Stringer struct_fields: @@ -78,7 +54,6 @@ flag_types: type: "func(*Context, uint) error" UintSlice: value_pointer: true - destination_pointer: true skip_interfaces: - fmt.Stringer struct_fields: @@ -105,7 +80,6 @@ flag_types: type: "func(*Context, string) error" StringSlice: value_pointer: true - destination_pointer: true skip_interfaces: - fmt.Stringer struct_fields: @@ -119,7 +93,6 @@ flag_types: type: "func(*Context, time.Duration) error" Timestamp: value_pointer: true - destination_pointer: true struct_fields: - name: Layout type: string diff --git a/godoc-current.txt b/godoc-current.txt index efbac4d1e8..6b3c739746 100644 --- a/godoc-current.txt +++ b/godoc-current.txt @@ -753,6 +753,14 @@ type DocGenerationFlag interface { DocGenerationFlag is an interface that allows documentation generation for the flag +type DocGenerationSliceFlag interface { + DocGenerationFlag + + // IsSliceFlag returns true for flags that can be given multiple times. + IsSliceFlag() bool +} + DocGenerationSliceFlag extends DocGenerationFlag for slice-based flags. + type DurationFlag struct { Name string @@ -1071,6 +1079,9 @@ func (f *Float64SliceFlag) IsRequired() bool func (f *Float64SliceFlag) IsSet() bool IsSet returns whether or not the flag has been set through env or file +func (f *Float64SliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + func (f *Float64SliceFlag) IsVisible() bool IsVisible returns true if the flag is not hidden, otherwise false @@ -1306,6 +1317,9 @@ func (f *Int64SliceFlag) IsRequired() bool func (f *Int64SliceFlag) IsSet() bool IsSet returns whether or not the flag has been set through env or file +func (f *Int64SliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + func (f *Int64SliceFlag) IsVisible() bool IsVisible returns true if the flag is not hidden, otherwise false @@ -1471,6 +1485,9 @@ func (f *IntSliceFlag) IsRequired() bool func (f *IntSliceFlag) IsSet() bool IsSet returns whether or not the flag has been set through env or file +func (f *IntSliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + func (f *IntSliceFlag) IsVisible() bool IsVisible returns true if the flag is not hidden, otherwise false @@ -1810,6 +1827,9 @@ func (f *StringSliceFlag) IsRequired() bool func (f *StringSliceFlag) IsSet() bool IsSet returns whether or not the flag has been set through env or file +func (f *StringSliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + func (f *StringSliceFlag) IsVisible() bool IsVisible returns true if the flag is not hidden, otherwise false @@ -2071,6 +2091,9 @@ func (f *Uint64SliceFlag) IsRequired() bool func (f *Uint64SliceFlag) IsSet() bool IsSet returns whether or not the flag has been set through env or file +func (f *Uint64SliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + func (f *Uint64SliceFlag) IsVisible() bool IsVisible returns true if the flag is not hidden, otherwise false @@ -2227,6 +2250,9 @@ func (f *UintSliceFlag) IsRequired() bool func (f *UintSliceFlag) IsSet() bool IsSet returns whether or not the flag has been set through env or file +func (f *UintSliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + func (f *UintSliceFlag) IsVisible() bool IsVisible returns true if the flag is not hidden, otherwise false diff --git a/internal/genflags/spec.go b/internal/genflags/spec.go index deff8c9307..f30eebc802 100644 --- a/internal/genflags/spec.go +++ b/internal/genflags/spec.go @@ -39,11 +39,11 @@ func (gfs *Spec) SortedFlagTypes() []*FlagType { } type FlagTypeConfig struct { - SkipInterfaces []string `yaml:"skip_interfaces"` - StructFields []*FlagStructField `yaml:"struct_fields"` - TypeName string `yaml:"type_name"` - ValuePointer bool `yaml:"value_pointer"` - DestinationPointer bool `yaml:"destination_pointer"` + SkipInterfaces []string `yaml:"skip_interfaces"` + StructFields []*FlagStructField `yaml:"struct_fields"` + TypeName string `yaml:"type_name"` + ValuePointer bool `yaml:"value_pointer"` + NoDestinationPointer bool `yaml:"no_destination_pointer"` } type FlagStructField struct { @@ -77,7 +77,7 @@ func (ft *FlagType) DestinationPointer() bool { return false } - return ft.Config.DestinationPointer + return ft.Config.NoDestinationPointer } func (ft *FlagType) TypeName() string { From a9c758e55fd045ca0535ce33e4df03703fbc9266 Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Wed, 5 Oct 2022 22:15:43 -0400 Subject: [PATCH 17/18] Fix compile --- internal/genflags/spec.go | 117 -------------------------------------- testdata/godoc-v2.x.txt | 26 +++++++++ 2 files changed, 26 insertions(+), 117 deletions(-) delete mode 100644 internal/genflags/spec.go diff --git a/internal/genflags/spec.go b/internal/genflags/spec.go deleted file mode 100644 index f30eebc802..0000000000 --- a/internal/genflags/spec.go +++ /dev/null @@ -1,117 +0,0 @@ -package genflags - -import ( - "sort" - "strings" -) - -type Spec struct { - FlagTypes map[string]*FlagTypeConfig `yaml:"flag_types"` - PackageName string `yaml:"package_name"` - TestPackageName string `yaml:"test_package_name"` - UrfaveCLINamespace string `yaml:"urfave_cli_namespace"` - UrfaveCLITestNamespace string `yaml:"urfave_cli_test_namespace"` -} - -func (gfs *Spec) SortedFlagTypes() []*FlagType { - typeNames := []string{} - - for name := range gfs.FlagTypes { - if strings.HasPrefix(name, "[]") { - name = strings.TrimPrefix(name, "[]") + "Slice" - } - - typeNames = append(typeNames, name) - } - - sort.Strings(typeNames) - - ret := make([]*FlagType, len(typeNames)) - - for i, typeName := range typeNames { - ret[i] = &FlagType{ - GoType: typeName, - Config: gfs.FlagTypes[typeName], - } - } - - return ret -} - -type FlagTypeConfig struct { - SkipInterfaces []string `yaml:"skip_interfaces"` - StructFields []*FlagStructField `yaml:"struct_fields"` - TypeName string `yaml:"type_name"` - ValuePointer bool `yaml:"value_pointer"` - NoDestinationPointer bool `yaml:"no_destination_pointer"` -} - -type FlagStructField struct { - Name string - Type string -} - -type FlagType struct { - GoType string - Config *FlagTypeConfig -} - -func (ft *FlagType) StructFields() []*FlagStructField { - if ft.Config == nil || ft.Config.StructFields == nil { - return []*FlagStructField{} - } - - return ft.Config.StructFields -} - -func (ft *FlagType) ValuePointer() bool { - if ft.Config == nil { - return false - } - - return ft.Config.ValuePointer -} - -func (ft *FlagType) DestinationPointer() bool { - if ft.Config == nil { - return false - } - - return ft.Config.NoDestinationPointer -} - -func (ft *FlagType) TypeName() string { - return TypeName(ft.GoType, ft.Config) -} - -func (ft *FlagType) GenerateFmtStringerInterface() bool { - return ft.skipInterfaceNamed("fmt.Stringer") -} - -func (ft *FlagType) GenerateFlagInterface() bool { - return ft.skipInterfaceNamed("Flag") -} - -func (ft *FlagType) GenerateRequiredFlagInterface() bool { - return ft.skipInterfaceNamed("RequiredFlag") -} - -func (ft *FlagType) GenerateVisibleFlagInterface() bool { - return ft.skipInterfaceNamed("VisibleFlag") -} - -func (ft *FlagType) skipInterfaceNamed(name string) bool { - if ft.Config == nil { - return true - } - - lowName := strings.ToLower(name) - - for _, interfaceName := range ft.Config.SkipInterfaces { - if strings.ToLower(interfaceName) == lowName { - return false - } - } - - return true -} diff --git a/testdata/godoc-v2.x.txt b/testdata/godoc-v2.x.txt index efbac4d1e8..6b3c739746 100644 --- a/testdata/godoc-v2.x.txt +++ b/testdata/godoc-v2.x.txt @@ -753,6 +753,14 @@ type DocGenerationFlag interface { DocGenerationFlag is an interface that allows documentation generation for the flag +type DocGenerationSliceFlag interface { + DocGenerationFlag + + // IsSliceFlag returns true for flags that can be given multiple times. + IsSliceFlag() bool +} + DocGenerationSliceFlag extends DocGenerationFlag for slice-based flags. + type DurationFlag struct { Name string @@ -1071,6 +1079,9 @@ func (f *Float64SliceFlag) IsRequired() bool func (f *Float64SliceFlag) IsSet() bool IsSet returns whether or not the flag has been set through env or file +func (f *Float64SliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + func (f *Float64SliceFlag) IsVisible() bool IsVisible returns true if the flag is not hidden, otherwise false @@ -1306,6 +1317,9 @@ func (f *Int64SliceFlag) IsRequired() bool func (f *Int64SliceFlag) IsSet() bool IsSet returns whether or not the flag has been set through env or file +func (f *Int64SliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + func (f *Int64SliceFlag) IsVisible() bool IsVisible returns true if the flag is not hidden, otherwise false @@ -1471,6 +1485,9 @@ func (f *IntSliceFlag) IsRequired() bool func (f *IntSliceFlag) IsSet() bool IsSet returns whether or not the flag has been set through env or file +func (f *IntSliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + func (f *IntSliceFlag) IsVisible() bool IsVisible returns true if the flag is not hidden, otherwise false @@ -1810,6 +1827,9 @@ func (f *StringSliceFlag) IsRequired() bool func (f *StringSliceFlag) IsSet() bool IsSet returns whether or not the flag has been set through env or file +func (f *StringSliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + func (f *StringSliceFlag) IsVisible() bool IsVisible returns true if the flag is not hidden, otherwise false @@ -2071,6 +2091,9 @@ func (f *Uint64SliceFlag) IsRequired() bool func (f *Uint64SliceFlag) IsSet() bool IsSet returns whether or not the flag has been set through env or file +func (f *Uint64SliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + func (f *Uint64SliceFlag) IsVisible() bool IsVisible returns true if the flag is not hidden, otherwise false @@ -2227,6 +2250,9 @@ func (f *UintSliceFlag) IsRequired() bool func (f *UintSliceFlag) IsSet() bool IsSet returns whether or not the flag has been set through env or file +func (f *UintSliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + func (f *UintSliceFlag) IsVisible() bool IsVisible returns true if the flag is not hidden, otherwise false From 67f293a1e5388244ce0d7446320d7e54e4e6f839 Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Wed, 5 Oct 2022 22:18:45 -0400 Subject: [PATCH 18/18] Revert main_test --- cmd/urfave-cli-genflags/main_test.go | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/cmd/urfave-cli-genflags/main_test.go b/cmd/urfave-cli-genflags/main_test.go index 61563b1513..b5c9fee8ca 100644 --- a/cmd/urfave-cli-genflags/main_test.go +++ b/cmd/urfave-cli-genflags/main_test.go @@ -80,9 +80,8 @@ func genFlagType() *main.FlagType { Type: "bool", }, }, - TypeName: "YeOldeBlerfFlag", - ValuePointer: true, - DestinationPointer: true, + TypeName: "YeOldeBlerfFlag", + ValuePointer: true, }, } } @@ -116,21 +115,6 @@ func TestFlagType_ValuePointer(t *testing.T) { } } -func TestFlagType_DestinationPointer(t *testing.T) { - ft := genFlagType() - - if !ft.DestinationPointer() { - t.Errorf("expected DestinationPointer to be true") - return - } - - ft.Config = nil - - if ft.DestinationPointer() { - t.Errorf("expected DestinationPointer to be false") - } -} - func TestFlagType_GenerateFmtStringerInterface(t *testing.T) { ft := genFlagType()