package parser import ( "fmt" "strconv" "errors" ) type ArgFlag struct { Name string Short string Long string Description string Type ArgType Arg string Args []string OnMatch func () error } var flags = make(map[string]*ArgFlag) func (f *ArgFlag) requireArg() bool { return f.Type != NoneType && f.Type != BoolType && f.Type != MatchType } func (f *ArgFlag) invalid() bool { return f.Name != "" } func (f *ArgFlag) Matches(identifier string) bool { if f.Name == identifier || f.Short == identifier || f.Long == identifier { return true } return false } func (f *ArgFlag) GetIndex() (int, error) { for i, arg := range f.Args { if arg == f.Short || arg == f.Long { return i, nil } } return 0, fmt.Errorf("ERROR : Flag(%s) not found in arguments", f.Name) } func (f *ArgFlag) GetValueInt() (int64, error) { if f.Type != IntType { return 0, fmt.Errorf("ERROR : Flag(%s) is not a IntType flag", f.symbol()) } return strconv.ParseInt(f.Arg, 10, 64) } func (f *ArgFlag) GetValueString() (string, error) { if f.Type != StringType { return "", fmt.Errorf("ERROR : Flag(%s) is not a StringType flag", f.Name) } return f.Arg, nil } func (f *ArgFlag) symbol() string { index, err := f.GetIndex() if err != nil { return f.Name } return f.Args[index] } func (f *ArgFlag) GetValueFloat32() (float32, error) { if f.Type != Float32Type { return 0.0, fmt.Errorf("ERROR : Flag(%s) is not a Float32Type flag", f.symbol()) } float, err := strconv.ParseFloat(f.Arg, 32) if err != nil { return 0.0, err } return float32(float), nil } func (f *ArgFlag) GetValueFloat64() (float64, error) { if f.Type != Float64Type { return 0.0, fmt.Errorf("ERROR : Flag(%s) is not a Float64Type flag", f.symbol()) } return strconv.ParseFloat(f.Arg, 64) } func (f *ArgFlag) GetValueBool() (bool, error) { if f.Type != BoolType { return false, fmt.Errorf("ERROR : Flag(%s) is not a BoolType flag", f.symbol()) } _, err := f.GetIndex() if err != nil { return false, nil } else { return true, nil } } type CheckFunc func(string) (bool,error) func (f *ArgFlag) doCheck(arg string, check CheckFunc, error_string string) error { is_true, err := check(arg) if err != nil { return err } if ! is_true { return fmt.Errorf(error_string, f.symbol()) } return nil } func (f *ArgFlag) CheckArg(args []string) error { // Just checking if the argument provided to this flag is a valid one based on the ArgType f.Args = args if f.Type == NoneType { return fmt.Errorf("ArgFlag(%s) : ERROR : Flag not configured with a type", f.symbol()) } if len(args) < 2 { return fmt.Errorf("ArgFlag(%s) : ERROR : Not enough arguments", f.Name) } arg := args[1] switch f.Type { case StringType: is_flag, err := isFlag(arg) if err != nil { return err } if is_flag { return fmt.Errorf("Flag(%s) : ERROR : Argument is a flag", f.symbol()) } case IntType: err := f.doCheck(arg, isInt, "Flag(%s) : ERROR : Argument is not a valid number") if err != nil { return err } case Float32Type, Float64Type: err := f.doCheck(arg, isFloat, "Flag(%s) : ERROR : Argument is not a valid float") if err != nil { return err } } f.Arg = arg return nil } func (f *ArgFlag) Check() error { if f.Name == "" { return errors.New("ERROR : Flag was not configured with Name") } if f.Type == NoneType { return fmt.Errorf("ArgFlag(%s) : ERROR : No type has been set", f.Name) } if f.Description == "" { return fmt.Errorf("ArgFlag(%s) : ERROR : No Description has been set", f.Name) } if f.Short == "" && f.Long == "" { return fmt.Errorf("ArgFlag(%s) : ERROR : No Short or Long flags were provided", f.Name) } return nil }