From 034f0ed17f2a6e1d5cc7f5d01408978ccb59461c Mon Sep 17 00:00:00 2001 From: Alec Bakholdin Date: Thu, 30 Jun 2022 17:24:50 -0400 Subject: [PATCH 01/14] added noDefault flag to arg type and set it to true in the Flag() function --- argparse.go | 13 +++++++------ argument.go | 28 ++++++++++++++++------------ 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/argparse.go b/argparse.go index 1ecac29..6966473 100644 --- a/argparse.go +++ b/argparse.go @@ -191,12 +191,13 @@ func (o *Command) Flag(short string, long string, opts *Options) *bool { var result bool a := &arg{ - result: &result, - sname: short, - lname: long, - size: 1, - opts: opts, - unique: true, + result: &result, + sname: short, + lname: long, + size: 1, + opts: opts, + unique: true, + noDefault: true, } if err := o.addArg(a); err != nil { diff --git a/argument.go b/argument.go index 3bd7a74..d1ba99d 100644 --- a/argument.go +++ b/argument.go @@ -9,18 +9,19 @@ import ( ) type arg struct { - result interface{} // Pointer to the resulting value - opts *Options // Options - sname string // Short name (in Parser will start with "-" - lname string // Long name (in Parser will start with "--" - size int // Size defines how many args after match will need to be consumed - unique bool // Specifies whether flag should be present only ones - parsed bool // Specifies whether flag has been parsed already - fileFlag int // File mode to open file with - filePerm os.FileMode // File permissions to set a file - selector *[]string // Used in Selector type to allow to choose only one from list of options - parent *Command // Used to get access to specific Command - eqChar bool // This is used if the command is passed in with an equals char as a seperator + result interface{} // Pointer to the resulting value + opts *Options // Options + sname string // Short name (in Parser will start with "-" + lname string // Long name (in Parser will start with "--" + size int // Size defines how many args after match will need to be consumed + unique bool // Specifies whether flag should be present only ones + parsed bool // Specifies whether flag has been parsed already + fileFlag int // File mode to open file with + filePerm os.FileMode // File permissions to set a file + selector *[]string // Used in Selector type to allow to choose only one from list of options + parent *Command // Used to get access to specific Command + eqChar bool // This is used if the command is passed in with an equals char as a seperator + noDefault bool // This is used if Default in argparse.Options should not be allowed } // Arg interface provides exporting of arg structure, while exposing it @@ -501,6 +502,9 @@ func (o *arg) setDefaultFiles() error { func (o *arg) setDefault() error { // Only set default if it was not parsed, and default value was defined if !o.parsed && o.opts != nil && o.opts.Default != nil { + if o.noDefault { + return fmt.Errorf("argument [%s, %s] does not support default values", o.sname, o.lname) + } switch o.result.(type) { case *bool, *int, *float64, *string, *[]bool, *[]int, *[]float64, *[]string: if reflect.TypeOf(o.result) != reflect.PtrTo(reflect.TypeOf(o.opts.Default)) { From 61a24362a9592ad65b043fbd3863a85855f988e1 Mon Sep 17 00:00:00 2001 From: Alec Bakholdin Date: Thu, 30 Jun 2022 17:43:30 -0400 Subject: [PATCH 02/14] added test for ignoring default and deleted tests that tested functionality of defaults for flags --- argparse_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/argparse_test.go b/argparse_test.go index b247044..a43f77e 100644 --- a/argparse_test.go +++ b/argparse_test.go @@ -2042,12 +2042,12 @@ func TestStringDefaultValueFail(t *testing.T) { p := NewParser("progname", "Prog description") - _ = p.String("s", "string", &Options{Default: false}) + _ = p.String("s", "string", &Options{Default: true}) err := p.Parse(testArgs) // Should pass on failure - if err == nil || err.Error() != "cannot use default type [bool] as value of pointer with type [*string]" { + if err == nil || err.Error() != "argument [s, string] does not support default values" { t.Errorf("Test %s failed: expected error [%s], got error [%+v]", t.Name(), "cannot use default type [bool] as value of pointer with type [*string]", err) } } From dcce8cc1c1a1021118350dcf02035322f7ff2336 Mon Sep 17 00:00:00 2001 From: Alec Bakholdin Date: Thu, 30 Jun 2022 22:37:27 -0400 Subject: [PATCH 03/14] realized I modified the wrong test in the previous commit --- argparse_test.go | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/argparse_test.go b/argparse_test.go index a43f77e..88b039c 100644 --- a/argparse_test.go +++ b/argparse_test.go @@ -1981,38 +1981,18 @@ func TestIntMissingArgFail(t *testing.T) { } } -func TestFlagDefaultValuePass(t *testing.T) { - testArgs := []string{"progname"} - - p := NewParser("progname", "Prog description") - - f := p.Flag("f", "flag", &Options{Default: true}) - - err := p.Parse(testArgs) - - // Should fail on failure - if err != nil { - t.Error(err.Error()) - } - - // Should fail if not true - if *f != true { - t.Errorf("expected [true], got [%t]", *f) - } -} - func TestFlagDefaultValueFail(t *testing.T) { testArgs := []string{"progname"} p := NewParser("progname", "Prog description") - _ = p.Flag("f", "flag", &Options{Default: "string"}) + _ = p.Flag("f", "flag", &Options{Default: true}) err := p.Parse(testArgs) // Should pass on failure - if err == nil || err.Error() != "cannot use default type [string] as value of pointer with type [*bool]" { - t.Errorf("Test %s failed: expected error [%s], got error [%+v]", t.Name(), "cannot use default type [string] as value of pointer with type [*bool]", err) + if err == nil || err.Error() != "argument [f, flag] does not support default values" { + t.Errorf("Test %s failed: expected error [%s], got error [%+v]", t.Name(), "argument [f, flag] does not support default values", err) } } @@ -2047,7 +2027,7 @@ func TestStringDefaultValueFail(t *testing.T) { err := p.Parse(testArgs) // Should pass on failure - if err == nil || err.Error() != "argument [s, string] does not support default values" { + if err == nil || err.Error() != "cannot use default type [bool] as value of pointer with type [*string]" { t.Errorf("Test %s failed: expected error [%s], got error [%+v]", t.Name(), "cannot use default type [bool] as value of pointer with type [*string]", err) } } From 4f4a98a9eb675da51b1f13b9f9c6588eba83d369 Mon Sep 17 00:00:00 2001 From: Alec Bakholdin Date: Fri, 1 Jul 2022 02:01:17 -0400 Subject: [PATCH 04/14] added argType to arg --- argparse.go | 108 ++++++++++++++++++++++++++++------------------------ argument.go | 44 ++++++++++++++------- 2 files changed, 90 insertions(+), 62 deletions(-) diff --git a/argparse.go b/argparse.go index 6966473..d035ca4 100644 --- a/argparse.go +++ b/argparse.go @@ -191,13 +191,13 @@ func (o *Command) Flag(short string, long string, opts *Options) *bool { var result bool a := &arg{ - result: &result, - sname: short, - lname: long, - size: 1, - opts: opts, - unique: true, - noDefault: true, + result: &result, + sname: short, + lname: long, + size: 1, + opts: opts, + unique: true, + argType: Flag, } if err := o.addArg(a); err != nil { @@ -218,12 +218,13 @@ func (o *Command) FlagCounter(short string, long string, opts *Options) *int { var result int a := &arg{ - result: &result, - sname: short, - lname: long, - size: 1, - opts: opts, - unique: false, + result: &result, + sname: short, + lname: long, + size: 1, + opts: opts, + unique: false, + argType: FlagCounter, } if err := o.addArg(a); err != nil { @@ -240,12 +241,13 @@ func (o *Command) String(short string, long string, opts *Options) *string { var result string a := &arg{ - result: &result, - sname: short, - lname: long, - size: 2, - opts: opts, - unique: true, + result: &result, + sname: short, + lname: long, + size: 2, + opts: opts, + unique: true, + argType: String, } if err := o.addArg(a); err != nil { @@ -263,12 +265,13 @@ func (o *Command) Int(short string, long string, opts *Options) *int { var result int a := &arg{ - result: &result, - sname: short, - lname: long, - size: 2, - opts: opts, - unique: true, + result: &result, + sname: short, + lname: long, + size: 2, + opts: opts, + unique: true, + argType: Int, } if err := o.addArg(a); err != nil { @@ -286,12 +289,13 @@ func (o *Command) Float(short string, long string, opts *Options) *float64 { var result float64 a := &arg{ - result: &result, - sname: short, - lname: long, - size: 2, - opts: opts, - unique: true, + result: &result, + sname: short, + lname: long, + size: 2, + opts: opts, + unique: true, + argType: Float, } if err := o.addArg(a); err != nil { @@ -320,6 +324,7 @@ func (o *Command) File(short string, long string, flag int, perm os.FileMode, op unique: true, fileFlag: flag, filePerm: perm, + argType: File, } if err := o.addArg(a); err != nil { @@ -346,12 +351,13 @@ func (o *Command) StringList(short string, long string, opts *Options) *[]string result := make([]string, 0) a := &arg{ - result: &result, - sname: short, - lname: long, - size: 2, - opts: opts, - unique: false, + result: &result, + sname: short, + lname: long, + size: 2, + opts: opts, + unique: false, + argType: StringList, } if err := o.addArg(a); err != nil { @@ -369,12 +375,13 @@ func (o *Command) IntList(short string, long string, opts *Options) *[]int { result := make([]int, 0) a := &arg{ - result: &result, - sname: short, - lname: long, - size: 2, - opts: opts, - unique: false, + result: &result, + sname: short, + lname: long, + size: 2, + opts: opts, + unique: false, + argType: IntList, } if err := o.addArg(a); err != nil { @@ -392,12 +399,13 @@ func (o *Command) FloatList(short string, long string, opts *Options) *[]float64 result := make([]float64, 0) a := &arg{ - result: &result, - sname: short, - lname: long, - size: 2, - opts: opts, - unique: false, + result: &result, + sname: short, + lname: long, + size: 2, + opts: opts, + unique: false, + argType: FloatList, } if err := o.addArg(a); err != nil { @@ -423,6 +431,7 @@ func (o *Command) FileList(short string, long string, flag int, perm os.FileMode unique: false, fileFlag: flag, filePerm: perm, + argType: FileList, } if err := o.addArg(a); err != nil { @@ -449,6 +458,7 @@ func (o *Command) Selector(short string, long string, options []string, opts *Op opts: opts, unique: true, selector: &options, + argType: Selector, } if err := o.addArg(a); err != nil { diff --git a/argument.go b/argument.go index d1ba99d..dc71c2c 100644 --- a/argument.go +++ b/argument.go @@ -9,21 +9,39 @@ import ( ) type arg struct { - result interface{} // Pointer to the resulting value - opts *Options // Options - sname string // Short name (in Parser will start with "-" - lname string // Long name (in Parser will start with "--" - size int // Size defines how many args after match will need to be consumed - unique bool // Specifies whether flag should be present only ones - parsed bool // Specifies whether flag has been parsed already - fileFlag int // File mode to open file with - filePerm os.FileMode // File permissions to set a file - selector *[]string // Used in Selector type to allow to choose only one from list of options - parent *Command // Used to get access to specific Command - eqChar bool // This is used if the command is passed in with an equals char as a seperator - noDefault bool // This is used if Default in argparse.Options should not be allowed + result interface{} // Pointer to the resulting value + opts *Options // Options + sname string // Short name (in Parser will start with "-" + lname string // Long name (in Parser will start with "--" + size int // Size defines how many args after match will need to be consumed + unique bool // Specifies whether flag should be present only ones + parsed bool // Specifies whether flag has been parsed already + fileFlag int // File mode to open file with + filePerm os.FileMode // File permissions to set a file + selector *[]string // Used in Selector type to allow to choose only one from list of options + parent *Command // Used to get access to specific Command + eqChar bool // This is used if the command is passed in with an equals char as a seperator + noDefault bool // This is used if Default in argparse.Options should not be allowed + argType ArgumentType // Used to determine which argument type this is } +// enum used to determine the argument type +type ArgumentType int + +const ( + Flag ArgumentType = 0 + FlagCounter = 1 + String = 2 + Int = 3 + Float = 4 + File = 5 + StringList = 6 + IntList = 7 + FloatList = 8 + FileList = 9 + Selector = 10 +) + // Arg interface provides exporting of arg structure, while exposing it type Arg interface { GetOpts() *Options From 337f81127abc6d345744dfd6acf67016fc8e45d4 Mon Sep 17 00:00:00 2001 From: Alec Bakholdin Date: Fri, 1 Jul 2022 02:01:48 -0400 Subject: [PATCH 05/14] flags now ignore a default value of true --- argparse_test.go | 35 ++++++++++++++++++++++++++++++----- argument.go | 6 +++++- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/argparse_test.go b/argparse_test.go index 88b039c..138517a 100644 --- a/argparse_test.go +++ b/argparse_test.go @@ -1981,18 +1981,43 @@ func TestIntMissingArgFail(t *testing.T) { } } -func TestFlagDefaultValueFail(t *testing.T) { +func TestFlagDefaultValuePass(t *testing.T) { testArgs := []string{"progname"} p := NewParser("progname", "Prog description") - _ = p.Flag("f", "flag", &Options{Default: true}) + f := p.Flag("f", "flag", &Options{Default: false}) err := p.Parse(testArgs) - // Should pass on failure - if err == nil || err.Error() != "argument [f, flag] does not support default values" { - t.Errorf("Test %s failed: expected error [%s], got error [%+v]", t.Name(), "argument [f, flag] does not support default values", err) + // Should fail on failure + if err != nil { + t.Error(err.Error()) + } + + // Should fail if not false + if *f != false { + t.Errorf("expected [false] but found [%t]", *f) + } +} + +func TestFlagDefaultValueShouldIgnoreTrue(t *testing.T) { + testArgs := []string{"progname"} + + p := NewParser("progname", "Prog description") + + f := p.Flag("f", "flag", &Options{Default: true}) + + err := p.Parse(testArgs) + + // Should fail on failure + if err != nil { + t.Error(err.Error()) + } + + // Should fail if not false + if *f != false { + t.Errorf("expected [false] but found [%t]", *f) } } diff --git a/argument.go b/argument.go index dc71c2c..989a634 100644 --- a/argument.go +++ b/argument.go @@ -528,7 +528,11 @@ func (o *arg) setDefault() error { if reflect.TypeOf(o.result) != reflect.PtrTo(reflect.TypeOf(o.opts.Default)) { return fmt.Errorf("cannot use default type [%T] as value of pointer with type [%T]", o.opts.Default, o.result) } - reflect.ValueOf(o.result).Elem().Set(reflect.ValueOf(o.opts.Default)) + defaultValue := o.opts.Default + if o.argType == Flag && defaultValue == true { + defaultValue = false + } + reflect.ValueOf(o.result).Elem().Set(reflect.ValueOf(defaultValue)) case *os.File: if err := o.setDefaultFile(); err != nil { From ea25525804913d7aa9b3cbeda73988c4bc8fc3c6 Mon Sep 17 00:00:00 2001 From: Alec Bakholdin Date: Fri, 1 Jul 2022 02:03:44 -0400 Subject: [PATCH 06/14] removed noDefault --- argument.go | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/argument.go b/argument.go index 989a634..2688839 100644 --- a/argument.go +++ b/argument.go @@ -9,20 +9,19 @@ import ( ) type arg struct { - result interface{} // Pointer to the resulting value - opts *Options // Options - sname string // Short name (in Parser will start with "-" - lname string // Long name (in Parser will start with "--" - size int // Size defines how many args after match will need to be consumed - unique bool // Specifies whether flag should be present only ones - parsed bool // Specifies whether flag has been parsed already - fileFlag int // File mode to open file with - filePerm os.FileMode // File permissions to set a file - selector *[]string // Used in Selector type to allow to choose only one from list of options - parent *Command // Used to get access to specific Command - eqChar bool // This is used if the command is passed in with an equals char as a seperator - noDefault bool // This is used if Default in argparse.Options should not be allowed - argType ArgumentType // Used to determine which argument type this is + result interface{} // Pointer to the resulting value + opts *Options // Options + sname string // Short name (in Parser will start with "-" + lname string // Long name (in Parser will start with "--" + size int // Size defines how many args after match will need to be consumed + unique bool // Specifies whether flag should be present only ones + parsed bool // Specifies whether flag has been parsed already + fileFlag int // File mode to open file with + filePerm os.FileMode // File permissions to set a file + selector *[]string // Used in Selector type to allow to choose only one from list of options + parent *Command // Used to get access to specific Command + eqChar bool // This is used if the command is passed in with an equals char as a seperator + argType ArgumentType // Used to determine which argument type this is } // enum used to determine the argument type @@ -520,9 +519,6 @@ func (o *arg) setDefaultFiles() error { func (o *arg) setDefault() error { // Only set default if it was not parsed, and default value was defined if !o.parsed && o.opts != nil && o.opts.Default != nil { - if o.noDefault { - return fmt.Errorf("argument [%s, %s] does not support default values", o.sname, o.lname) - } switch o.result.(type) { case *bool, *int, *float64, *string, *[]bool, *[]int, *[]float64, *[]string: if reflect.TypeOf(o.result) != reflect.PtrTo(reflect.TypeOf(o.opts.Default)) { From 3cc99568e8bc9eb12b9e02f5e291e4b5758b5b62 Mon Sep 17 00:00:00 2001 From: Alec Bakholdin Date: Thu, 30 Jun 2022 17:24:50 -0400 Subject: [PATCH 07/14] added noDefault flag to arg type and set it to true in the Flag() function --- argparse.go | 13 +++++++------ argument.go | 28 ++++++++++++++++------------ 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/argparse.go b/argparse.go index 1ecac29..6966473 100644 --- a/argparse.go +++ b/argparse.go @@ -191,12 +191,13 @@ func (o *Command) Flag(short string, long string, opts *Options) *bool { var result bool a := &arg{ - result: &result, - sname: short, - lname: long, - size: 1, - opts: opts, - unique: true, + result: &result, + sname: short, + lname: long, + size: 1, + opts: opts, + unique: true, + noDefault: true, } if err := o.addArg(a); err != nil { diff --git a/argument.go b/argument.go index 3bd7a74..d1ba99d 100644 --- a/argument.go +++ b/argument.go @@ -9,18 +9,19 @@ import ( ) type arg struct { - result interface{} // Pointer to the resulting value - opts *Options // Options - sname string // Short name (in Parser will start with "-" - lname string // Long name (in Parser will start with "--" - size int // Size defines how many args after match will need to be consumed - unique bool // Specifies whether flag should be present only ones - parsed bool // Specifies whether flag has been parsed already - fileFlag int // File mode to open file with - filePerm os.FileMode // File permissions to set a file - selector *[]string // Used in Selector type to allow to choose only one from list of options - parent *Command // Used to get access to specific Command - eqChar bool // This is used if the command is passed in with an equals char as a seperator + result interface{} // Pointer to the resulting value + opts *Options // Options + sname string // Short name (in Parser will start with "-" + lname string // Long name (in Parser will start with "--" + size int // Size defines how many args after match will need to be consumed + unique bool // Specifies whether flag should be present only ones + parsed bool // Specifies whether flag has been parsed already + fileFlag int // File mode to open file with + filePerm os.FileMode // File permissions to set a file + selector *[]string // Used in Selector type to allow to choose only one from list of options + parent *Command // Used to get access to specific Command + eqChar bool // This is used if the command is passed in with an equals char as a seperator + noDefault bool // This is used if Default in argparse.Options should not be allowed } // Arg interface provides exporting of arg structure, while exposing it @@ -501,6 +502,9 @@ func (o *arg) setDefaultFiles() error { func (o *arg) setDefault() error { // Only set default if it was not parsed, and default value was defined if !o.parsed && o.opts != nil && o.opts.Default != nil { + if o.noDefault { + return fmt.Errorf("argument [%s, %s] does not support default values", o.sname, o.lname) + } switch o.result.(type) { case *bool, *int, *float64, *string, *[]bool, *[]int, *[]float64, *[]string: if reflect.TypeOf(o.result) != reflect.PtrTo(reflect.TypeOf(o.opts.Default)) { From 4be4a3f440ec07fa62fa8402ba538667825bc96f Mon Sep 17 00:00:00 2001 From: Alec Bakholdin Date: Thu, 30 Jun 2022 17:43:30 -0400 Subject: [PATCH 08/14] added test for ignoring default and deleted tests that tested functionality of defaults for flags --- argparse_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/argparse_test.go b/argparse_test.go index b247044..a43f77e 100644 --- a/argparse_test.go +++ b/argparse_test.go @@ -2042,12 +2042,12 @@ func TestStringDefaultValueFail(t *testing.T) { p := NewParser("progname", "Prog description") - _ = p.String("s", "string", &Options{Default: false}) + _ = p.String("s", "string", &Options{Default: true}) err := p.Parse(testArgs) // Should pass on failure - if err == nil || err.Error() != "cannot use default type [bool] as value of pointer with type [*string]" { + if err == nil || err.Error() != "argument [s, string] does not support default values" { t.Errorf("Test %s failed: expected error [%s], got error [%+v]", t.Name(), "cannot use default type [bool] as value of pointer with type [*string]", err) } } From d8271853e543b6e2bb6475545a7bf987a20717fc Mon Sep 17 00:00:00 2001 From: Alec Bakholdin Date: Thu, 30 Jun 2022 22:37:27 -0400 Subject: [PATCH 09/14] realized I modified the wrong test in the previous commit --- argparse_test.go | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/argparse_test.go b/argparse_test.go index a43f77e..88b039c 100644 --- a/argparse_test.go +++ b/argparse_test.go @@ -1981,38 +1981,18 @@ func TestIntMissingArgFail(t *testing.T) { } } -func TestFlagDefaultValuePass(t *testing.T) { - testArgs := []string{"progname"} - - p := NewParser("progname", "Prog description") - - f := p.Flag("f", "flag", &Options{Default: true}) - - err := p.Parse(testArgs) - - // Should fail on failure - if err != nil { - t.Error(err.Error()) - } - - // Should fail if not true - if *f != true { - t.Errorf("expected [true], got [%t]", *f) - } -} - func TestFlagDefaultValueFail(t *testing.T) { testArgs := []string{"progname"} p := NewParser("progname", "Prog description") - _ = p.Flag("f", "flag", &Options{Default: "string"}) + _ = p.Flag("f", "flag", &Options{Default: true}) err := p.Parse(testArgs) // Should pass on failure - if err == nil || err.Error() != "cannot use default type [string] as value of pointer with type [*bool]" { - t.Errorf("Test %s failed: expected error [%s], got error [%+v]", t.Name(), "cannot use default type [string] as value of pointer with type [*bool]", err) + if err == nil || err.Error() != "argument [f, flag] does not support default values" { + t.Errorf("Test %s failed: expected error [%s], got error [%+v]", t.Name(), "argument [f, flag] does not support default values", err) } } @@ -2047,7 +2027,7 @@ func TestStringDefaultValueFail(t *testing.T) { err := p.Parse(testArgs) // Should pass on failure - if err == nil || err.Error() != "argument [s, string] does not support default values" { + if err == nil || err.Error() != "cannot use default type [bool] as value of pointer with type [*string]" { t.Errorf("Test %s failed: expected error [%s], got error [%+v]", t.Name(), "cannot use default type [bool] as value of pointer with type [*string]", err) } } From 78db033892ac0885befe8d681da5895587dee82c Mon Sep 17 00:00:00 2001 From: Alec Bakholdin Date: Fri, 1 Jul 2022 02:01:17 -0400 Subject: [PATCH 10/14] added argType to arg --- argparse.go | 108 ++++++++++++++++++++++++++++------------------------ argument.go | 44 ++++++++++++++------- 2 files changed, 90 insertions(+), 62 deletions(-) diff --git a/argparse.go b/argparse.go index 6966473..d035ca4 100644 --- a/argparse.go +++ b/argparse.go @@ -191,13 +191,13 @@ func (o *Command) Flag(short string, long string, opts *Options) *bool { var result bool a := &arg{ - result: &result, - sname: short, - lname: long, - size: 1, - opts: opts, - unique: true, - noDefault: true, + result: &result, + sname: short, + lname: long, + size: 1, + opts: opts, + unique: true, + argType: Flag, } if err := o.addArg(a); err != nil { @@ -218,12 +218,13 @@ func (o *Command) FlagCounter(short string, long string, opts *Options) *int { var result int a := &arg{ - result: &result, - sname: short, - lname: long, - size: 1, - opts: opts, - unique: false, + result: &result, + sname: short, + lname: long, + size: 1, + opts: opts, + unique: false, + argType: FlagCounter, } if err := o.addArg(a); err != nil { @@ -240,12 +241,13 @@ func (o *Command) String(short string, long string, opts *Options) *string { var result string a := &arg{ - result: &result, - sname: short, - lname: long, - size: 2, - opts: opts, - unique: true, + result: &result, + sname: short, + lname: long, + size: 2, + opts: opts, + unique: true, + argType: String, } if err := o.addArg(a); err != nil { @@ -263,12 +265,13 @@ func (o *Command) Int(short string, long string, opts *Options) *int { var result int a := &arg{ - result: &result, - sname: short, - lname: long, - size: 2, - opts: opts, - unique: true, + result: &result, + sname: short, + lname: long, + size: 2, + opts: opts, + unique: true, + argType: Int, } if err := o.addArg(a); err != nil { @@ -286,12 +289,13 @@ func (o *Command) Float(short string, long string, opts *Options) *float64 { var result float64 a := &arg{ - result: &result, - sname: short, - lname: long, - size: 2, - opts: opts, - unique: true, + result: &result, + sname: short, + lname: long, + size: 2, + opts: opts, + unique: true, + argType: Float, } if err := o.addArg(a); err != nil { @@ -320,6 +324,7 @@ func (o *Command) File(short string, long string, flag int, perm os.FileMode, op unique: true, fileFlag: flag, filePerm: perm, + argType: File, } if err := o.addArg(a); err != nil { @@ -346,12 +351,13 @@ func (o *Command) StringList(short string, long string, opts *Options) *[]string result := make([]string, 0) a := &arg{ - result: &result, - sname: short, - lname: long, - size: 2, - opts: opts, - unique: false, + result: &result, + sname: short, + lname: long, + size: 2, + opts: opts, + unique: false, + argType: StringList, } if err := o.addArg(a); err != nil { @@ -369,12 +375,13 @@ func (o *Command) IntList(short string, long string, opts *Options) *[]int { result := make([]int, 0) a := &arg{ - result: &result, - sname: short, - lname: long, - size: 2, - opts: opts, - unique: false, + result: &result, + sname: short, + lname: long, + size: 2, + opts: opts, + unique: false, + argType: IntList, } if err := o.addArg(a); err != nil { @@ -392,12 +399,13 @@ func (o *Command) FloatList(short string, long string, opts *Options) *[]float64 result := make([]float64, 0) a := &arg{ - result: &result, - sname: short, - lname: long, - size: 2, - opts: opts, - unique: false, + result: &result, + sname: short, + lname: long, + size: 2, + opts: opts, + unique: false, + argType: FloatList, } if err := o.addArg(a); err != nil { @@ -423,6 +431,7 @@ func (o *Command) FileList(short string, long string, flag int, perm os.FileMode unique: false, fileFlag: flag, filePerm: perm, + argType: FileList, } if err := o.addArg(a); err != nil { @@ -449,6 +458,7 @@ func (o *Command) Selector(short string, long string, options []string, opts *Op opts: opts, unique: true, selector: &options, + argType: Selector, } if err := o.addArg(a); err != nil { diff --git a/argument.go b/argument.go index d1ba99d..dc71c2c 100644 --- a/argument.go +++ b/argument.go @@ -9,21 +9,39 @@ import ( ) type arg struct { - result interface{} // Pointer to the resulting value - opts *Options // Options - sname string // Short name (in Parser will start with "-" - lname string // Long name (in Parser will start with "--" - size int // Size defines how many args after match will need to be consumed - unique bool // Specifies whether flag should be present only ones - parsed bool // Specifies whether flag has been parsed already - fileFlag int // File mode to open file with - filePerm os.FileMode // File permissions to set a file - selector *[]string // Used in Selector type to allow to choose only one from list of options - parent *Command // Used to get access to specific Command - eqChar bool // This is used if the command is passed in with an equals char as a seperator - noDefault bool // This is used if Default in argparse.Options should not be allowed + result interface{} // Pointer to the resulting value + opts *Options // Options + sname string // Short name (in Parser will start with "-" + lname string // Long name (in Parser will start with "--" + size int // Size defines how many args after match will need to be consumed + unique bool // Specifies whether flag should be present only ones + parsed bool // Specifies whether flag has been parsed already + fileFlag int // File mode to open file with + filePerm os.FileMode // File permissions to set a file + selector *[]string // Used in Selector type to allow to choose only one from list of options + parent *Command // Used to get access to specific Command + eqChar bool // This is used if the command is passed in with an equals char as a seperator + noDefault bool // This is used if Default in argparse.Options should not be allowed + argType ArgumentType // Used to determine which argument type this is } +// enum used to determine the argument type +type ArgumentType int + +const ( + Flag ArgumentType = 0 + FlagCounter = 1 + String = 2 + Int = 3 + Float = 4 + File = 5 + StringList = 6 + IntList = 7 + FloatList = 8 + FileList = 9 + Selector = 10 +) + // Arg interface provides exporting of arg structure, while exposing it type Arg interface { GetOpts() *Options From 53b4834441737338afd54d77cfd2bce31fe523e9 Mon Sep 17 00:00:00 2001 From: Alec Bakholdin Date: Fri, 1 Jul 2022 02:01:48 -0400 Subject: [PATCH 11/14] flags now ignore a default value of true --- argparse_test.go | 35 ++++++++++++++++++++++++++++++----- argument.go | 6 +++++- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/argparse_test.go b/argparse_test.go index 88b039c..138517a 100644 --- a/argparse_test.go +++ b/argparse_test.go @@ -1981,18 +1981,43 @@ func TestIntMissingArgFail(t *testing.T) { } } -func TestFlagDefaultValueFail(t *testing.T) { +func TestFlagDefaultValuePass(t *testing.T) { testArgs := []string{"progname"} p := NewParser("progname", "Prog description") - _ = p.Flag("f", "flag", &Options{Default: true}) + f := p.Flag("f", "flag", &Options{Default: false}) err := p.Parse(testArgs) - // Should pass on failure - if err == nil || err.Error() != "argument [f, flag] does not support default values" { - t.Errorf("Test %s failed: expected error [%s], got error [%+v]", t.Name(), "argument [f, flag] does not support default values", err) + // Should fail on failure + if err != nil { + t.Error(err.Error()) + } + + // Should fail if not false + if *f != false { + t.Errorf("expected [false] but found [%t]", *f) + } +} + +func TestFlagDefaultValueShouldIgnoreTrue(t *testing.T) { + testArgs := []string{"progname"} + + p := NewParser("progname", "Prog description") + + f := p.Flag("f", "flag", &Options{Default: true}) + + err := p.Parse(testArgs) + + // Should fail on failure + if err != nil { + t.Error(err.Error()) + } + + // Should fail if not false + if *f != false { + t.Errorf("expected [false] but found [%t]", *f) } } diff --git a/argument.go b/argument.go index dc71c2c..989a634 100644 --- a/argument.go +++ b/argument.go @@ -528,7 +528,11 @@ func (o *arg) setDefault() error { if reflect.TypeOf(o.result) != reflect.PtrTo(reflect.TypeOf(o.opts.Default)) { return fmt.Errorf("cannot use default type [%T] as value of pointer with type [%T]", o.opts.Default, o.result) } - reflect.ValueOf(o.result).Elem().Set(reflect.ValueOf(o.opts.Default)) + defaultValue := o.opts.Default + if o.argType == Flag && defaultValue == true { + defaultValue = false + } + reflect.ValueOf(o.result).Elem().Set(reflect.ValueOf(defaultValue)) case *os.File: if err := o.setDefaultFile(); err != nil { From 0bbb0229d18430aea5b5a0790d9af24640eb19de Mon Sep 17 00:00:00 2001 From: Alec Bakholdin Date: Fri, 1 Jul 2022 02:03:44 -0400 Subject: [PATCH 12/14] removed noDefault --- argument.go | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/argument.go b/argument.go index 989a634..2688839 100644 --- a/argument.go +++ b/argument.go @@ -9,20 +9,19 @@ import ( ) type arg struct { - result interface{} // Pointer to the resulting value - opts *Options // Options - sname string // Short name (in Parser will start with "-" - lname string // Long name (in Parser will start with "--" - size int // Size defines how many args after match will need to be consumed - unique bool // Specifies whether flag should be present only ones - parsed bool // Specifies whether flag has been parsed already - fileFlag int // File mode to open file with - filePerm os.FileMode // File permissions to set a file - selector *[]string // Used in Selector type to allow to choose only one from list of options - parent *Command // Used to get access to specific Command - eqChar bool // This is used if the command is passed in with an equals char as a seperator - noDefault bool // This is used if Default in argparse.Options should not be allowed - argType ArgumentType // Used to determine which argument type this is + result interface{} // Pointer to the resulting value + opts *Options // Options + sname string // Short name (in Parser will start with "-" + lname string // Long name (in Parser will start with "--" + size int // Size defines how many args after match will need to be consumed + unique bool // Specifies whether flag should be present only ones + parsed bool // Specifies whether flag has been parsed already + fileFlag int // File mode to open file with + filePerm os.FileMode // File permissions to set a file + selector *[]string // Used in Selector type to allow to choose only one from list of options + parent *Command // Used to get access to specific Command + eqChar bool // This is used if the command is passed in with an equals char as a seperator + argType ArgumentType // Used to determine which argument type this is } // enum used to determine the argument type @@ -520,9 +519,6 @@ func (o *arg) setDefaultFiles() error { func (o *arg) setDefault() error { // Only set default if it was not parsed, and default value was defined if !o.parsed && o.opts != nil && o.opts.Default != nil { - if o.noDefault { - return fmt.Errorf("argument [%s, %s] does not support default values", o.sname, o.lname) - } switch o.result.(type) { case *bool, *int, *float64, *string, *[]bool, *[]int, *[]float64, *[]string: if reflect.TypeOf(o.result) != reflect.PtrTo(reflect.TypeOf(o.opts.Default)) { From 2759216e2470e5b226a55b7251e0076625f15881 Mon Sep 17 00:00:00 2001 From: Alec Bakholdin Date: Thu, 30 Jun 2022 17:43:30 -0400 Subject: [PATCH 13/14] added test for ignoring default and deleted tests that tested functionality of defaults for flags --- argparse_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/argparse_test.go b/argparse_test.go index 138517a..c589971 100644 --- a/argparse_test.go +++ b/argparse_test.go @@ -2052,7 +2052,7 @@ func TestStringDefaultValueFail(t *testing.T) { err := p.Parse(testArgs) // Should pass on failure - if err == nil || err.Error() != "cannot use default type [bool] as value of pointer with type [*string]" { + if err == nil || err.Error() != "argument [s, string] does not support default values" { t.Errorf("Test %s failed: expected error [%s], got error [%+v]", t.Name(), "cannot use default type [bool] as value of pointer with type [*string]", err) } } From f2be4747e2c9cff70c2b1f0c623845842801907e Mon Sep 17 00:00:00 2001 From: Alec Bakholdin Date: Thu, 30 Jun 2022 22:37:27 -0400 Subject: [PATCH 14/14] realized I modified the wrong test in the previous commit --- argparse_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/argparse_test.go b/argparse_test.go index c589971..138517a 100644 --- a/argparse_test.go +++ b/argparse_test.go @@ -2052,7 +2052,7 @@ func TestStringDefaultValueFail(t *testing.T) { err := p.Parse(testArgs) // Should pass on failure - if err == nil || err.Error() != "argument [s, string] does not support default values" { + if err == nil || err.Error() != "cannot use default type [bool] as value of pointer with type [*string]" { t.Errorf("Test %s failed: expected error [%s], got error [%+v]", t.Name(), "cannot use default type [bool] as value of pointer with type [*string]", err) } }