diff --git a/go/clago/command.go b/go/clago/command.go new file mode 100644 index 00000000..f3db0db3 --- /dev/null +++ b/go/clago/command.go @@ -0,0 +1,9 @@ +package clago + +import ( +) + +type Command struct { + Name string + options []Option +} diff --git a/go/clago/command_test.go b/go/clago/command_test.go new file mode 100644 index 00000000..5e054c3a --- /dev/null +++ b/go/clago/command_test.go @@ -0,0 +1,10 @@ +package clago + +import ( + //"testing" +) + +//func TestFun(t *testing.T) { + //c := Command{Name:"example"} + //t.Errorf("Option: %v\n", c) +//} diff --git a/go/clago/option.go b/go/clago/option.go new file mode 100644 index 00000000..b2278441 --- /dev/null +++ b/go/clago/option.go @@ -0,0 +1,45 @@ +package clago + +import ( + "github.com/Sirupsen/logrus" +) + +var log = logrus.New() + +func init() { + log.Formatter = new(logrus.JSONFormatter) + log.Level = logrus.Debug +} + +type Validator func(interface{}) error +type Option struct { + Name string + Description string + Parser Parser + + validators []Validator + value interface{} +} + +func (o *Option) Set(str string) { + logger := log.WithFields(logrus.Fields{"option": o.Name, "value": str}) + var err error + + logger.Debug("Parsing") + o.value, err = o.Parser.Parse(str) + if err != nil { panic("parse failure") } + logger.WithFields(logrus.Fields{"parsed": o.value}).Debug("Parsed") + + logger.Debug("Validating") + for _, validator := range o.validators { + if err = validator(o.value); err != nil { panic("validate failure") } + } +} + +func (o *Option) Value() interface{} { + return o.value +} + +func (o *Option) AddValidation(v Validator) { + o.validators = append(o.validators, v) +} diff --git a/go/clago/option_parser.go b/go/clago/option_parser.go new file mode 100644 index 00000000..2a1c8c15 --- /dev/null +++ b/go/clago/option_parser.go @@ -0,0 +1,70 @@ +package clago + +import ( + "strconv" +) + +type Parser int +const ( + String Parser = iota // default parser + Bool + Uint8 + Uint16 + Uint32 + Uint64 + Int8 + Int16 + Int32 + Int64 + Float32 + Float64 + + // Not really sure this is needed yet? ;) + //Complex64 + //Complex128 +) + +func (p Parser) Parse(value string) (interface{}, error) { + switch p { + case Bool: + switch value { + case "true", "yes", "1": return true, nil + default: return false, nil + } + case Uint8: + conv, err := strconv.ParseUint(value, 0, 8) + return uint8(conv), err + case Uint16: + conv, err := strconv.ParseUint(value, 0, 16) + return uint16(conv), err + case Uint32: + conv, err := strconv.ParseUint(value, 0, 32) + return uint32(conv), err + case Uint64: + conv, err := strconv.ParseUint(value, 0, 64) + return uint64(conv), err + case Int8: + conv, err := strconv.ParseInt(value, 0, 8) + return int8(conv), err + case Int16: + conv, err := strconv.ParseInt(value, 0, 16) + return int16(conv), err + case Int32: + conv, err := strconv.ParseInt(value, 0, 32) + return int32(conv), err + case Int64: + conv, err := strconv.ParseInt(value, 0, 64) + return int64(conv), err + case Float32: + conv, err := strconv.ParseFloat(value, 32) + return float32(conv), err + case Float64: + conv, err := strconv.ParseFloat(value, 64) + return float64(conv), err + //case Complex64: + //case Complex128: + case String: + return value, nil + } + return nil, nil +} diff --git a/go/clago/option_test.go b/go/clago/option_test.go new file mode 100644 index 00000000..5fd25eb4 --- /dev/null +++ b/go/clago/option_test.go @@ -0,0 +1,87 @@ +package clago + +import ( + "testing" + //"reflect" +) + +func TestDefaultParser(t *testing.T) { + p := String + str := "hello" + v, err := p.Parse(str) + if err != nil { + t.Errorf("String failed to parse") + } + if str != v { + t.Errorf("Strings didn't match") + } +} + +func TestNumberParsers(t *testing.T) { + parsers := [...]Parser{ Uint8, Uint16, Uint32, Uint64, Int8, Int16, Int32, Int64, Float32, Float64 } + + for _, p := range parsers { + testSpecificParser(t, p) + } +} + +func testSpecificParser(t *testing.T, p Parser) { + v, err := p.Parse("100") + if err != nil { + t.Errorf("'100' failed to parse") + } + + var ok bool + var equal bool + switch p { + case Uint8: + var i uint8 + i, ok = v.(uint8) + equal = i == uint8(100) + case Uint16: + var i uint16 + i, ok = v.(uint16) + equal = i == uint16(100) + case Uint32: + var i uint32 + i, ok = v.(uint32) + equal = i == uint32(100) + case Uint64: + var i uint64 + i, ok = v.(uint64) + equal = i == uint64(100) + case Int8: + var i int8 + i, ok = v.(int8) + equal = i == int8(100) + case Int16: + var i int16 + i, ok = v.(int16) + equal = i == int16(100) + case Int32: + var i int32 + i, ok = v.(int32) + equal = i == int32(100) + case Int64: + var i int64 + i, ok = v.(int64) + equal = i == int64(100) + case Float32: + var i float32 + i, ok = v.(float32) + equal = i == float32(100) + case Float64: + var i float64 + i, ok = v.(float64) + equal = i == float64(100) + case String: + ok = true + equal = v == "100" + } + if !ok { + t.Errorf("Parse %#v expected to return correct type. Got %t", p, v) + } + if !equal { + t.Errorf("Expected %s == %s", v, "100") + } +}