Browse Source

separate options

pull/2/head
andrey1s 4 years ago
parent
commit
1c7e9623ce
  1. 5
      command_test.go
  2. 74
      descriptor/txt.go
  3. 4
      example/pkg/command/args.go
  4. 2
      example/pkg/command/create_user.go
  5. 2
      example/pkg/command/hello.go
  6. 5
      example/pkg/command/long.go
  7. 9
      help.go
  8. 23
      input/argument/argument.go
  9. 18
      input/argument/option.go
  10. 21
      input/argv/input.go
  11. 16
      input/array/input.go
  12. 39
      input/definition.go
  13. 76
      input/flag.go
  14. 97
      input/flag/flag.go
  15. 26
      input/flag/flag_string.go
  16. 14
      input/input.go
  17. 52
      input/option.go
  18. 36
      input/option/helpers.go
  19. 86
      input/option/option.go
  20. 6
      input/validator/enum.go
  21. 2
      input/validator/enum_test.go
  22. 0
      input/validator/error.go
  23. 49
      input/validator/not_blank.go
  24. 44
      input/validator/not_blank_test.go
  25. 15
      input/validator/valid.go
  26. 6
      input/validator/valid_test.go
  27. 58
      input/value.go
  28. 4
      input/value/any.go
  29. 6
      input/value/bool.go
  30. 6
      input/value/duration.go
  31. 5
      input/value/empty.go
  32. 6
      input/value/float64.go
  33. 6
      input/value/int.go
  34. 6
      input/value/int64.go
  35. 15
      input/value/read.go
  36. 4
      input/value/string.go
  37. 6
      input/value/time.go
  38. 6
      input/value/uint.go
  39. 6
      input/value/uint64.go
  40. 112
      input/value/value.go
  41. 8
      input/wrap/input.go
  42. 7
      list.go
  43. 15
      validator/valid.go

5
command_test.go

