From 2d260eef7eafb3b6f6327093d98912d13a4cc5ef Mon Sep 17 00:00:00 2001 From: Andrei Merlescu Date: Thu, 3 Jul 2025 05:10:25 -0400 Subject: [PATCH 1/4] Adjusted error handling and moved flag.Var to tree.flagSet.Var --- alias.go | 3 +- assure.go | 88 ++++++++++++++++++------------------ conversions.go | 18 ++++---- errors.go | 28 ++++++++++++ loading.go | 5 ++- mutagenesis.go | 115 +++++++++++++++++++++++++++++++++++++++++++++++ mutations_new.go | 101 ++++------------------------------------- parsing.go | 22 ++++----- 8 files changed, 220 insertions(+), 160 deletions(-) create mode 100644 mutagenesis.go diff --git a/alias.go b/alias.go index 6e3b232..de6a7ac 100644 --- a/alias.go +++ b/alias.go @@ -1,7 +1,6 @@ package figtree import ( - "flag" "fmt" "strings" ) @@ -25,6 +24,6 @@ func (tree *figTree) WithAlias(name, alias string) Plant { fmt.Println("failed to cast -" + name + " value") return tree } - flag.Var(value, alias, "Alias of -"+name) + tree.flagSet.Var(value, alias, "Alias of -"+name) return tree } diff --git a/assure.go b/assure.go index 994fcc7..0824514 100644 --- a/assure.go +++ b/assure.go @@ -36,7 +36,7 @@ var AssureStringNoSuffixes = func(suffixes []string) FigValidatorFunc { } return nil } - return fmt.Errorf("invalid type, expected string, got %T", value) + return ErrInvalidType{tString, value} } } @@ -53,7 +53,7 @@ var AssureStringNoPrefixes = func(prefixes []string) FigValidatorFunc { } return nil } - return fmt.Errorf("invalid type, expected string, got %T", value) + return ErrInvalidType{tString, value} } } @@ -70,7 +70,7 @@ var AssureStringHasSuffixes = func(suffixes []string) FigValidatorFunc { } return nil } - return fmt.Errorf("invalid type, expected string, got %T", value) + return ErrInvalidType{tString, value} } } @@ -87,7 +87,7 @@ var AssureStringHasPrefixes = func(prefixes []string) FigValidatorFunc { } return nil } - return fmt.Errorf("invalid type, expected string, got %T", value) + return ErrInvalidType{tString, value} } } @@ -103,7 +103,7 @@ var AssureStringNoSuffix = func(suffix string) FigValidatorFunc { } return nil } - return fmt.Errorf("invalid type, expected string, got %T", value) + return ErrInvalidType{tString, value} } } @@ -119,7 +119,7 @@ var AssureStringNoPrefix = func(prefix string) FigValidatorFunc { } return nil } - return fmt.Errorf("invalid type, expected string, got %T", value) + return ErrInvalidType{tString, value} } } @@ -135,7 +135,7 @@ var AssureStringLengthLessThan = func(length int) FigValidatorFunc { } return nil } - return fmt.Errorf("invalid type, expected string, got %T", value) + return ErrInvalidType{tString, value} } } @@ -151,7 +151,7 @@ var AssureStringLengthGreaterThan = func(length int) FigValidatorFunc { } return nil } - return fmt.Errorf("invalid type, expected string, got %T", value) + return ErrInvalidType{tString, value} } } @@ -167,7 +167,7 @@ var AssureStringSubstring = func(sub string) FigValidatorFunc { } return nil } - return fmt.Errorf("invalid type, expected string, got %T", value) + return ErrInvalidType{tString, value} } } @@ -184,7 +184,7 @@ var AssureStringLength = func(length int) FigValidatorFunc { return nil } - return fmt.Errorf("invalid type, expected string, got %T", value) + return ErrInvalidType{tString, value} } } @@ -200,7 +200,7 @@ var AssureStringNotLength = func(length int) FigValidatorFunc { } return nil } - return fmt.Errorf("invalid type, expected string, got %T", value) + return ErrInvalidType{tString, value} } } @@ -214,7 +214,7 @@ var AssureStringNotEmpty = func(value interface{}) error { } return nil } - return fmt.Errorf("invalid type, got %T", value) + return ErrInvalidType{tString, value} } // AssureStringContains ensures a string contains a specific substring. @@ -238,7 +238,7 @@ var AssureStringNotContains = func(substring string) FigValidatorFunc { } return nil } - return fmt.Errorf("invalid type, got %T", value) + return ErrInvalidType{tString, value} } } @@ -252,7 +252,7 @@ var AssureBoolTrue = func(value interface{}) error { } return nil } - return fmt.Errorf("invalid type, expected bool, got %T", value) + return ErrInvalidType{tBool, value} } // AssureBoolFalse ensures a boolean value is false. @@ -265,7 +265,7 @@ var AssureBoolFalse = func(value interface{}) error { } return nil } - return fmt.Errorf("invalid type, expected bool, got %T", value) + return ErrInvalidType{tBool, value} } // AssureIntPositive ensures an integer is positive. @@ -278,7 +278,7 @@ var AssureIntPositive = func(value interface{}) error { } return nil } - return fmt.Errorf("invalid type, expected int, got %T", value) + return ErrInvalidType{tInt, value} } // AssureIntNegative ensures an integer is negative. @@ -291,7 +291,7 @@ var AssureIntNegative = func(value interface{}) error { } return nil } - return fmt.Errorf("invalid type, expected int, got %T", value) + return ErrInvalidType{tInt, value} } // AssureIntGreaterThan ensures an integer is greater than (but not including) an int. @@ -300,7 +300,7 @@ var AssureIntGreaterThan = func(above int) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsInt() { - return fmt.Errorf("invalid type, expected int, got %T", value) + return ErrInvalidType{tInt, value} } i := v.ToInt() if i < above { @@ -316,7 +316,7 @@ var AssureIntLessThan = func(below int) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsInt() { - return fmt.Errorf("invalid type, expected int, got %T", value) + return ErrInvalidType{tInt, value} } i := v.ToInt() if i > below { @@ -332,7 +332,7 @@ var AssureIntInRange = func(min, max int) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsInt() { - return fmt.Errorf("invalid type, expected int, got %T", value) + return ErrInvalidType{tInt, value} } i := v.ToInt() if i < min || i > max { @@ -348,7 +348,7 @@ var AssureInt64GreaterThan = func(above int64) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsInt64() { - return fmt.Errorf("invalid type, expected int64, got %T", value) + return ErrInvalidType{tInt64, value} } i := v.ToInt64() if i < above { @@ -379,7 +379,7 @@ var AssureInt64LessThan = func(below int64) FigValidatorFunc { var AssureInt64Positive = func(value interface{}) error { v := figFlesh{value, nil} if !v.IsInt64() { - return fmt.Errorf("invalid type, expected int64, got %T", value) + return ErrInvalidType{tInt64, value} } i := v.ToInt64() if i <= 0 { @@ -394,7 +394,7 @@ var AssureInt64InRange = func(min, max int64) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsInt64() { - return fmt.Errorf("invalid type, expected int64, got %T", value) + return ErrInvalidType{tInt64, value} } i := v.ToInt64() if i < min || i > max { @@ -409,7 +409,7 @@ var AssureInt64InRange = func(min, max int64) FigValidatorFunc { var AssureFloat64Positive = func(value interface{}) error { v := figFlesh{value, nil} if !v.IsFloat64() { - return fmt.Errorf("invalid type, expected float64, got %T", value) + return ErrInvalidType{tFloat64, value} } f := v.ToFloat64() if f <= 0 { @@ -424,7 +424,7 @@ var AssureFloat64InRange = func(min, max float64) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsFloat64() { - return fmt.Errorf("invalid type, expected float64, got %T", value) + return ErrInvalidType{tFloat64, value} } f := v.ToFloat64() if f < min || f > max { @@ -440,7 +440,7 @@ var AssureFloat64GreaterThan = func(above float64) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsFloat64() { - return fmt.Errorf("invalid type, expected float64, got %T", value) + return ErrInvalidType{tFloat64, value} } f := v.ToFloat64() if f < above { @@ -456,7 +456,7 @@ var AssureFloat64LessThan = func(below float64) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsFloat64() { - return fmt.Errorf("invalid type, expected float64, got %T", value) + return ErrInvalidType{tFloat64, value} } f := v.ToFloat64() if f > below { @@ -471,7 +471,7 @@ var AssureFloat64LessThan = func(below float64) FigValidatorFunc { var AssureFloat64NotNaN = func(value interface{}) error { v := figFlesh{value, nil} if !v.IsFloat64() { - return fmt.Errorf("invalid type, expected float64, got %T", value) + return ErrInvalidType{tFloat64, value} } n := v.ToFloat64() if math.IsNaN(n) { @@ -517,7 +517,7 @@ var AssureDurationLessThan = func(below time.Duration) FigValidatorFunc { var AssureDurationPositive = func(value interface{}) error { v := figFlesh{value, nil} if !v.IsDuration() { - return fmt.Errorf("invalid type, expected time.Duration, got %T", value) + return ErrInvalidType{tDuration, value} } d := v.ToDuration() if d <= 0 { @@ -532,7 +532,7 @@ var AssureDurationMin = func(min time.Duration) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsDuration() { - return fmt.Errorf("value must be a duration, got %s", v) + return ErrInvalidType{tDuration, value} } d := v.ToDuration() if d < min { @@ -548,7 +548,7 @@ var AssureDurationMax = func(max time.Duration) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsDuration() { - return fmt.Errorf("invalid type, expected time.Duration, got %T", value) + return ErrInvalidType{tDuration, value} } d := v.ToDuration() if d > max { @@ -563,7 +563,7 @@ var AssureDurationMax = func(max time.Duration) FigValidatorFunc { var AssureListNotEmpty = func(value interface{}) error { v := figFlesh{value, nil} if !v.IsList() { - return fmt.Errorf("invalid type, expected *ListFlag or []string, got %T", v) + return ErrInvalidType{tList, value} } l := v.ToList() if len(l) == 0 { @@ -578,7 +578,7 @@ var AssureListMinLength = func(min int) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsList() { - return fmt.Errorf("invalid type, expected *ListFlag or []string, got %T", v) + return ErrInvalidType{tList, value} } l := v.ToList() if len(l) < min { @@ -594,7 +594,7 @@ var AssureListContains = func(inside string) FigValidatorFunc { return func(value interface{}) error { v := NewFlesh(value) if !v.IsList() { - return fmt.Errorf("invalid type, expected ListFlag or []string, got %T", value) + return ErrInvalidType{tList, value} } l := v.ToList() for _, item := range l { @@ -612,7 +612,7 @@ var AssureListNotContains = func(not string) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsList() { - return fmt.Errorf("invalid type, expected *ListFlag, []string, or *[]string, got %T", v) + return ErrInvalidType{tList, value} } l := v.ToList() for _, item := range l { @@ -631,7 +631,7 @@ var AssureListContainsKey = func(key string) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsList() { - return fmt.Errorf("invalid type, expected *ListFlag or []string, got %T", value) + return ErrInvalidType{tList, value} } l := v.ToList() for _, item := range l { @@ -650,7 +650,7 @@ var AssureListLength = func(length int) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsList() { - return fmt.Errorf("invalid type, expected *ListFlag or []string, got %T", value) + return ErrInvalidType{tList, value} } l := v.ToList() if len(l) != length { @@ -665,11 +665,11 @@ var AssureListLength = func(length int) FigValidatorFunc { var AssureMapNotEmpty = func(value interface{}) error { v := figFlesh{value, nil} if !v.IsMap() { - return fmt.Errorf("invalid type, expected *ListFlag or []string, got %T", v) + return ErrInvalidType{tMap, value} } m := v.ToMap() if len(m) == 0 { - return fmt.Errorf("list is empty") + return fmt.Errorf("map is empty") } return nil } @@ -680,7 +680,7 @@ var AssureMapHasKey = func(key string) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsMap() { - return fmt.Errorf("invalid type, got %T", value) + return ErrInvalidType{tMap, value} } m := v.ToMap() if _, exists := m[key]; !exists { @@ -696,7 +696,7 @@ var AssureMapHasNoKey = func(key string) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsMap() { - return fmt.Errorf("invalid type, got %T", value) + return ErrInvalidType{tMap, value} } m := v.ToMap() if _, exists := m[key]; exists { @@ -732,7 +732,7 @@ var AssureMapHasKeys = func(keys []string) FigValidatorFunc { var missing []string v := figFlesh{value, nil} if !v.IsMap() { - return fmt.Errorf("invalid type, expected map[string]string, got %T", v) + return ErrInvalidType{tMap, value} } m := v.ToMap() for _, key := range keys { @@ -754,7 +754,7 @@ var AssureMapLength = func(length int) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsMap() { - return fmt.Errorf("invalid type, expected *MapFlag or map[string]string, got %T", value) + return ErrInvalidType{tMap, value} } m := v.ToMap() if len(m) != length { @@ -771,7 +771,7 @@ var AssureMapNotLength = func(length int) FigValidatorFunc { return func(value interface{}) error { v := figFlesh{value, nil} if !v.IsMap() { - return fmt.Errorf("invalid type, got %T", value) + return ErrInvalidType{tMap, value} } m := v.ToMap() if len(m) == length { diff --git a/conversions.go b/conversions.go index 0ee3cb3..d4a0d54 100644 --- a/conversions.go +++ b/conversions.go @@ -39,7 +39,7 @@ func toInt(value interface{}) (int, error) { } return strconv.Atoi(v) default: - return 0, fmt.Errorf("cannot convert %v to int", value) + return 0, ErrConversion{MutagenesisOf(value), tInt, value} } } @@ -73,7 +73,7 @@ func toInt64(value interface{}) (int64, error) { } return strconv.ParseInt(v, 10, 64) default: - return 0, fmt.Errorf("cannot convert %v to int64", value) + return 0, ErrConversion{MutagenesisOf(value), tInt64, value} } } @@ -101,7 +101,7 @@ func toFloat64(value interface{}) (float64, error) { case string: return strconv.ParseFloat(v, 64) default: - return 0, fmt.Errorf("cannot convert %v to float64", value) + return 0, ErrConversion{MutagenesisOf(value), tFloat64, value} } } @@ -165,7 +165,7 @@ func toString(value interface{}) (string, error) { } return strings.Join(parts, MapSeparator), nil default: - return "", fmt.Errorf("cannot convert %v %T to string", value, value) + return "", ErrConversion{MutagenesisOf(value), tString, value} } } @@ -185,7 +185,7 @@ func toBool(value interface{}) (bool, error) { case bool: return v, nil default: - return false, fmt.Errorf("cannot convert %v to bool", value) + return false, ErrConversion{MutagenesisOf(value), tBool, value} } } @@ -219,7 +219,7 @@ func toStringSlice(value interface{}) ([]string, error) { return []string{}, nil } if strings.Contains(*v, MapKeySeparator) { - return nil, fmt.Errorf("cannot convert %v to []string", value) + return nil, ErrConversion{MutagenesisOf(value), tList, value} } return strings.Split(*v, ListSeparator), nil case string: @@ -227,11 +227,11 @@ func toStringSlice(value interface{}) ([]string, error) { return []string{}, nil } if strings.Contains(v, MapSeparator) && strings.Contains(v, MapKeySeparator) { - return nil, fmt.Errorf("cannot convert map %v to []string", value) + return nil, ErrConversion{MutagenesisOf(value), tList, value} } return strings.Split(v, ListSeparator), nil default: - return nil, fmt.Errorf("cannot convert %v %T to []string", value, value) + return nil, ErrConversion{MutagenesisOf(value), tList, value} } } @@ -289,6 +289,6 @@ func toStringMap(value interface{}) (map[string]string, error) { } return result, nil default: - return nil, fmt.Errorf("cannot convert %v to map[string]string", value) + return nil, ErrConversion{MutagenesisOf(value), tMap, value} } } diff --git a/errors.go b/errors.go index cf785c3..24bb7e3 100644 --- a/errors.go +++ b/errors.go @@ -14,3 +14,31 @@ func (tree *figTree) ErrorFor(name string) error { } return fruit.Error } + +type ErrInvalidType struct { + Wanted Mutagenesis + Got any +} + +func (e ErrInvalidType) Error() string { + return fmt.Sprintf("invalid type ; got %s ; wanted %s", e.Got, e.Wanted.Kind()) +} + +type ErrConversion struct { + From Mutagenesis + To Mutagenesis + Got any +} + +func (e ErrConversion) Error() string { + return fmt.Sprintf("failed to convert %T type %s into %s", e.Got, e.From.Kind(), e.To.Kind()) +} + +type ErrInvalidValue struct { + Name string + Err error +} + +func (e ErrInvalidValue) Error() string { + return fmt.Sprintf("invalid value for flag -%s: %s", e.Name, e.Err.Error()) +} diff --git a/loading.go b/loading.go index 2538765..29f545b 100644 --- a/loading.go +++ b/loading.go @@ -4,11 +4,12 @@ import ( "errors" "flag" "fmt" - check "github.com/andreimerlescu/checkfs" - "github.com/andreimerlescu/checkfs/file" "os" "path/filepath" "strings" + + check "github.com/andreimerlescu/checkfs" + "github.com/andreimerlescu/checkfs/file" ) // Reload will readEnv on each flag in the configurable package diff --git a/mutagenesis.go b/mutagenesis.go new file mode 100644 index 0000000..55f1793 --- /dev/null +++ b/mutagenesis.go @@ -0,0 +1,115 @@ +package figtree + +import ( + "flag" + "time" +) + +func (m Mutagenesis) Kind() string { + switch m { + case tString: + return "string|*string" + case tBool: + return "bool|*bool" + case tInt: + return "int|*int" + case tInt64: + return "int64|*int64" + case tFloat64: + return "float64|*float64" + case tDuration, tUnitDuration: + return "time.Duration|*time.Duration" + case tList: + return "ListFlag|*ListFlag|[]string|*[]string" + case tMap: + return "MapFlag|*MapFlag|map[string]string|*map[string]string" + default: + return string(m) + } +} + +// MutagenesisOfFig returns the Mutagensis of the name +func (tree *figTree) MutagenesisOfFig(name string) Mutagenesis { + fruit, ok := tree.figs[name] + if !ok { + return "" + } + return fruit.Mutagenesis +} + +func MutagenesisOf(what interface{}) Mutagenesis { + switch x := what.(type) { + case Value: + return x.Mutagensis + case flag.Value: + fv, e := toFloat64(x.String()) + if e == nil { + return MutagenesisOf(fv) + } + i64v, e := toInt64(x.String()) + if e == nil { + return MutagenesisOf(i64v) + } + iv, e := toInt(x.String()) + if e == nil { + return MutagenesisOf(iv) + } + bv, e := toBool(x.String()) + if e == nil { + return MutagenesisOf(bv) + } + sv, e := toStringSlice(x.String()) + if e == nil { + return MutagenesisOf(sv) + } + mv, e := toStringMap(x.String()) + if e == nil { + return MutagenesisOf(mv) + } + return "" + + case int: + return tInt + case *int: + return tInt + case *int64: + return tInt64 + case int64: + return tInt64 + case string: + return tString + case *string: + return tString + case bool: + return tBool + case *bool: + return tBool + case *float64: + return tFloat64 + case float64: + return tFloat64 + case time.Duration: + return tDuration + case *time.Duration: + return tDuration + case []string: + return tList + case *[]string: + return tList + case map[string]string: + return tMap + case *map[string]string: + return tMap + default: + return "" + } +} + +// MutagenesisOf accepts anything and allows you to determine the Mutagensis of the type of from what +// Example: +// +// tree.MutagenesisOf("hello") // Returns tString +// tree.MutagenesisOf(42) // Returns tInt +func (tree *figTree) MutagenesisOf(what interface{}) Mutagenesis { + return MutagenesisOf(what) +} diff --git a/mutations_new.go b/mutations_new.go index 60ed6df..9d7fefc 100644 --- a/mutations_new.go +++ b/mutations_new.go @@ -1,93 +1,10 @@ package figtree import ( - "flag" "strings" "time" ) -// MutagenesisOfFig returns the Mutagensis of the name -func (tree *figTree) MutagenesisOfFig(name string) Mutagenesis { - fruit, ok := tree.figs[name] - if !ok { - return "" - } - return fruit.Mutagenesis -} - -// MutagenesisOf accepts anything and allows you to determine the Mutagensis of the type of from what -// Example: -// -// tree.MutagenesisOf("hello") // Returns tString -// tree.MutagenesisOf(42) // Returns tInt -func (tree *figTree) MutagenesisOf(what interface{}) Mutagenesis { - switch x := what.(type) { - case Value: - return x.Mutagensis - case flag.Value: - fv, e := toFloat64(x.String()) - if e == nil { - return tree.MutagenesisOf(fv) - } - i64v, e := toInt64(x.String()) - if e == nil { - return tree.MutagenesisOf(i64v) - } - iv, e := toInt(x.String()) - if e == nil { - return tree.MutagenesisOf(iv) - } - bv, e := toBool(x.String()) - if e == nil { - return tree.MutagenesisOf(bv) - } - sv, e := toStringSlice(x.String()) - if e == nil { - return tree.MutagenesisOf(sv) - } - mv, e := toStringMap(x.String()) - if e == nil { - return tree.MutagenesisOf(mv) - } - return "" - - case int: - return tInt - case *int: - return tInt - case *int64: - return tInt64 - case int64: - return tInt64 - case string: - return tString - case *string: - return tString - case bool: - return tBool - case *bool: - return tBool - case *float64: - return tFloat64 - case float64: - return tFloat64 - case time.Duration: - return tDuration - case *time.Duration: - return tDuration - case []string: - return tList - case *[]string: - return tList - case map[string]string: - return tMap - case *map[string]string: - return tMap - default: - return "" - } -} - // NewString with validator and withered support func (tree *figTree) NewString(name string, value string, usage string) Plant { tree.mu.Lock() @@ -99,7 +16,7 @@ func (tree *figTree) NewString(name string, value string, usage string) Plant { Mutagensis: tString, } tree.values.Store(name, vPtr) - flag.Var(vPtr, name, usage) + tree.flagSet.Var(vPtr, name, usage) def := &figFruit{ name: name, usage: usage, @@ -133,7 +50,7 @@ func (tree *figTree) NewBool(name string, value bool, usage string) Plant { Mutagensis: tBool, } tree.values.Store(name, v) - flag.Var(v, name, usage) + tree.flagSet.Var(v, name, usage) def := &figFruit{ name: name, usage: usage, @@ -163,7 +80,7 @@ func (tree *figTree) NewInt(name string, value int, usage string) Plant { Mutagensis: tInt, } tree.values.Store(name, v) - flag.Var(v, name, usage) + tree.flagSet.Var(v, name, usage) def := &figFruit{ name: name, usage: usage, @@ -193,7 +110,7 @@ func (tree *figTree) NewInt64(name string, value int64, usage string) Plant { Mutagensis: tInt64, } tree.values.Store(name, v) - flag.Var(v, name, usage) + tree.flagSet.Var(v, name, usage) def := &figFruit{ name: name, usage: usage, @@ -223,7 +140,7 @@ func (tree *figTree) NewFloat64(name string, value float64, usage string) Plant Mutagensis: tFloat64, } tree.values.Store(name, v) - flag.Var(v, name, usage) + tree.flagSet.Var(v, name, usage) def := &figFruit{ name: name, usage: usage, @@ -253,7 +170,7 @@ func (tree *figTree) NewDuration(name string, value time.Duration, usage string) Mutagensis: tDuration, } tree.values.Store(name, v) - flag.Var(v, name, usage) + tree.flagSet.Var(v, name, usage) def := &figFruit{ name: name, usage: usage, @@ -283,7 +200,7 @@ func (tree *figTree) NewUnitDuration(name string, value, units time.Duration, us Mutagensis: tUnitDuration, } tree.values.Store(name, v) - flag.Var(v, name, usage) + tree.flagSet.Var(v, name, usage) def := &figFruit{ name: name, usage: usage, @@ -316,7 +233,7 @@ func (tree *figTree) NewList(name string, value []string, usage string) Plant { Mutagensis: tList, } tree.values.Store(name, v) - flag.Var(v, name, usage) + tree.flagSet.Var(v, name, usage) def := &figFruit{ name: name, usage: usage, @@ -354,7 +271,7 @@ func (tree *figTree) NewMap(name string, value map[string]string, usage string) Mutagensis: tMap, } tree.values.Store(name, v) - flag.Var(v, name, usage) + tree.flagSet.Var(v, name, usage) def := &figFruit{ name: name, usage: usage, diff --git a/parsing.go b/parsing.go index 0156364..0fb8e82 100644 --- a/parsing.go +++ b/parsing.go @@ -113,7 +113,7 @@ func (tree *figTree) checkFigErrors() error { if er != nil { e = errors.Join(e, er) } - return fmt.Errorf("invalid value for flag -%s: %w", name, e) + return ErrInvalidValue{name, e} } case tInt: _, e := toInt(value) @@ -122,7 +122,7 @@ func (tree *figTree) checkFigErrors() error { if er != nil { e = errors.Join(e, er) } - return fmt.Errorf("invalid value for flag -%s: %w", name, e) + return ErrInvalidValue{name, e} } case tFloat64: _, e := toFloat64(value) @@ -131,7 +131,7 @@ func (tree *figTree) checkFigErrors() error { if er != nil { e = errors.Join(e, er) } - return fmt.Errorf("invalid value for flag -%s: %w", name, e) + return ErrInvalidValue{name, e} } case tBool: @@ -141,7 +141,7 @@ func (tree *figTree) checkFigErrors() error { if er != nil { e = errors.Join(e, er) } - return fmt.Errorf("invalid value for flag -%s: %w", name, e) + return ErrInvalidValue{name, e} } case tInt64, tUnitDuration, tDuration: if value.Mutagensis == tUnitDuration || value.Mutagensis == tDuration { @@ -154,7 +154,7 @@ func (tree *figTree) checkFigErrors() error { if err == nil { err = value.Assign(val) if err != nil { - return fmt.Errorf("invalid value for flag -%s: %w", name, err) + return ErrInvalidValue{name, err} } continue } @@ -170,7 +170,7 @@ func (tree *figTree) checkFigErrors() error { if er != nil { e = errors.Join(e, er) } - return fmt.Errorf("invalid value for flag -%s: %w", name, e) + return ErrInvalidValue{name, e} } case tMap: _, e := toStringMap(value.Value) @@ -179,7 +179,7 @@ func (tree *figTree) checkFigErrors() error { if er != nil { e = errors.Join(e, er) } - return fmt.Errorf("invalid value for flag -%s: %w", name, e) + return ErrInvalidValue{name, e} } case tList: _, e := toStringSlice(value.Value) @@ -188,10 +188,10 @@ func (tree *figTree) checkFigErrors() error { if er != nil { e = errors.Join(e, er) } - return fmt.Errorf("invalid value for flag -%s: %w", name, e) + return ErrInvalidValue{name, e} } default: - return fmt.Errorf("invalid value for flag -%s: %w", name, fmt.Errorf("unknown flag type")) + return ErrInvalidValue{name, fmt.Errorf("unknown flag type")} } } return nil @@ -256,7 +256,7 @@ func (tree *figTree) applyWithered() error { } err := value.Assign(unique) if err != nil { - return fmt.Errorf("failed to assign %s due to %w", name, err) + return ErrInvalidValue{name, err} } tree.values.Store(name, value) } @@ -280,7 +280,7 @@ func (tree *figTree) applyWithered() error { sort.Strings(result) err := value.Assign(result) if err != nil { - return fmt.Errorf("failed assign to %s: %w", name, err) + return ErrInvalidValue{name, err} } tree.values.Store(name, value) } From 3b4378309b7301cb486737a0214841a3c69ccdd1 Mon Sep 17 00:00:00 2001 From: Andrei Merlescu Date: Thu, 3 Jul 2025 05:15:12 -0400 Subject: [PATCH 2/4] Added Copilot recommendation --- errors.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/errors.go b/errors.go index 24bb7e3..8abfd76 100644 --- a/errors.go +++ b/errors.go @@ -31,7 +31,7 @@ type ErrConversion struct { } func (e ErrConversion) Error() string { - return fmt.Sprintf("failed to convert %T type %s into %s", e.Got, e.From.Kind(), e.To.Kind()) + return fmt.Sprintf("failed to convert %v (type %T) type %s into %s", e.Got, e.Got, e.From.Kind(), e.To.Kind()) } type ErrInvalidValue struct { From f2e8dacb9eaa6e6acb2588b34d67c5fd7e17fada Mon Sep 17 00:00:00 2001 From: Andrei Merlescu Date: Thu, 3 Jul 2025 05:17:12 -0400 Subject: [PATCH 3/4] Added Unwrap for errors.Is and errors.As usage on type --- errors.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/errors.go b/errors.go index 8abfd76..5cce4a8 100644 --- a/errors.go +++ b/errors.go @@ -42,3 +42,7 @@ type ErrInvalidValue struct { func (e ErrInvalidValue) Error() string { return fmt.Sprintf("invalid value for flag -%s: %s", e.Name, e.Err.Error()) } + +func (e ErrInvalidValue) Unwrap() error { + return e.Err +} From dcac5d41c7de7fdba15cfcb77cbd857bd4188956 Mon Sep 17 00:00:00 2001 From: Andrei Merlescu Date: Thu, 3 Jul 2025 05:20:19 -0400 Subject: [PATCH 4/4] Bumped version for new release --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 93b1c84..9949c17 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.12 \ No newline at end of file +v2.0.13 \ No newline at end of file