From b2edec6e174cb078a13ec6d7c13c91f26c159608 Mon Sep 17 00:00:00 2001 From: Tieg Zaharia Date: Wed, 14 Sep 2022 14:40:32 -0700 Subject: [PATCH 1/5] Fix test output with redundant newlines. This was raising this error, which was added in go 1.10: ./flag_test.go:1242:3: fmt.Println arg list ends with redundant newline --- flag_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/flag_test.go b/flag_test.go index 58a5d25a..721bc312 100644 --- a/flag_test.go +++ b/flag_test.go @@ -1134,7 +1134,6 @@ func TestMultipleNormalizeFlagNameInvocations(t *testing.T) { } } -// func TestHiddenFlagInUsage(t *testing.T) { f := NewFlagSet("bob", ContinueOnError) f.Bool("secretFlag", true, "shhh") @@ -1149,7 +1148,6 @@ func TestHiddenFlagInUsage(t *testing.T) { } } -// func TestHiddenFlagUsage(t *testing.T) { f := NewFlagSet("bob", ContinueOnError) f.Bool("secretFlag", true, "shhh") @@ -1238,8 +1236,8 @@ func TestPrintDefaults(t *testing.T) { fs.PrintDefaults() got := buf.String() if got != defaultOutput { - fmt.Println("\n" + got) - fmt.Println("\n" + defaultOutput) + fmt.Print("\n" + got) + fmt.Print("\n" + defaultOutput) t.Errorf("got %q want %q\n", got, defaultOutput) } } From baa6eb916f40f222ed5b4e8d03861b1382c713b8 Mon Sep 17 00:00:00 2001 From: Tieg Zaharia Date: Wed, 14 Sep 2022 15:11:02 -0700 Subject: [PATCH 2/5] Add a test for AddFlag() --- flag_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/flag_test.go b/flag_test.go index 721bc312..4bc21593 100644 --- a/flag_test.go +++ b/flag_test.go @@ -128,6 +128,20 @@ func TestAddFlagSet(t *testing.T) { } } +func TestAddFlag(t *testing.T) { + flagSet := NewFlagSet("adding-flags", ContinueOnError) + flag := &Flag{ + Name: "a-flag", + Shorthand: "a", + Usage: "the usage", + } + flagSet.AddFlag(flag) + + if len(flagSet.formal) != 1 { + t.Errorf("Unexpected result adding a Flag to a FlagSet %v", flagSet) + } +} + func TestAnnotation(t *testing.T) { f := NewFlagSet("shorthand", ContinueOnError) From 243a5cad19e11efa2373b8ea909e1539c339ca15 Mon Sep 17 00:00:00 2001 From: Tieg Zaharia Date: Thu, 15 Sep 2022 16:45:36 -0700 Subject: [PATCH 3/5] Add a helpful comment to actual+formal fields. --- flag.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flag.go b/flag.go index 7c058de3..35bb692e 100644 --- a/flag.go +++ b/flag.go @@ -150,10 +150,10 @@ type FlagSet struct { name string parsed bool - actual map[NormalizedName]*Flag + actual map[NormalizedName]*Flag // the flags after parsing orderedActual []*Flag sortedActual []*Flag - formal map[NormalizedName]*Flag + formal map[NormalizedName]*Flag // the flags before parsing orderedFormal []*Flag sortedFormal []*Flag shorthands map[byte]*Flag From 023c13117497b06eaf66262c8d3f49367fe9aa9c Mon Sep 17 00:00:00 2001 From: Tieg Zaharia Date: Thu, 15 Sep 2022 16:46:02 -0700 Subject: [PATCH 4/5] Add pflag.RemoveFlag() method, with a test. --- flag.go | 9 +++++++++ flag_test.go | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/flag.go b/flag.go index 35bb692e..5f8ea955 100644 --- a/flag.go +++ b/flag.go @@ -844,6 +844,15 @@ func (f *FlagSet) VarP(value Value, name, shorthand, usage string) { f.VarPF(value, name, shorthand, usage) } +// RemoveFlag will remove the flag from the FlagSet +func (f *FlagSet) RemoveFlag(name string) { + normalizedFlagName := f.normalizeFlagName(name) + _, exists := f.formal[normalizedFlagName] + if exists { + delete(f.formal, normalizedFlagName) + } +} + // AddFlag will add the flag to the FlagSet func (f *FlagSet) AddFlag(flag *Flag) { normalizedFlagName := f.normalizeFlagName(flag.Name) diff --git a/flag_test.go b/flag_test.go index 4bc21593..2476c7d5 100644 --- a/flag_test.go +++ b/flag_test.go @@ -142,6 +142,23 @@ func TestAddFlag(t *testing.T) { } } +func TestRemoveFlag(t *testing.T) { + flagSet := NewFlagSet("removing-flags", ContinueOnError) + flagSet.String("string1", "a", "enter a string1") + flagSet.String("string2", "b", "enter a string2") + + flagSet.RemoveFlag("string1") + + if len(flagSet.formal) != 1 { + t.Errorf("Flagset %v should only have 1 formal flag now, but has %d.", flagSet, len(flagSet.formal)) + } + flagSet.VisitAll(func(f *Flag) { + if f.Name == "string1" { + t.Errorf("Flag string1 was not removed from %v formal flags.", flagSet) + } + }) +} + func TestAnnotation(t *testing.T) { f := NewFlagSet("shorthand", ContinueOnError) From 87758c1f3698998724c4732009362f43cc5bd874 Mon Sep 17 00:00:00 2001 From: Tieg Zaharia Date: Thu, 15 Sep 2022 16:46:36 -0700 Subject: [PATCH 5/5] Formatting --- flag.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/flag.go b/flag.go index 5f8ea955..7381c722 100644 --- a/flag.go +++ b/flag.go @@ -27,23 +27,32 @@ unaffected. Define flags using flag.String(), Bool(), Int(), etc. This declares an integer flag, -flagname, stored in the pointer ip, with type *int. + var ip = flag.Int("flagname", 1234, "help message for flagname") + If you like, you can bind the flag to a variable using the Var() functions. + var flagvar int func init() { flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname") } + Or you can create custom flags that satisfy the Value interface (with pointer receivers) and couple them to flag parsing by + flag.Var(&flagVal, "name", "help message for flagname") + For such flags, the default value is just the initial value of the variable. After all flags are defined, call + flag.Parse() + to parse the command line into the defined flags. Flags may then be used directly. If you're using the flags themselves, they are all pointers; if you bind to variables, they're values. + fmt.Println("ip has value ", *ip) fmt.Println("flagvar has value ", flagvar) @@ -54,22 +63,26 @@ The arguments are indexed from 0 through flag.NArg()-1. The pflag package also defines some new functions that are not in flag, that give one-letter shorthands for flags. You can use these by appending 'P' to the name of any function that defines a flag. + var ip = flag.IntP("flagname", "f", 1234, "help message") var flagvar bool func init() { flag.BoolVarP(&flagvar, "boolname", "b", true, "help message") } flag.VarP(&flagval, "varname", "v", "help message") + Shorthand letters can be used with single dashes on the command line. Boolean shorthand flags can be combined with other shorthand flags. Command line flag syntax: + --flag // boolean flags only --flag=x Unlike the flag package, a single dash before an option means something different than a double dash. Single dashes signify a series of shorthand letters for flags. All but the last shorthand letter must be boolean flags. + // boolean flags -f -abc @@ -943,9 +956,9 @@ func (f *FlagSet) usage() { } } -//--unknown (args will be empty) -//--unknown --next-flag ... (args will be --next-flag ...) -//--unknown arg ... (args will be arg ...) +// --unknown (args will be empty) +// --unknown --next-flag ... (args will be --next-flag ...) +// --unknown arg ... (args will be arg ...) func stripUnknownFlagValue(args []string) []string { if len(args) == 0 { //--unknown