From 9d997429ac1c63118908b83fe33c8693abad8779 Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Thu, 20 Oct 2022 20:51:40 -0400 Subject: [PATCH 1/5] Feature:(issue_269) Add compatibility with external package flag definitions --- flag_ext.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 flag_ext.go diff --git a/flag_ext.go b/flag_ext.go new file mode 100644 index 0000000000..00e3bc9e16 --- /dev/null +++ b/flag_ext.go @@ -0,0 +1,48 @@ +package cli + +import "flag" + +type extFlag struct { + f *flag.Flag +} + +func (e extFlag) Apply(fs *flag.FlagSet) error { + fs.Var(e.f.Value, e.f.Name, e.f.Usage) + return nil +} + +func (e extFlag) Names() []string { + return []string{e.f.Name} +} + +func (e extFlag) IsSet() bool { + return false +} + +func (e extFlag) String() string { + return FlagStringer(e) +} + +func (e extFlag) IsVisible() bool { + return true +} + +func (e extFlag) TakesValue() bool { + return false +} + +func (e extFlag) GetUsage() string { + return e.f.Usage +} + +func (e extFlag) GetValue() string { + return e.f.Value.String() +} + +func (e extFlag) GetDefaultText() string { + return e.f.DefValue +} + +func (e extFlag) GetEnvVars() []string { + return nil +} From f909a31ac244322fd099ecca0606a113770a2dbd Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Thu, 20 Oct 2022 20:52:01 -0400 Subject: [PATCH 2/5] Add tests --- app.go | 9 +++++++++ app_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/app.go b/app.go index 24704e8f7b..80a6c80ecf 100644 --- a/app.go +++ b/app.go @@ -8,6 +8,7 @@ import ( "os" "path/filepath" "sort" + "strings" "time" ) @@ -195,6 +196,14 @@ func (a *App) Setup() { a.ErrWriter = os.Stderr } + // add global flags added by other packages + flag.VisitAll(func(f *flag.Flag) { + // skip test flags + if !strings.HasPrefix(f.Name, "test.") { + a.Flags = append(a.Flags, extFlag{f}) + } + }) + var newCommands []*Command for _, c := range a.Commands { diff --git a/app_test.go b/app_test.go index 844aa65441..4504df941e 100644 --- a/app_test.go +++ b/app_test.go @@ -643,6 +643,37 @@ func TestApp_RunDefaultCommandWithFlags(t *testing.T) { } } +func TestApp_FlagsFromExtPackage(t *testing.T) { + + var someint int + flag.IntVar(&someint, "epflag", 2, "ext package flag usage") + + a := &App{ + Flags: []Flag{ + &StringFlag{ + Name: "carly", + Aliases: []string{"c"}, + Required: false, + }, + &BoolFlag{ + Name: "jimbob", + Aliases: []string{"j"}, + Required: false, + Value: true, + }, + }, + } + + err := a.Run([]string{"foo", "-c", "cly", "--epflag", "10"}) + if err != nil { + t.Error(err) + } + + if someint != 10 { + t.Errorf("Expected 10 got %d for someint", someint) + } +} + func TestApp_Setup_defaultsReader(t *testing.T) { app := &App{} app.Setup() From 7793b0a375ae8bfcdeb550edb5ca22995bf2f328 Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Fri, 21 Oct 2022 09:23:42 -0400 Subject: [PATCH 3/5] Add defer to remove global flag --- app_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app_test.go b/app_test.go index 4504df941e..9e8931afaf 100644 --- a/app_test.go +++ b/app_test.go @@ -648,6 +648,11 @@ func TestApp_FlagsFromExtPackage(t *testing.T) { var someint int flag.IntVar(&someint, "epflag", 2, "ext package flag usage") + // Based on source code we can reset the global flag parsing this way + defer func() { + flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError) + }() + a := &App{ Flags: []Flag{ &StringFlag{ From 7554e6b614d777b6aeb143f8116417c14977111d Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Thu, 27 Oct 2022 08:02:09 -0400 Subject: [PATCH 4/5] Use ptr to receiver for extFlag --- app.go | 2 +- flag_ext.go | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app.go b/app.go index 80a6c80ecf..a6e63da3b1 100644 --- a/app.go +++ b/app.go @@ -200,7 +200,7 @@ func (a *App) Setup() { flag.VisitAll(func(f *flag.Flag) { // skip test flags if !strings.HasPrefix(f.Name, "test.") { - a.Flags = append(a.Flags, extFlag{f}) + a.Flags = append(a.Flags, &extFlag{f}) } }) diff --git a/flag_ext.go b/flag_ext.go index 00e3bc9e16..64da59ea93 100644 --- a/flag_ext.go +++ b/flag_ext.go @@ -6,43 +6,43 @@ type extFlag struct { f *flag.Flag } -func (e extFlag) Apply(fs *flag.FlagSet) error { +func (e *extFlag) Apply(fs *flag.FlagSet) error { fs.Var(e.f.Value, e.f.Name, e.f.Usage) return nil } -func (e extFlag) Names() []string { +func (e *extFlag) Names() []string { return []string{e.f.Name} } -func (e extFlag) IsSet() bool { +func (e *extFlag) IsSet() bool { return false } -func (e extFlag) String() string { +func (e *extFlag) String() string { return FlagStringer(e) } -func (e extFlag) IsVisible() bool { +func (e *extFlag) IsVisible() bool { return true } -func (e extFlag) TakesValue() bool { +func (e *extFlag) TakesValue() bool { return false } -func (e extFlag) GetUsage() string { +func (e *extFlag) GetUsage() string { return e.f.Usage } -func (e extFlag) GetValue() string { +func (e *extFlag) GetValue() string { return e.f.Value.String() } -func (e extFlag) GetDefaultText() string { +func (e *extFlag) GetDefaultText() string { return e.f.DefValue } -func (e extFlag) GetEnvVars() []string { +func (e *extFlag) GetEnvVars() []string { return nil } From aa793437aac8138f1c589369dba28b9fa075231b Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Fri, 28 Oct 2022 09:12:17 -0400 Subject: [PATCH 5/5] Add const for flag prefix to ignore --- app.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app.go b/app.go index a6e63da3b1..738199c1ce 100644 --- a/app.go +++ b/app.go @@ -21,6 +21,7 @@ var ( errInvalidActionType = NewExitError("ERROR invalid Action type. "+ fmt.Sprintf("Must be `func(*Context`)` or `func(*Context) error). %s", contactSysadmin)+ fmt.Sprintf("See %s", appActionDeprecationURL), 2) + ignoreFlagPrefix = "test." // this is to ignore test flags when adding flags from other packages SuggestFlag SuggestFlagFunc = suggestFlag SuggestCommand SuggestCommandFunc = suggestCommand @@ -199,7 +200,7 @@ func (a *App) Setup() { // add global flags added by other packages flag.VisitAll(func(f *flag.Flag) { // skip test flags - if !strings.HasPrefix(f.Name, "test.") { + if !strings.HasPrefix(f.Name, ignoreFlagPrefix) { a.Flags = append(a.Flags, &extFlag{f}) } })