@ -10,6 +10,7 @@ import (
"gitoa.ru/go-4devs/console" "gitoa.ru/go-4devs/console"
"gitoa.ru/go-4devs/console/example/pkg/command" "gitoa.ru/go-4devs/console/example/pkg/command"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input"
"gitoa.ru/go-4devs/console/input/argument"
"gitoa.ru/go-4devs/console/input/array" "gitoa.ru/go-4devs/console/input/array"
"gitoa.ru/go-4devs/console/input/option" "gitoa.ru/go-4devs/console/input/option"
"gitoa.ru/go-4devs/console/output" "gitoa.ru/go-4devs/console/output"
@ -39,10 +40,10 @@ func Command() *console.Command {
Configure: func(ctx context.Context, def *input.Definition) error { Configure: func(ctx context.Context, def *input.Definition) error {
def. def.
SetArguments( SetArguments(
input.NewArgument("test_argument", "test argument"), argument.New("test_argument", "test argument"),
). ).
SetOptions( SetOptions(
input.NewOption("string", "array string", option.Array), option.New("string", "array string", option.Array),
option.Bool("bool", "test bool option"), option.Bool("bool", "test bool option"),
option.Duration("duration", "test duration with default", option.Default(time.Second)), option.Duration("duration", "test duration with default", option.Default(time.Second)),
) )

74
descriptor/txt.go

@ -10,6 +10,8 @@ import (
"time" "time"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input"
"gitoa.ru/go-4devs/console/input/flag"
"gitoa.ru/go-4devs/console/input/value"
"gitoa.ru/go-4devs/console/output" "gitoa.ru/go-4devs/console/output"
) )
@ -76,36 +78,36 @@ func (t *txt) Commands(ctx context.Context, out output.Output, cmds Commands) er
return nil return nil
} }
func txtDefaultArray(val input.Value, flag input.Flag) string { func txtDefaultArray(v value.Value, f flag.Flag) string {
st := val.Strings() st := v.Strings()
switch { switch {
case flag.IsInt(): case f.IsInt():
for _, i := range val.Ints() { for _, i := range v.Ints() {
st = append(st, strconv.Itoa(i)) st = append(st, strconv.Itoa(i))
} }
case flag.IsInt64(): case f.IsInt64():
for _, i := range val.Int64s() { for _, i := range v.Int64s() {
st = append(st, strconv.FormatInt(i, 10)) st = append(st, strconv.FormatInt(i, 10))
} }
case flag.IsUint(): case f.IsUint():
for _, u := range val.Uints() { for _, u := range v.Uints() {
st = append(st, strconv.FormatUint(uint64(u), 10)) st = append(st, strconv.FormatUint(uint64(u), 10))
} }
case flag.IsUint64(): case f.IsUint64():
for _, u := range val.Uint64s() { for _, u := range v.Uint64s() {
st = append(st, strconv.FormatUint(u, 10)) st = append(st, strconv.FormatUint(u, 10))
} }
case flag.IsFloat64(): case f.IsFloat64():
for _, f := range val.Float64s() { for _, f := range v.Float64s() {
st = append(st, strconv.FormatFloat(f, 'g', -1, 64)) st = append(st, strconv.FormatFloat(f, 'g', -1, 64))
} }
case flag.IsDuration(): case f.IsDuration():
for _, d := range val.Durations() { for _, d := range v.Durations() {
st = append(st, d.String()) st = append(st, d.String())
} }
case flag.IsTime(): case f.IsTime():
for _, d := range val.Times() { for _, d := range v.Times() {
st = append(st, d.Format(time.RFC3339)) st = append(st, d.Format(time.RFC3339))
} }
} }
@ -113,32 +115,32 @@ func txtDefaultArray(val input.Value, flag input.Flag) string {
return strings.Join(st, ",") return strings.Join(st, ",")
} }
func txtDefault(val input.Value, flag input.Flag) []byte { func txtDefault(v value.Value, f flag.Flag) []byte {
var buf bytes.Buffer var buf bytes.Buffer
buf.WriteString("<comment> [default: ") buf.WriteString("<comment> [default: ")
switch { switch {
case flag.IsArray(): case f.IsArray():
buf.WriteString(txtDefaultArray(val, flag)) buf.WriteString(txtDefaultArray(v, f))
case flag.IsInt(): case f.IsInt():
buf.WriteString(strconv.Itoa(val.Int())) buf.WriteString(strconv.Itoa(v.Int()))
case flag.IsInt64(): case f.IsInt64():
buf.WriteString(strconv.FormatInt(val.Int64(), 10)) buf.WriteString(strconv.FormatInt(v.Int64(), 10))
case flag.IsUint(): case f.IsUint():
buf.WriteString(strconv.FormatUint(uint64(val.Uint()), 10)) buf.WriteString(strconv.FormatUint(uint64(v.Uint()), 10))
case flag.IsUint64(): case f.IsUint64():
buf.WriteString(strconv.FormatUint(val.Uint64(), 10)) buf.WriteString(strconv.FormatUint(v.Uint64(), 10))
case flag.IsFloat64(): case f.IsFloat64():
buf.WriteString(strconv.FormatFloat(val.Float64(), 'g', -1, 64)) buf.WriteString(strconv.FormatFloat(v.Float64(), 'g', -1, 64))
case flag.IsDuration(): case f.IsDuration():
buf.WriteString(val.Duration().String()) buf.WriteString(v.Duration().String())
case flag.IsTime(): case f.IsTime():
buf.WriteString(val.Time().Format(time.RFC3339)) buf.WriteString(v.Time().Format(time.RFC3339))
case flag.IsAny(): case f.IsAny():
buf.WriteString(fmt.Sprint(val.Any())) buf.WriteString(fmt.Sprint(v.Any()))
default: default:
buf.WriteString(val.String()) buf.WriteString(v.String())
} }
buf.WriteString("]</comment>") buf.WriteString("]</comment>")

4
example/pkg/command/args.go

@ -16,8 +16,8 @@ func Args() *console.Command {
Configure: func(ctx context.Context, def *input.Definition) error { Configure: func(ctx context.Context, def *input.Definition) error {
def.SetOptions( def.SetOptions(
option.Bool("foo", "foo option", option.Short("f")), option.Bool("foo", "foo option", option.Short("f")),
input.NewOption("bar", "required bar option", option.Required, option.Short("b")), option.New("bar", "required bar option", option.Required, option.Short("b")),
input.NewOption("cat", "cat option", option.Short("c")), option.New("cat", "cat option", option.Short("c")),
) )
return nil return nil

2
example/pkg/command/create_user.go

@ -15,7 +15,7 @@ func CreateUser(required bool) *console.Command {
Description: "Creates a new user.", Description: "Creates a new user.",
Help: "This command allows you to create a user...", Help: "This command allows you to create a user...",
Configure: func(ctx context.Context, cfg *input.Definition) error { Configure: func(ctx context.Context, cfg *input.Definition) error {
var opts []func(*input.Argument) var opts []func(*argument.Argument)
if required { if required {
opts = append(opts, argument.Required) opts = append(opts, argument.Required)
} }

2
example/pkg/command/hello.go

@ -25,7 +25,7 @@ func Hello() *console.Command {
}, },
Configure: func(_ context.Context, def *input.Definition) error { Configure: func(_ context.Context, def *input.Definition) error {
def.SetArguments( def.SetArguments(
input.NewArgument("name", "Same name", argument.Default("World")), argument.New("name", "Same name", argument.Default("World")),
) )
return nil return nil

5
example/pkg/command/long.go

@ -6,9 +6,10 @@ import (
"gitoa.ru/go-4devs/console" "gitoa.ru/go-4devs/console"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input"
"gitoa.ru/go-4devs/console/input/flag"
"gitoa.ru/go-4devs/console/input/option" "gitoa.ru/go-4devs/console/input/option"
"gitoa.ru/go-4devs/console/input/validator"
"gitoa.ru/go-4devs/console/output" "gitoa.ru/go-4devs/console/output"
"gitoa.ru/go-4devs/console/validator"
) )
const defaultTimeout = time.Second * 30 const defaultTimeout = time.Second * 30
@ -41,7 +42,7 @@ func Long() *console.Command {
def.SetOptions(option.Duration("timeout", "set duration run command", def.SetOptions(option.Duration("timeout", "set duration run command",
option.Default(defaultTimeout), option.Default(defaultTimeout),
option.Short("t"), option.Short("t"),
option.Valid(validator.NotBlank(input.ValueDuration)), option.Valid(validator.NotBlank(flag.Duration)),
)) ))
return nil return nil

9
help.go

@ -9,9 +9,10 @@ import (
"gitoa.ru/go-4devs/console/descriptor" "gitoa.ru/go-4devs/console/descriptor"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input"
"gitoa.ru/go-4devs/console/input/argument" "gitoa.ru/go-4devs/console/input/argument"
"gitoa.ru/go-4devs/console/input/flag"
"gitoa.ru/go-4devs/console/input/option" "gitoa.ru/go-4devs/console/input/option"
"gitoa.ru/go-4devs/console/input/validator"
"gitoa.ru/go-4devs/console/output" "gitoa.ru/go-4devs/console/output"
"gitoa.ru/go-4devs/console/validator"
) )
//nolint: gochecknoinits //nolint: gochecknoinits
@ -73,14 +74,14 @@ To display the list of available commands, please use the <info>list</info> comm
formats := descriptor.Descriptors() formats := descriptor.Descriptors()
config. config.
SetArguments( SetArguments(
input.NewArgument(HelpArgumentCommandName, "The command name", argument.Default("help")), argument.New(HelpArgumentCommandName, "The command name", argument.Default("help")),
). ).
SetOptions( SetOptions(
input.NewOption(helpOptFormat, fmt.Sprintf("The output format (%s)", strings.Join(formats, ", ")), option.New(helpOptFormat, fmt.Sprintf("The output format (%s)", strings.Join(formats, ", ")),
option.Required, option.Required,
option.Default(formats[0]), option.Default(formats[0]),
option.Valid( option.Valid(
validator.NotBlank(input.ValueString), validator.NotBlank(flag.String),
validator.Enum(formats...), validator.Enum(formats...),
), ),
), ),

23
input/argument.go → input/argument/argument.go

@ -1,6 +1,11 @@
package input package argument
func NewArgument(name, description string, opts ...func(*Argument)) Argument { import (
"gitoa.ru/go-4devs/console/input/flag"
"gitoa.ru/go-4devs/console/input/value"
)
func New(name, description string, opts ...func(*Argument)) Argument {
a := Argument{ a := Argument{
Name: name, Name: name,
Description: description, Description: description,
@ -16,9 +21,9 @@ func NewArgument(name, description string, opts ...func(*Argument)) Argument {
type Argument struct { type Argument struct {
Name string Name string
Description string Description string
Default Value Default value.Value
Flag Flag Flag flag.Flag
Valid []func(Value) error Valid []func(value.Value) error
} }
func (a Argument) HasDefault() bool { func (a Argument) HasDefault() bool {
@ -37,12 +42,16 @@ func (a Argument) IsArray() bool {
return a.Flag.IsArray() return a.Flag.IsArray()
} }
func (a Argument) Validate(v Value) error { func (a Argument) Validate(v value.Value) error {
for _, valid := range a.Valid { for _, valid := range a.Valid {
if err := valid(v); err != nil { if err := valid(v); err != nil {
return ErrorArgument(a.Name, err) return Error(a.Name, err)
} }
} }
return nil return nil
} }
func Error(name string, err error) error {
return err
}

18
input/argument/option.go

@ -1,26 +1,26 @@
package argument package argument
import ( import (
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input/flag"
"gitoa.ru/go-4devs/console/input/value" "gitoa.ru/go-4devs/console/input/value"
) )
func Required(a *input.Argument) { func Required(a *Argument) {
a.Flag |= input.ValueRequired a.Flag |= flag.Required
} }
func Default(v interface{}) func(*input.Argument) { func Default(v interface{}) func(*Argument) {
return func(a *input.Argument) { return func(a *Argument) {
a.Default = value.New(v) a.Default = value.New(v)
} }
} }
func Flag(flag input.Flag) func(*input.Argument) { func Flag(flag flag.Flag) func(*Argument) {
return func(a *input.Argument) { return func(a *Argument) {
a.Flag = flag a.Flag = flag
} }
} }
func Array(a *input.Argument) { func Array(a *Argument) {
a.Flag |= input.ValueArray a.Flag |= flag.Array
} }

21
input/argv/input.go

@ -7,6 +7,7 @@ import (
"sync" "sync"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input"
"gitoa.ru/go-4devs/console/input/option"
"gitoa.ru/go-4devs/console/input/value" "gitoa.ru/go-4devs/console/input/value"
"gitoa.ru/go-4devs/console/input/wrap" "gitoa.ru/go-4devs/console/input/wrap"
) )
@ -24,8 +25,8 @@ func WithErrorHandle(h func(error) error) func(*Input) {
func New(args []string, opts ...func(*Input)) *wrap.Input { func New(args []string, opts ...func(*Input)) *wrap.Input {
i := &Input{ i := &Input{
args: args, args: args,
arguments: make(map[string]input.AppendValue), arguments: make(map[string]value.AppendValue),
options: make(map[string]input.AppendValue), options: make(map[string]value.AppendValue),
errorHandle: func(err error) error { errorHandle: func(err error) error {
return err return err
}, },
@ -40,13 +41,13 @@ func New(args []string, opts ...func(*Input)) *wrap.Input {
type Input struct { type Input struct {
args []string args []string
arguments map[string]input.AppendValue arguments map[string]value.AppendValue
options map[string]input.AppendValue options map[string]value.AppendValue
mu sync.RWMutex mu sync.RWMutex
errorHandle func(error) error errorHandle func(error) error
} }
func (i *Input) ReadOption(ctx context.Context, name string) (input.Value, error) { func (i *Input) ReadOption(ctx context.Context, name string) (value.Value, error) {
if v, ok := i.options[name]; ok { if v, ok := i.options[name]; ok {
return v, nil return v, nil
} }
@ -54,14 +55,14 @@ func (i *Input) ReadOption(ctx context.Context, name string) (input.Value, error
return nil, input.ErrNotFound return nil, input.ErrNotFound
} }
func (i *Input) SetOption(name string, val input.Value) { func (i *Input) SetOption(name string, val value.Value) {
i.mu.Lock() i.mu.Lock()
defer i.mu.Unlock() defer i.mu.Unlock()
i.options[name] = &value.Read{Value: val} i.options[name] = &value.Read{Value: val}
} }
func (i *Input) ReadArgument(ctx context.Context, name string) (input.Value, error) { func (i *Input) ReadArgument(ctx context.Context, name string) (value.Value, error) {
if v, ok := i.arguments[name]; ok { if v, ok := i.arguments[name]; ok {
return v, nil return v, nil
} }
@ -69,7 +70,7 @@ func (i *Input) ReadArgument(ctx context.Context, name string) (input.Value, err
return nil, input.ErrNotFound return nil, input.ErrNotFound
} }
func (i *Input) SetArgument(name string, val input.Value) { func (i *Input) SetArgument(name string, val value.Value) {
i.mu.Lock() i.mu.Lock()
defer i.mu.Unlock() defer i.mu.Unlock()
@ -129,11 +130,11 @@ func (i *Input) parseLongOption(arg string, def *input.Definition) error {
return i.appendOption(name, value, opt) return i.appendOption(name, value, opt)
} }
func (i *Input) appendOption(name string, data *string, opt input.Option) error { func (i *Input) appendOption(name string, data *string, opt option.Option) error {
v, ok := i.options[name] v, ok := i.options[name]
if ok && !opt.IsArray() { if ok && !opt.IsArray() {
return fmt.Errorf("%w: got: array, expect: %s", input.ErrUnexpectedType, input.Type(opt.Flag)) return fmt.Errorf("%w: got: array, expect: %s", input.ErrUnexpectedType, opt.Flag.Type())
} }
var val string var val string

16
input/array/input.go

@ -25,8 +25,8 @@ func Option(name string, v interface{}) func(*Input) {
func New(opts ...func(*Input)) *wrap.Input { func New(opts ...func(*Input)) *wrap.Input {
i := &Input{ i := &Input{
args: make(map[string]input.Value), args: make(map[string]value.Value),
opt: make(map[string]input.Value), opt: make(map[string]value.Value),
} }
for _, opt := range opts { for _, opt := range opts {
@ -37,12 +37,12 @@ func New(opts ...func(*Input)) *wrap.Input {
} }
type Input struct { type Input struct {
args map[string]input.Value args map[string]value.Value
opt map[string]input.Value opt map[string]value.Value
mu sync.Mutex mu sync.Mutex
} }
func (i *Input) ReadOption(_ context.Context, name string) (input.Value, error) { func (i *Input) ReadOption(_ context.Context, name string) (value.Value, error) {
if o, has := i.opt[name]; has { if o, has := i.opt[name]; has {
return o, nil return o, nil
} }
@ -56,13 +56,13 @@ func (i *Input) HasOption(name string) bool {
return has return has
} }
func (i *Input) SetOption(name string, val input.Value) { func (i *Input) SetOption(name string, val value.Value) {
i.mu.Lock() i.mu.Lock()
i.opt[name] = val i.opt[name] = val
i.mu.Unlock() i.mu.Unlock()
} }
func (i *Input) ReadArgument(_ context.Context, name string) (input.Value, error) { func (i *Input) ReadArgument(_ context.Context, name string) (value.Value, error) {
if a, has := i.args[name]; has { if a, has := i.args[name]; has {
return a, nil return a, nil
} }
@ -76,7 +76,7 @@ func (i *Input) HasArgument(name string) bool {
return has return has
} }
func (i *Input) SetArgument(name string, val input.Value) { func (i *Input) SetArgument(name string, val value.Value) {
i.mu.Lock() i.mu.Lock()
i.args[name] = val i.args[name] = val
i.mu.Unlock() i.mu.Unlock()

39
input/definition.go

@ -1,17 +1,22 @@
package input package input
import (
"gitoa.ru/go-4devs/console/input/argument"
"gitoa.ru/go-4devs/console/input/option"
)
func NewDefinition() *Definition { func NewDefinition() *Definition {
return &Definition{ return &Definition{
options: make(map[string]Option), options: make(map[string]option.Option),
args: make(map[string]Argument), args: make(map[string]argument.Argument),
short: make(map[string]string), short: make(map[string]string),
} }
} }
type Definition struct { type Definition struct {
options map[string]Option options map[string]option.Option
posOpt []string posOpt []string
args map[string]Argument args map[string]argument.Argument
posArgs []string posArgs []string
short map[string]string short map[string]string
} }
@ -24,11 +29,11 @@ func (d *Definition) Arguments() []string {
return d.posArgs return d.posArgs
} }
func (d *Definition) SetOption(name, description string, opts ...func(*Option)) *Definition { func (d *Definition) SetOption(name, description string, opts ...func(*option.Option)) *Definition {
return d.SetOptions(NewOption(name, description, opts...)) return d.SetOptions(option.New(name, description, opts...))
} }
func (d *Definition) SetOptions(opts ...Option) *Definition { func (d *Definition) SetOptions(opts ...option.Option) *Definition {
for _, opt := range opts { for _, opt := range opts {
if _, has := d.options[opt.Name]; !has { if _, has := d.options[opt.Name]; !has {
d.posOpt = append([]string{opt.Name}, d.posOpt...) d.posOpt = append([]string{opt.Name}, d.posOpt...)
@ -43,11 +48,11 @@ func (d *Definition) SetOptions(opts ...Option) *Definition {
return d return d
} }
func (d *Definition) SetArgument(name, description string, opts ...func(*Argument)) *Definition { func (d *Definition) SetArgument(name, description string, opts ...func(*argument.Argument)) *Definition {
return d.SetArguments(NewArgument(name, description, opts...)) return d.SetArguments(argument.New(name, description, opts...))
} }
func (d *Definition) SetArguments(args ...Argument) *Definition { func (d *Definition) SetArguments(args ...argument.Argument) *Definition {
for _, arg := range args { for _, arg := range args {
if _, ok := d.args[arg.Name]; !ok { if _, ok := d.args[arg.Name]; !ok {
d.posArgs = append(d.posArgs, arg.Name) d.posArgs = append(d.posArgs, arg.Name)
@ -59,9 +64,9 @@ func (d *Definition) SetArguments(args ...Argument) *Definition {
return d return d
} }
func (d *Definition) Argument(pos int) (Argument, error) { func (d *Definition) Argument(pos int) (argument.Argument, error) {
if len(d.posArgs) == 0 { if len(d.posArgs) == 0 {
return Argument{}, ErrNoArgs return argument.Argument{}, ErrNoArgs
} }
lastPos := len(d.posArgs) - 1 lastPos := len(d.posArgs) - 1
@ -71,25 +76,25 @@ func (d *Definition) Argument(pos int) (Argument, error) {
return arg, nil return arg, nil
} }
return Argument{}, ErrToManyArgs return argument.Argument{}, ErrToManyArgs
} }
return d.args[d.posArgs[pos]], nil return d.args[d.posArgs[pos]], nil
} }
func (d *Definition) ShortOption(short string) (Option, error) { func (d *Definition) ShortOption(short string) (option.Option, error) {
name, ok := d.short[short] name, ok := d.short[short]
if !ok { if !ok {
return Option{}, ErrNotFound return option.Option{}, ErrNotFound
} }
return d.Option(name) return d.Option(name)
} }
func (d *Definition) Option(name string) (Option, error) { func (d *Definition) Option(name string) (option.Option, error) {
if opt, ok := d.options[name]; ok { if opt, ok := d.options[name]; ok {
return opt, nil return opt, nil
} }
return Option{}, ErrNotFound return option.Option{}, ErrNotFound
} }

76
input/flag.go

@ -1,76 +0,0 @@
package input
//go:generate stringer -type=Flag -linecomment
type Flag int
const (
ValueString Flag = 0 // string
ValueRequired Flag = 1 << iota // required
ValueArray // array
ValueInt // int
ValueInt64 // int64
ValueUint // uint
ValueUint64 // uint64
ValueFloat64 // float64
ValueBool // bool
ValueDuration // duration
ValueTime // time
ValueAny // any
)
func (f Flag) Type() Flag {
return Type(f)
}
func (f Flag) With(v Flag) Flag {
return f | v
}
func (f Flag) IsString() bool {
return f|ValueRequired|ValueArray^ValueRequired^ValueArray == 0
}
func (f Flag) IsRequired() bool {
return f&ValueRequired > 0
}
func (f Flag) IsArray() bool {
return f&ValueArray > 0
}
func (f Flag) IsInt() bool {
return f&ValueInt > 0
}
func (f Flag) IsInt64() bool {
return f&ValueInt64 > 0
}
func (f Flag) IsUint() bool {
return f&ValueUint > 0
}
func (f Flag) IsUint64() bool {
return f&ValueUint64 > 0
}
func (f Flag) IsFloat64() bool {
return f&ValueFloat64 > 0
}
func (f Flag) IsBool() bool {
return f&ValueBool > 0
}
func (f Flag) IsDuration() bool {
return f&ValueDuration > 0
}
func (f Flag) IsTime() bool {
return f&ValueTime > 0
}
func (f Flag) IsAny() bool {
return f&ValueAny > 0
}

97
input/flag/flag.go

@ -0,0 +1,97 @@
package flag
//go:generate stringer -type=Flag -linecomment
type Flag int
const (
String Flag = 0 // string
Required Flag = 1 << iota // required
Array // array
Int // int
Int64 // int64
Uint // uint
Uint64 // uint64
Float64 // float64
Bool // bool
Duration // duration
Time // time
Any // any
)
func (f Flag) With(v Flag) Flag {
return f | v
}
func (f Flag) IsString() bool {
return f|Required|Array^Required^Array == 0
}
func (f Flag) IsRequired() bool {
return f&Required > 0
}
func (f Flag) IsArray() bool {
return f&Array > 0
}
func (f Flag) IsInt() bool {
return f&Int > 0
}
func (f Flag) IsInt64() bool {
return f&Int64 > 0
}
func (f Flag) IsUint() bool {
return f&Uint > 0
}
func (f Flag) IsUint64() bool {
return f&Uint64 > 0
}
func (f Flag) IsFloat64() bool {
return f&Float64 > 0
}
func (f Flag) IsBool() bool {
return f&Bool > 0
}
func (f Flag) IsDuration() bool {
return f&Duration > 0
}
func (f Flag) IsTime() bool {
return f&Time > 0
}
func (f Flag) IsAny() bool {
return f&Any > 0
}
func (f Flag) Type() Flag {
switch {
case f.IsInt():
return Int
case f.IsInt64():
return Int64
case f.IsUint():
return Uint
case f.IsUint64():
return Uint64
case f.IsFloat64():
return Float64
case f.IsBool():
return Bool
case f.IsDuration():
return Duration
case f.IsTime():
return Time
case f.IsAny():
return Any
default:
return String
}
}

26
input/flag_string.go → input/flag/flag_string.go

@ -1,6 +1,6 @@
// Code generated by "stringer -type=Flag -linecomment"; DO NOT EDIT. // Code generated by "stringer -type=Flag -linecomment"; DO NOT EDIT.
package input package flag
import "strconv" import "strconv"
@ -8,18 +8,18 @@ func _() {
// An "invalid array index" compiler error signifies that the constant values have changed. // An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again. // Re-run the stringer command to generate them again.
var x [1]struct{} var x [1]struct{}
_ = x[ValueString-0] _ = x[String-0]
_ = x[ValueRequired-2] _ = x[Required-2]
_ = x[ValueArray-4] _ = x[Array-4]
_ = x[ValueInt-8] _ = x[Int-8]
_ = x[ValueInt64-16] _ = x[Int64-16]
_ = x[ValueUint-32] _ = x[Uint-32]
_ = x[ValueUint64-64] _ = x[Uint64-64]
_ = x[ValueFloat64-128] _ = x[Float64-128]
_ = x[ValueBool-256] _ = x[Bool-256]
_ = x[ValueDuration-512] _ = x[Duration-512]
_ = x[ValueTime-1024] _ = x[Time-1024]
_ = x[ValueAny-2048] _ = x[Any-2048]
} }
const _Flag_name = "stringrequiredarrayintint64uintuint64float64booldurationtimeany" const _Flag_name = "stringrequiredarrayintint64uintuint64float64booldurationtimeany"

14
input/input.go

@ -2,20 +2,22 @@ package input
import ( import (
"context" "context"
"gitoa.ru/go-4devs/console/input/value"
) )
type ReadInput interface { type ReadInput interface {
Bind(ctx context.Context, def *Definition) error Bind(ctx context.Context, def *Definition) error
ReadOption(ctx context.Context, name string) (Value, error) ReadOption(ctx context.Context, name string) (value.Value, error)
SetOption(name string, value Value) SetOption(name string, v value.Value)
ReadArgument(ctx context.Context, name string) (Value, error) ReadArgument(ctx context.Context, name string) (value.Value, error)
SetArgument(name string, value Value) SetArgument(name string, v value.Value)
} }
type Input interface { type Input interface {
Option(ctx context.Context, name string) Value Option(ctx context.Context, name string) value.Value
Argument(ctx context.Context, name string) Value Argument(ctx context.Context, name string) value.Value
ReadInput ReadInput
} }

52
input/option.go

@ -1,53 +1 @@
package input package input
func NewOption(name, description string, opts ...func(*Option)) Option {
o := Option{
Name: name,
Description: description,
}
for _, opt := range opts {
opt(&o)
}
return o
}
type Option struct {
Name string
Description string
Short string
Flag Flag
Default Value
Valid []func(Value) error
}
func (o Option) HasShort() bool {
return len(o.Short) == 1
}
func (o Option) HasDefault() bool {
return o.Default != nil
}
func (o Option) IsBool() bool {
return o.Flag.IsBool()
}
func (o Option) IsArray() bool {
return o.Flag.IsArray()
}
func (o Option) IsRequired() bool {
return o.Flag.IsRequired()
}
func (o Option) Validate(v Value) error {
for _, valid := range o.Valid {
if err := valid(v); err != nil {
return ErrorOption(o.Name, err)
}
}
return nil
}

36
input/option/helpers.go

@ -1,35 +1,37 @@
package option package option
import "gitoa.ru/go-4devs/console/input" import (
"gitoa.ru/go-4devs/console/input/flag"
)
func Bool(name, description string, opts ...func(*input.Option)) input.Option { func Bool(name, description string, opts ...func(*Option)) Option {
return input.NewOption(name, description, append(opts, Value(input.ValueBool))...) return New(name, description, append(opts, Value(flag.Bool))...)
} }
func Duration(name, description string, opts ...func(*input.Option)) input.Option { func Duration(name, description string, opts ...func(*Option)) Option {
return input.NewOption(name, description, append(opts, Value(input.ValueDuration))...) return New(name, description, append(opts, Value(flag.Duration))...)
} }
func Float64(name, description string, opts ...func(*input.Option)) input.Option { func Float64(name, description string, opts ...func(*Option)) Option {
return input.NewOption(name, description, append(opts, Value(input.ValueFloat64))...) return New(name, description, append(opts, Value(flag.Float64))...)
} }
func Int(name, description string, opts ...func(*input.Option)) input.Option { func Int(name, description string, opts ...func(*Option)) Option {
return input.NewOption(name, description, append(opts, Value(input.ValueInt))...) return New(name, description, append(opts, Value(flag.Int))...)
} }
func Int64(name, description string, opts ...func(*input.Option)) input.Option { func Int64(name, description string, opts ...func(*Option)) Option {
return input.NewOption(name, description, append(opts, Value(input.ValueInt64))...) return New(name, description, append(opts, Value(flag.Int64))...)
} }
func Time(name, description string, opts ...func(*input.Option)) input.Option { func Time(name, description string, opts ...func(*Option)) Option {
return input.NewOption(name, description, append(opts, Value(input.ValueTime))...) return New(name, description, append(opts, Value(flag.Time))...)
} }
func Uint(name, description string, opts ...func(*input.Option)) input.Option { func Uint(name, description string, opts ...func(*Option)) Option {
return input.NewOption(name, description, append(opts, Value(input.ValueUint))...) return New(name, description, append(opts, Value(flag.Uint))...)
} }
func Uint64(name, descriontion string, opts ...func(*input.Option)) input.Option { func Uint64(name, descriontion string, opts ...func(*Option)) Option {
return input.NewOption(name, descriontion, append(opts, Value(input.ValueUint64))...) return New(name, descriontion, append(opts, Value(flag.Uint64))...)
} }

86
input/option/option.go

@ -1,44 +1,100 @@
package option package option
import ( import (
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input/flag"
"gitoa.ru/go-4devs/console/input/value" "gitoa.ru/go-4devs/console/input/value"
) )
func Required(o *input.Option) { func Required(o *Option) {
o.Flag |= input.ValueRequired o.Flag |= flag.Required
} }
func Default(in interface{}) func(*input.Option) { func Default(in interface{}) func(*Option) {
return func(o *input.Option) { return func(o *Option) {
o.Default = value.New(in) o.Default = value.New(in)
} }
} }
func Short(s string) func(*input.Option) { func Short(s string) func(*Option) {
return func(o *input.Option) { return func(o *Option) {
o.Short = s o.Short = s
} }
} }
func Array(o *input.Option) { func Array(o *Option) {
o.Flag |= input.ValueArray o.Flag |= flag.Array
} }
func Value(flag input.Flag) func(*input.Option) { func Value(flag flag.Flag) func(*Option) {
return func(o *input.Option) { return func(o *Option) {
o.Flag |= flag o.Flag |= flag
} }
} }
func Flag(in input.Flag) func(*input.Option) { func Flag(in flag.Flag) func(*Option) {
return func(o *input.Option) { return func(o *Option) {
o.Flag = in o.Flag = in
} }
} }
func Valid(f ...func(input.Value) error) func(*input.Option) { func Valid(f ...func(value.Value) error) func(*Option) {
return func(o *input.Option) { return func(o *Option) {
o.Valid = f o.Valid = f
} }
} }
func New(name, description string, opts ...func(*Option)) Option {
o := Option{
Name: name,
Description: description,
}
for _, opt := range opts {
opt(&o)
}
return o
}
type Option struct {
Name string
Description string
Short string
Flag flag.Flag
Default value.Value
Valid []func(value.Value) error
}
func (o Option) HasShort() bool {
return len(o.Short) == 1
}
func (o Option) HasDefault() bool {
return o.Default != nil
}
func (o Option) IsBool() bool {
return o.Flag.IsBool()
}
func (o Option) IsArray() bool {
return o.Flag.IsArray()
}
func (o Option) IsRequired() bool {
return o.Flag.IsRequired()
}
func (o Option) Validate(v value.Value) error {
for _, valid := range o.Valid {
if err := valid(v); err != nil {
return Error(o.Name, err)
}
}
return nil
}
func Error(name string, err error) error {
return err
}

6
validator/enum.go → input/validator/enum.go

@ -1,9 +1,9 @@
package validator package validator
import "gitoa.ru/go-4devs/console/input" import "gitoa.ru/go-4devs/console/input/value"
func Enum(enum ...string) func(input.Value) error { func Enum(enum ...string) func(value.Value) error {
return func(in input.Value) error { return func(in value.Value) error {
v := in.String() v := in.String()
for _, e := range enum { for _, e := range enum {
if e == v { if e == v {

2
validator/enum_test.go → input/validator/enum_test.go

@ -4,8 +4,8 @@ import (
"errors" "errors"
"testing" "testing"
"gitoa.ru/go-4devs/console/input/validator"
"gitoa.ru/go-4devs/console/input/value" "gitoa.ru/go-4devs/console/input/value"
"gitoa.ru/go-4devs/console/validator"
) )
func TestEnum(t *testing.T) { func TestEnum(t *testing.T) {

0
validator/error.go → input/validator/error.go

49
validator/not_blank.go → input/validator/not_blank.go

@ -1,32 +1,33 @@
package validator package validator
import ( import (
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input/flag"
"gitoa.ru/go-4devs/console/input/value"
) )
//nolint: gocyclo //nolint: gocyclo
func NotBlank(flag input.Flag) func(input.Value) error { func NotBlank(f flag.Flag) func(value.Value) error {
return func(in input.Value) error { return func(in value.Value) error {
switch { switch {
case flag.IsAny() && in.Any() != nil: case f.IsAny() && in.Any() != nil:
return nil return nil
case flag.IsArray(): case f.IsArray():
return arrayNotBlank(flag, in) return arrayNotBlank(f, in)
case flag.IsInt() && in.Int() != 0: case f.IsInt() && in.Int() != 0:
return nil return nil
case flag.IsInt64() && in.Int64() != 0: case f.IsInt64() && in.Int64() != 0:
return nil return nil
case flag.IsUint() && in.Uint() != 0: case f.IsUint() && in.Uint() != 0:
return nil return nil
case flag.IsUint64() && in.Uint64() != 0: case f.IsUint64() && in.Uint64() != 0:
return nil return nil
case flag.IsFloat64() && in.Float64() != 0: case f.IsFloat64() && in.Float64() != 0:
return nil return nil
case flag.IsDuration() && in.Duration() != 0: case f.IsDuration() && in.Duration() != 0:
return nil return nil
case flag.IsTime() && !in.Time().IsZero(): case f.IsTime() && !in.Time().IsZero():
return nil return nil
case flag.IsString() && len(in.String()) > 0: case f.IsString() && len(in.String()) > 0:
return nil return nil
} }
@ -35,9 +36,9 @@ func NotBlank(flag input.Flag) func(input.Value) error {
} }
//nolint: gocyclo,gocognit //nolint: gocyclo,gocognit
func arrayNotBlank(flag input.Flag, in input.Value) error { func arrayNotBlank(f flag.Flag, in value.Value) error {
switch { switch {
case flag.IsInt() && len(in.Ints()) > 0: case f.IsInt() && len(in.Ints()) > 0:
for _, i := range in.Ints() { for _, i := range in.Ints() {
if i == 0 { if i == 0 {
return ErrNotBlank return ErrNotBlank
@ -45,7 +46,7 @@ func arrayNotBlank(flag input.Flag, in input.Value) error {
} }
return nil return nil
case flag.IsInt64() && len(in.Int64s()) > 0: case f.IsInt64() && len(in.Int64s()) > 0:
for _, i := range in.Int64s() { for _, i := range in.Int64s() {
if i == 0 { if i == 0 {
return ErrNotBlank return ErrNotBlank
@ -53,7 +54,7 @@ func arrayNotBlank(flag input.Flag, in input.Value) error {
} }
return nil return nil
case flag.IsUint() && len(in.Uints()) > 0: case f.IsUint() && len(in.Uints()) > 0:
for _, u := range in.Uints() { for _, u := range in.Uints() {
if u == 0 { if u == 0 {
return ErrNotBlank return ErrNotBlank
@ -61,7 +62,7 @@ func arrayNotBlank(flag input.Flag, in input.Value) error {
} }
return nil return nil
case flag.IsUint64() && len(in.Uint64s()) > 0: case f.IsUint64() && len(in.Uint64s()) > 0:
for _, u := range in.Uint64s() { for _, u := range in.Uint64s() {
if u == 0 { if u == 0 {
return ErrNotBlank return ErrNotBlank
@ -69,7 +70,7 @@ func arrayNotBlank(flag input.Flag, in input.Value) error {
} }
return nil return nil
case flag.IsFloat64() && len(in.Float64s()) > 0: case f.IsFloat64() && len(in.Float64s()) > 0:
for _, f := range in.Float64s() { for _, f := range in.Float64s() {
if f == 0 { if f == 0 {
return ErrNotBlank return ErrNotBlank
@ -77,9 +78,9 @@ func arrayNotBlank(flag input.Flag, in input.Value) error {
} }
return nil return nil
case flag.IsBool() && len(in.Bools()) > 0: case f.IsBool() && len(in.Bools()) > 0:
return nil return nil
case flag.IsDuration() && len(in.Durations()) > 0: case f.IsDuration() && len(in.Durations()) > 0:
for _, d := range in.Durations() { for _, d := range in.Durations() {
if d == 0 { if d == 0 {
return ErrNotBlank return ErrNotBlank
@ -87,7 +88,7 @@ func arrayNotBlank(flag input.Flag, in input.Value) error {
} }
return nil return nil
case flag.IsTime() && len(in.Times()) > 0: case f.IsTime() && len(in.Times()) > 0:
for _, t := range in.Times() { for _, t := range in.Times() {
if t.IsZero() { if t.IsZero() {
return ErrNotBlank return ErrNotBlank
@ -95,7 +96,7 @@ func arrayNotBlank(flag input.Flag, in input.Value) error {
} }
return nil return nil
case flag.IsString() && len(in.Strings()) > 0: case f.IsString() && len(in.Strings()) > 0:
for _, st := range in.Strings() { for _, st := range in.Strings() {
if len(st) == 0 { if len(st) == 0 {
return ErrNotBlank return ErrNotBlank

44
validator/not_blank_test.go → input/validator/not_blank_test.go

@ -5,90 +5,90 @@ import (
"testing" "testing"
"time" "time"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input/flag"
"gitoa.ru/go-4devs/console/input/validator"
"gitoa.ru/go-4devs/console/input/value" "gitoa.ru/go-4devs/console/input/value"
"gitoa.ru/go-4devs/console/validator"
) )
func TestNotBlank(t *testing.T) { func TestNotBlank(t *testing.T) {
cases := map[string]struct { cases := map[string]struct {
flag input.Flag flag flag.Flag
value input.Value value value.Value
empty input.Value empty value.Value
}{ }{
"any": {flag: input.ValueAny, value: value.New(float32(1))}, "any": {flag: flag.Any, value: value.New(float32(1))},
"array int": { "array int": {
flag: input.ValueInt | input.ValueArray, flag: flag.Int | flag.Array,
value: value.New([]int{1}), value: value.New([]int{1}),
empty: value.New([]int{10, 20, 0}), empty: value.New([]int{10, 20, 0}),
}, },
"array int64": { "array int64": {
flag: input.ValueInt64 | input.ValueArray, flag: flag.Int64 | flag.Array,
value: value.New([]int64{1}), value: value.New([]int64{1}),
empty: value.New([]int64{0}), empty: value.New([]int64{0}),
}, },
"array uint": { "array uint": {
flag: input.ValueUint | input.ValueArray, flag: flag.Uint | flag.Array,
value: value.New([]uint{1}), value: value.New([]uint{1}),
empty: value.New([]uint{1, 0}), empty: value.New([]uint{1, 0}),
}, },
"array uint64": { "array uint64": {
flag: input.ValueUint64 | input.ValueArray, flag: flag.Uint64 | flag.Array,
value: value.New([]uint64{1}), value: value.New([]uint64{1}),
empty: value.New([]uint64{0}), empty: value.New([]uint64{0}),
}, },
"array float64": { "array float64": {
flag: input.ValueFloat64 | input.ValueArray, flag: flag.Float64 | flag.Array,
value: value.New([]float64{0.2}), value: value.New([]float64{0.2}),
empty: value.New([]float64{0}), empty: value.New([]float64{0}),
}, },
"array bool": { "array bool": {
flag: input.ValueBool | input.ValueArray, flag: flag.Bool | flag.Array,
value: value.New([]bool{true, false}), value: value.New([]bool{true, false}),
empty: value.New([]bool{}), empty: value.New([]bool{}),
}, },
"array duration": { "array duration": {
flag: input.ValueDuration | input.ValueArray, flag: flag.Duration | flag.Array,
value: value.New([]time.Duration{time.Second}), value: value.New([]time.Duration{time.Second}),
empty: value.New([]time.Duration{time.Second, 0}), empty: value.New([]time.Duration{time.Second, 0}),
}, },
"array time": { "array time": {
flag: input.ValueTime | input.ValueArray, flag: flag.Time | flag.Array,
value: value.New([]time.Time{time.Now()}), value: value.New([]time.Time{time.Now()}),
empty: value.New([]time.Time{{}, time.Now()}), empty: value.New([]time.Time{{}, time.Now()}),
}, },
"array string": { "array string": {
flag: input.ValueArray, flag: flag.Array,
value: value.New([]string{"value"}), value: value.New([]string{"value"}),
empty: value.New([]string{""}), empty: value.New([]string{""}),
}, },
"int": { "int": {
flag: input.ValueInt, flag: flag.Int,
value: value.New(int(1)), value: value.New(int(1)),
}, },
"int64": { "int64": {
flag: input.ValueInt64, flag: flag.Int64,
value: value.New(int64(2)), value: value.New(int64(2)),
}, },
"uint": { "uint": {
flag: input.ValueUint, flag: flag.Uint,
value: value.New(uint(1)), value: value.New(uint(1)),
empty: value.New([]uint{1}), empty: value.New([]uint{1}),
}, },
"uint64": { "uint64": {
flag: input.ValueUint64, flag: flag.Uint64,
value: value.New(uint64(10)), value: value.New(uint64(10)),
}, },
"float64": { "float64": {
flag: input.ValueFloat64, flag: flag.Float64,
value: value.New(float64(.00001)), value: value.New(float64(.00001)),
}, },
"duration": { "duration": {
flag: input.ValueDuration, flag: flag.Duration,
value: value.New(time.Minute), value: value.New(time.Minute),
empty: value.New("same string"), empty: value.New("same string"),
}, },
"time": {flag: input.ValueTime, value: value.New(time.Now())}, "time": {flag: flag.Time, value: value.New(time.Now())},
"string": {value: value.New("string"), empty: value.New("")}, "string": {value: value.New("string"), empty: value.New("")},
} }

15
input/validator/valid.go

@ -0,0 +1,15 @@
package validator
import "gitoa.ru/go-4devs/console/input/value"
func Valid(v ...func(value.Value) error) func(value.Value) error {
return func(in value.Value) error {
for _, valid := range v {
if err := valid(in); err != nil {
return err
}
}
return nil
}
}

6
validator/valid_test.go → input/validator/valid_test.go

@ -4,9 +4,9 @@ import (
"errors" "errors"
"testing" "testing"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input/flag"
"gitoa.ru/go-4devs/console/input/validator"
"gitoa.ru/go-4devs/console/input/value" "gitoa.ru/go-4devs/console/input/value"
"gitoa.ru/go-4devs/console/validator"
) )
func TestValid(t *testing.T) { func TestValid(t *testing.T) {
@ -14,7 +14,7 @@ func TestValid(t *testing.T) {
invalidValue := value.New([]string{"one"}) invalidValue := value.New([]string{"one"})
valid := validator.Valid( valid := validator.Valid(
validator.NotBlank(input.ValueString), validator.NotBlank(flag.String),
validator.Enum("one", "two"), validator.Enum("one", "two"),
) )

58
input/value.go

@ -1,58 +0,0 @@
package input
import (
"time"
)
type Value interface {
String() string
Int() int
Int64() int64
Uint() uint
Uint64() uint64
Float64() float64
Bool() bool
Duration() time.Duration
Time() time.Time
Any() interface{}
Strings() []string
Ints() []int
Int64s() []int64
Uints() []uint
Uint64s() []uint64
Float64s() []float64
Bools() []bool
Durations() []time.Duration
Times() []time.Time
}
type AppendValue interface {
Value
Append(string) error
}
func Type(flag Flag) Flag {
switch {
case (flag & ValueInt) > 0:
return ValueInt
case (flag & ValueInt64) > 0:
return ValueInt64
case (flag & ValueUint) > 0:
return ValueUint
case (flag & ValueUint64) > 0:
return ValueUint64
case (flag & ValueFloat64) > 0:
return ValueFloat64
case (flag & ValueBool) > 0:
return ValueBool
case (flag & ValueDuration) > 0:
return ValueDuration
case (flag & ValueTime) > 0:
return ValueTime
case (flag & ValueAny) > 0:
return ValueAny
default:
return ValueString
}
}

4
input/value/any.go

@ -1,11 +1,11 @@
package value package value
import "gitoa.ru/go-4devs/console/input" import "gitoa.ru/go-4devs/console/input/flag"
type Any struct { type Any struct {
Empty Empty
Val []interface{} Val []interface{}
Flag input.Flag Flag flag.Flag
} }
func (a *Any) Any() interface{} { func (a *Any) Any() interface{} {

6
input/value/bool.go

@ -3,13 +3,13 @@ package value
import ( import (
"strconv" "strconv"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input/flag"
) )
type Bool struct { type Bool struct {
Empty Empty
Val []bool Val []bool
Flag input.Flag Flag flag.Flag
} }
func (b *Bool) Append(in string) error { func (b *Bool) Append(in string) error {
@ -36,7 +36,7 @@ func (b *Bool) Bools() []bool {
} }
func (b *Bool) Any() interface{} { func (b *Bool) Any() interface{} {
if b.Flag&input.ValueArray > 0 { if b.Flag.IsArray() {
return b.Bools() return b.Bools()
} }

6
input/value/duration.go

@ -3,13 +3,13 @@ package value
import ( import (
"time" "time"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input/flag"
) )
type Duration struct { type Duration struct {
Empty Empty
Val []time.Duration Val []time.Duration
Flag input.Flag Flag flag.Flag
} }
func (d *Duration) Append(in string) error { func (d *Duration) Append(in string) error {
@ -36,7 +36,7 @@ func (d *Duration) Durations() []time.Duration {
} }
func (d *Duration) Any() interface{} { func (d *Duration) Any() interface{} {
if d.Flag&input.ValueArray > 0 { if d.Flag.IsArray() {
return d.Durations() return d.Durations()
} }

5
input/value/empty.go

@ -1,16 +1,13 @@
package value package value
import ( import (
"fmt"
"time" "time"
"gitoa.ru/go-4devs/console/input"
) )
type Empty struct{} type Empty struct{}
func (e *Empty) Append(string) error { func (e *Empty) Append(string) error {
return fmt.Errorf("%w: in empty value", input.ErrInvalidName) return ErrAppendEmpty
} }
func (e *Empty) String() string { func (e *Empty) String() string {

6
input/value/float64.go

@ -3,13 +3,13 @@ package value
import ( import (
"strconv" "strconv"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input/flag"
) )
type Float64 struct { type Float64 struct {
Empty Empty
Val []float64 Val []float64
Flag input.Flag Flag flag.Flag
} }
func (f *Float64) Append(in string) error { func (f *Float64) Append(in string) error {
@ -36,7 +36,7 @@ func (f *Float64) Float64s() []float64 {
} }
func (f *Float64) Any() interface{} { func (f *Float64) Any() interface{} {
if f.Flag&input.ValueFloat64 > 0 { if f.Flag.IsArray() {
return f.Float64s() return f.Float64s()
} }

6
input/value/int.go

@ -3,13 +3,13 @@ package value
import ( import (
"strconv" "strconv"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input/flag"
) )
type Int struct { type Int struct {
Empty Empty
Val []int Val []int
Flag input.Flag Flag flag.Flag
} }
func (i *Int) Append(in string) error { func (i *Int) Append(in string) error {
@ -36,7 +36,7 @@ func (i *Int) Ints() []int {
} }
func (i *Int) Any() interface{} { func (i *Int) Any() interface{} {
if i.Flag&input.ValueArray > 0 { if i.Flag.IsArray() {
return i.Ints() return i.Ints()
} }

6
input/value/int64.go

@ -3,13 +3,13 @@ package value
import ( import (
"strconv" "strconv"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input/flag"
) )
type Int64 struct { type Int64 struct {
Empty Empty
Val []int64 Val []int64
Flag input.Flag Flag flag.Flag
} }
func (i *Int64) Int64() int64 { func (i *Int64) Int64() int64 {
@ -25,7 +25,7 @@ func (i *Int64) Int64s() []int64 {
} }
func (i *Int64) Any() interface{} { func (i *Int64) Any() interface{} {
if i.Flag&input.ValueArray > 0 { if i.Flag.IsArray() {
return i.Int64s() return i.Int64s()
} }

15
input/value/read.go

@ -1,17 +1,20 @@
package value package value
import ( import (
"fmt" "errors"
"gitoa.ru/go-4devs/console/input"
) )
var _ input.AppendValue = (*Read)(nil) var _ AppendValue = (*Read)(nil)
var (
ErrAppendRead = errors.New("invalid append data to read value")
ErrAppendEmpty = errors.New("invalid apped data to empty value")
)
type Read struct { type Read struct {
input.Value Value
} }
func (r *Read) Append(string) error { func (r *Read) Append(string) error {
return fmt.Errorf("%w: read value", input.ErrInvalidName) return ErrAppendRead
} }

4
input/value/string.go

@ -1,11 +1,11 @@
package value package value
import "gitoa.ru/go-4devs/console/input" import "gitoa.ru/go-4devs/console/input/flag"
type String struct { type String struct {
Empty Empty
Val []string Val []string
Flag input.Flag Flag flag.Flag
} }
func (s *String) Append(in string) error { func (s *String) Append(in string) error {

6
input/value/time.go

@ -3,13 +3,13 @@ package value
import ( import (
"time" "time"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input/flag"
) )
type Time struct { type Time struct {
Empty Empty
Val []time.Time Val []time.Time
Flag input.Flag Flag flag.Flag
} }
func (t *Time) Append(in string) error { func (t *Time) Append(in string) error {
@ -36,7 +36,7 @@ func (t *Time) Times() []time.Time {
} }
func (t *Time) Amy() interface{} { func (t *Time) Amy() interface{} {
if t.Flag&input.ValueArray > 0 { if t.Flag.IsArray() {
return t.Times() return t.Times()
} }

6
input/value/uint.go

@ -3,13 +3,13 @@ package value
import ( import (
"strconv" "strconv"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input/flag"
) )
type Uint struct { type Uint struct {
Empty Empty
Val []uint Val []uint
Flag input.Flag Flag flag.Flag
} }
func (u *Uint) Append(in string) error { func (u *Uint) Append(in string) error {
@ -36,7 +36,7 @@ func (u *Uint) Uints() []uint {
} }
func (u *Uint) Any() interface{} { func (u *Uint) Any() interface{} {
if u.Flag&input.ValueArray > 0 { if u.Flag.IsArray() {
return u.Uints() return u.Uints()
} }

6
input/value/uint64.go

@ -3,13 +3,13 @@ package value
import ( import (
"strconv" "strconv"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input/flag"
) )
type Uint64 struct { type Uint64 struct {
Empty Empty
Val []uint64 Val []uint64
Flag input.Flag Flag flag.Flag
} }
func (u *Uint64) Append(in string) error { func (u *Uint64) Append(in string) error {
@ -36,7 +36,7 @@ func (u *Uint64) Uint64s() []uint64 {
} }
func (u *Uint64) Any() interface{} { func (u *Uint64) Any() interface{} {
if u.Flag&input.ValueArray > 0 { if u.Flag.IsArray() {
return u.Uint64s() return u.Uint64s()
} }

112
input/value/value.go

@ -3,81 +3,109 @@ package value
import ( import (
"time" "time"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input/flag"
) )
type Value interface {
String() string
Int() int
Int64() int64
Uint() uint
Uint64() uint64
Float64() float64
Bool() bool
Duration() time.Duration
Time() time.Time
Any() interface{}
Strings() []string
Ints() []int
Int64s() []int64
Uints() []uint
Uint64s() []uint64
Float64s() []float64
Bools() []bool
Durations() []time.Duration
Times() []time.Time
}
type AppendValue interface {
Value
Append(string) error
}
//nolint: gocyclo //nolint: gocyclo
func New(v interface{}) input.Value { func New(v interface{}) Value {
switch val := v.(type) { switch val := v.(type) {
case string: case string:
return &String{Val: []string{val}, Flag: input.ValueString} return &String{Val: []string{val}, Flag: flag.String}
case int: case int:
return &Int{Val: []int{val}, Flag: input.ValueInt} return &Int{Val: []int{val}, Flag: flag.Int}
case int64: case int64:
return &Int64{Val: []int64{val}, Flag: input.ValueInt64} return &Int64{Val: []int64{val}, Flag: flag.Int64}
case uint: case uint:
return &Uint{Val: []uint{val}, Flag: input.ValueUint} return &Uint{Val: []uint{val}, Flag: flag.Uint}
case uint64: case uint64:
return &Uint64{Val: []uint64{val}, Flag: input.ValueUint64} return &Uint64{Val: []uint64{val}, Flag: flag.Uint64}
case float64: case float64:
return &Float64{Val: []float64{val}, Flag: input.ValueFloat64} return &Float64{Val: []float64{val}, Flag: flag.Float64}
case bool: case bool:
return &Bool{Val: []bool{val}, Flag: input.ValueBool} return &Bool{Val: []bool{val}, Flag: flag.Bool}
case time.Duration: case time.Duration:
return &Duration{Val: []time.Duration{val}, Flag: input.ValueDuration} return &Duration{Val: []time.Duration{val}, Flag: flag.Duration}
case time.Time: case time.Time:
return &Time{Val: []time.Time{val}, Flag: input.ValueTime} return &Time{Val: []time.Time{val}, Flag: flag.Time}
case []int64: case []int64:
return &Int64{Val: val, Flag: input.ValueInt64 | input.ValueArray} return &Int64{Val: val, Flag: flag.Int64 | flag.Array}
case []uint: case []uint:
return &Uint{Val: val, Flag: input.ValueUint | input.ValueArray} return &Uint{Val: val, Flag: flag.Uint | flag.Array}
case []uint64: case []uint64:
return &Uint64{Val: val, Flag: input.ValueUint64 | input.ValueArray} return &Uint64{Val: val, Flag: flag.Uint64 | flag.Array}
case []float64: case []float64:
return &Float64{Val: val, Flag: input.ValueFloat64 | input.ValueArray} return &Float64{Val: val, Flag: flag.Float64 | flag.Array}
case []bool: case []bool:
return &Bool{Val: val, Flag: input.ValueBool | input.ValueArray} return &Bool{Val: val, Flag: flag.Bool | flag.Array}
case []time.Duration: case []time.Duration:
return &Duration{Val: val, Flag: input.ValueDuration | input.ValueArray} return &Duration{Val: val, Flag: flag.Duration | flag.Array}
case []time.Time: case []time.Time:
return &Time{Val: val, Flag: input.ValueTime | input.ValueArray} return &Time{Val: val, Flag: flag.Time | flag.Array}
case []string: case []string:
return &String{Val: val, Flag: input.ValueString | input.ValueArray} return &String{Val: val, Flag: flag.String | flag.Array}
case []int: case []int:
return &Int{Val: val, Flag: input.ValueInt | input.ValueArray} return &Int{Val: val, Flag: flag.Int | flag.Array}
case []interface{}: case []interface{}:
return &Any{Val: val, Flag: input.ValueAny | input.ValueArray} return &Any{Val: val, Flag: flag.Any | flag.Array}
case input.Value: case Value:
return val return val
default: default:
if v != nil { if v != nil {
return &Any{Val: []interface{}{v}, Flag: input.ValueAny} return &Any{Val: []interface{}{v}, Flag: flag.Any}
} }
return &Empty{} return &Empty{}
} }
} }
func ByFlag(flag input.Flag) input.AppendValue { func ByFlag(f flag.Flag) AppendValue {
switch { switch {
case flag.IsInt(): case f.IsInt():
return &Int{Flag: flag | input.ValueInt} return &Int{Flag: f | flag.Int}
case flag.IsInt64(): case f.IsInt64():
return &Int64{Flag: flag | input.ValueInt64} return &Int64{Flag: f | flag.Int64}
case flag.IsUint(): case f.IsUint():
return &Uint{Flag: flag | input.ValueUint} return &Uint{Flag: f | flag.Uint}
case flag.IsUint64(): case f.IsUint64():
return &Uint64{Flag: flag | input.ValueUint64} return &Uint64{Flag: f | flag.Uint64}
case flag.IsFloat64(): case f.IsFloat64():
return &Float64{Flag: flag | input.ValueFloat64} return &Float64{Flag: f | flag.Float64}
case flag.IsBool(): case f.IsBool():
return &Bool{Flag: flag | input.ValueBool} return &Bool{Flag: f | flag.Bool}
case flag.IsDuration(): case f.IsDuration():
return &Duration{Flag: flag | input.ValueDuration} return &Duration{Flag: f | flag.Duration}
case flag.IsTime(): case f.IsTime():
return &Time{Flag: flag | input.ValueTime} return &Time{Flag: f | flag.Time}
case flag.IsAny(): case f.IsAny():
return &Any{Flag: flag | input.ValueAny} return &Any{Flag: f | flag.Any}
default: default:
return &String{} return &String{}
} }

8
input/wrap/input.go

@ -12,7 +12,7 @@ type Input struct {
input.ReadInput input.ReadInput
} }
func (i *Input) Option(ctx context.Context, name string) input.Value { func (i *Input) Option(ctx context.Context, name string) value.Value {
if v, err := i.ReadOption(ctx, name); err == nil { if v, err := i.ReadOption(ctx, name); err == nil {
return v return v
} }
@ -20,7 +20,7 @@ func (i *Input) Option(ctx context.Context, name string) input.Value {
return &value.Empty{} return &value.Empty{}
} }
func (i *Input) Argument(ctx context.Context, name string) input.Value { func (i *Input) Argument(ctx context.Context, name string) value.Value {
if v, err := i.ReadArgument(ctx, name); err == nil { if v, err := i.ReadArgument(ctx, name); err == nil {
return v return v
} }
@ -40,10 +40,6 @@ func (i *Input) Bind(ctx context.Context, def *input.Definition) error {
return i.bindOptions(ctx, def) return i.bindOptions(ctx, def)
} }
func (i *Input) build(ctx context.Context) error {
return nil
}
func (i *Input) bindOptions(ctx context.Context, def *input.Definition) error { func (i *Input) bindOptions(ctx context.Context, def *input.Definition) error {
for _, name := range def.Options() { for _, name := range def.Options() {
opt, err := def.Option(name) opt, err := def.Option(name)

7
list.go

@ -7,9 +7,10 @@ import (
"gitoa.ru/go-4devs/console/descriptor" "gitoa.ru/go-4devs/console/descriptor"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input"
"gitoa.ru/go-4devs/console/input/argument"
"gitoa.ru/go-4devs/console/input/option" "gitoa.ru/go-4devs/console/input/option"
"gitoa.ru/go-4devs/console/input/validator"
"gitoa.ru/go-4devs/console/output" "gitoa.ru/go-4devs/console/output"
"gitoa.ru/go-4devs/console/validator"
) )
const defaultLenNamespace = 2 const defaultLenNamespace = 2
@ -92,10 +93,10 @@ You can also output the information in other formats by using the <comment>--for
formats := descriptor.Descriptors() formats := descriptor.Descriptors()
config. config.
SetArguments( SetArguments(
input.NewArgument("namespace", "The namespace name"), argument.New("namespace", "The namespace name"),
). ).
SetOptions( SetOptions(
input.NewOption(helpOptFormat, fmt.Sprintf("The output format (%s)", strings.Join(formats, ", ")), option.New(helpOptFormat, fmt.Sprintf("The output format (%s)", strings.Join(formats, ", ")),
option.Required, option.Required,
option.Default(formats[0]), option.Default(formats[0]),
option.Valid( option.Valid(

15
validator/valid.go

@ -1,15 +0,0 @@
package validator
import "gitoa.ru/go-4devs/console/input"
func Valid(v ...func(input.Value) error) func(input.Value) error {
return func(in input.Value) error {
for _, valid := range v {
if err := valid(in); err != nil {
return err
}
}
return nil
}
}
Loading…
Cancel
Save