Skip to content

Commit

Permalink
✨ feat: cflag - add new ext flag var types: IntVar, StrVar
Browse files Browse the repository at this point in the history
- IntVar, StrVar can be with value check func
- add more unit test cases for other ext type
  • Loading branch information
inhere committed Jun 29, 2023
1 parent 4d52d37 commit 899294d
Show file tree
Hide file tree
Showing 5 changed files with 263 additions and 66 deletions.
2 changes: 1 addition & 1 deletion cflag/cflag.go
Expand Up @@ -222,7 +222,7 @@ func (c *CFlags) MustParse(args []string) {
}
}

// Parse flags and run command
// Parse flags and run command func
//
// If args is nil, will parse os.Args
func (c *CFlags) Parse(args []string) error {
Expand Down
227 changes: 167 additions & 60 deletions cflag/ext.go
Expand Up @@ -20,23 +20,160 @@ type RepeatableFlag interface {
IsRepeatable() bool
}

// LimitInt limit int value range
func LimitInt(min, max int) comdef.IntCheckFunc {
return func(val int) error {
if val < min || val > max {
return fmt.Errorf("the value must be between %d and %d", min, max)
}
return nil
}
}

/*************************************************************************
* options: some special flag vars
* - implemented flag.Value interface
*************************************************************************/

// IntValue int, allow limit min and max value TODO
type IntValue struct {
val string //lint:ignore U1000 is TODO
// validate
Min, Max int
// IntVar int value can with a check func
//
// Limit min and max value:
//
// iv := cflag.IntValue{CheckFn: cflag.LimitInt(1, 10)}
// fs.IntVar(&iv, "int", 1, "the int value")
type IntVar struct {
val int
str string
// check func
CheckFn comdef.IntCheckFunc
}

// NewIntVar create a new IntVar instance with check func
func NewIntVar(checkFn comdef.IntCheckFunc) IntVar {
return IntVar{CheckFn: checkFn}
}

// Get value string
func (o *IntVar) Get() any {
return o.str
}

// Set new value
func (o *IntVar) Set(value string) error {
intVal, err := strconv.Atoi(value)
if err != nil {
return err
}

if o.CheckFn != nil {
if err = o.CheckFn(intVal); err != nil {
return err
}
}

o.str = value
o.val = intVal
return nil
}

// String value get
func (o *IntVar) String() string {
return o.str
}

// String a special string
//
// Usage:
//
// // case 1:
// var names gcli.String
// c.VarOpt(&names, "names", "", "multi name by comma split")
//
// --names "tom,john,joy"
// names.Split(",") -> []string{"tom","john","joy"}
//
// // case 2:
// var ids gcli.String
// c.VarOpt(&ids, "ids", "", "multi id by comma split")
//
// --names "23,34,56"
// names.Ints(",") -> []int{23,34,56}
type String string

// Get value
func (s *String) Get() any {
return s
}

// Set value
func (s *String) Set(val string) error {
*s = String(val)
return nil
}

// String input value to string
func (s *String) String() string {
return string(*s)
}

// Strings split value to []string by sep ','
func (s *String) Strings() []string {
return strutil.Split(string(*s), ",")
}

// Split value to []string
func (s *String) Split(sep string) []string {
return strutil.Split(string(*s), sep)
}

// Ints value to []int
func (s *String) Ints(sep string) []int {
return strutil.Ints(string(*s), sep)
}

// StrVar string value can with a check func
//
// Usage:
//
// sv := cflag.StrVar{}
// fs.Var(&sv, "str", "the string value")
type StrVar struct {
val string
// check func
CheckFn comdef.StrCheckFunc
}

// NewStrVar create a new StrVar with check func
func NewStrVar(checkFn comdef.StrCheckFunc) StrVar {
return StrVar{CheckFn: checkFn}
}

// Get value string
func (o *StrVar) Get() any {
return o.val
}

// Set new value
func (o *StrVar) Set(value string) error {
if o.CheckFn != nil {
if err := o.CheckFn(value); err != nil {
return err
}
}

o.val = value
return nil
}

// String value get
func (o *StrVar) String() string {
return o.val
}

// IntsString The ints-string flag. eg: --get 1,2,3
//
// Implemented the flag.Value interface
type IntsString struct {
val string //nolint:unused
ints []int
// value and size validate
ValueFn func(val int) error
Expand All @@ -45,7 +182,7 @@ type IntsString struct {

// String input value to string
func (o *IntsString) String() string {
return o.val
return arrutil.IntsToString(o.ints)
}

// Get value
Expand All @@ -58,7 +195,7 @@ func (o *IntsString) Ints() []int {
return o.ints
}

// Set new value
// Set new value. eg: "12"
func (o *IntsString) Set(value string) error {
intVal, err := strconv.Atoi(value)
if err != nil {
Expand Down Expand Up @@ -90,6 +227,11 @@ func (s *Ints) String() string {
return fmt.Sprintf("%v", *s)
}

// Get value
func (s *Ints) Get() any {
return *s
}

// Set new value
func (s *Ints) Set(value string) error {
intVal, err := strconv.Atoi(value)
Expand All @@ -99,6 +241,11 @@ func (s *Ints) Set(value string) error {
return err
}

// Ints value
func (s *Ints) Ints() []int {
return *s
}

// IsRepeatable on input
func (s *Ints) IsRepeatable() bool {
return true
Expand All @@ -114,6 +261,11 @@ func (s *Strings) String() string {
return strings.Join(*s, ",")
}

// Get value
func (s *Strings) Get() any {
return s
}

// Set new value
func (s *Strings) Set(value string) error {
*s = append(*s, value)
Expand Down Expand Up @@ -148,8 +300,13 @@ func (s *Booleans) IsRepeatable() bool {
return true
}

// EnumString The string flag list.
// EnumString limit input value is in the enum list.
// implemented flag.Value interface
//
// Usage:
//
// var enumStr = cflag.NewEnumString("php", "go", "java")
// c.VarOpt(&enumStr, "lang", "", "input language name")
type EnumString struct {
val string
enum []string
Expand Down Expand Up @@ -177,7 +334,7 @@ func (s *EnumString) SetEnum(enum []string) {

// WithEnum values
func (s *EnumString) WithEnum(enum []string) *EnumString {
s.enum = enum
s.SetEnum(enum)
return s
}

Expand All @@ -201,56 +358,6 @@ func (s *EnumString) Enum() []string {
return s.enum
}

// String a special string
//
// Usage:
//
// // case 1:
// var names gcli.String
// c.VarOpt(&names, "names", "", "multi name by comma split")
//
// --names "tom,john,joy"
// names.Split(",") -> []string{"tom","john","joy"}
//
// // case 2:
// var ids gcli.String
// c.VarOpt(&ids, "ids", "", "multi id by comma split")
//
// --names "23,34,56"
// names.Ints(",") -> []int{23,34,56}
type String string

// Get value
func (s *String) Get() any {
return s
}

// Set value
func (s *String) Set(val string) error {
*s = String(val)
return nil
}

// String input value to string
func (s *String) String() string {
return string(*s)
}

// Strings split value to []string by sep ','
func (s *String) Strings() []string {
return strutil.Split(string(*s), ",")
}

// Split value to []string
func (s *String) Split(sep string) []string {
return strutil.Split(string(*s), sep)
}

// Ints value to []int
func (s *String) Ints(sep string) []int {
return strutil.Ints(string(*s), sep)
}

// KVString The kv-string flag, allow input multi.
//
// Implemented the flag.Value interface.
Expand Down

0 comments on commit 899294d

Please sign in to comment.