From 1c7e9623ce988e0fa13114c0161c7cc29e976471 Mon Sep 17 00:00:00 2001 From: andrey1s Date: Sun, 25 Oct 2020 12:40:40 +0300 Subject: [PATCH] separate options --- command_test.go | 5 +- descriptor/txt.go | 74 ++++++------ example/pkg/command/args.go | 4 +- example/pkg/command/create_user.go | 2 +- example/pkg/command/hello.go | 2 +- example/pkg/command/long.go | 5 +- help.go | 9 +- input/{ => argument}/argument.go | 23 ++-- input/argument/option.go | 18 +-- input/argv/input.go | 21 ++-- input/array/input.go | 16 +-- input/definition.go | 39 +++--- input/flag.go | 76 ------------ input/flag/flag.go | 97 +++++++++++++++ input/{ => flag}/flag_string.go | 26 ++-- input/input.go | 14 ++- input/option.go | 52 -------- input/option/helpers.go | 36 +++--- input/option/option.go | 86 +++++++++++--- {validator => input/validator}/enum.go | 6 +- {validator => input/validator}/enum_test.go | 2 +- {validator => input/validator}/error.go | 0 {validator => input/validator}/not_blank.go | 49 ++++---- .../validator}/not_blank_test.go | 44 +++---- input/validator/valid.go | 15 +++ {validator => input/validator}/valid_test.go | 6 +- input/value.go | 58 --------- input/value/any.go | 4 +- input/value/bool.go | 6 +- input/value/duration.go | 6 +- input/value/empty.go | 5 +- input/value/float64.go | 6 +- input/value/int.go | 6 +- input/value/int64.go | 6 +- input/value/read.go | 15 ++- input/value/string.go | 4 +- input/value/time.go | 6 +- input/value/uint.go | 6 +- input/value/uint64.go | 6 +- input/value/value.go | 112 +++++++++++------- input/wrap/input.go | 8 +- list.go | 7 +- validator/valid.go | 15 --- 43 files changed, 510 insertions(+), 493 deletions(-) rename input/{ => argument}/argument.go (57%) delete mode 100644 input/flag.go create mode 100644 input/flag/flag.go rename input/{ => flag}/flag_string.go (74%) rename {validator => input/validator}/enum.go (52%) rename {validator => input/validator}/enum_test.go (91%) rename {validator => input/validator}/error.go (100%) rename {validator => input/validator}/not_blank.go (50%) rename {validator => input/validator}/not_blank_test.go (69%) create mode 100644 input/validator/valid.go rename {validator => input/validator}/valid_test.go (80%) delete mode 100644 input/value.go delete mode 100644 validator/valid.go diff --git a/command_test.go b/command_test.go index 1b2c983..90f45e0 100644 --- a/command_test.go +++ b/command_test.go @@ -10,6 +10,7 @@ import ( "gitoa.ru/go-4devs/console" "gitoa.ru/go-4devs/console/example/pkg/command" "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/option" "gitoa.ru/go-4devs/console/output" @@ -39,10 +40,10 @@ func Command() *console.Command { Configure: func(ctx context.Context, def *input.Definition) error { def. SetArguments( - input.NewArgument("test_argument", "test argument"), + argument.New("test_argument", "test argument"), ). SetOptions( - input.NewOption("string", "array string", option.Array), + option.New("string", "array string", option.Array), option.Bool("bool", "test bool option"), option.Duration("duration", "test duration with default", option.Default(time.Second)), ) diff --git a/descriptor/txt.go b/descriptor/txt.go index c383a80..c74c3da 100644 --- a/descriptor/txt.go +++ b/descriptor/txt.go @@ -10,6 +10,8 @@ import ( "time" "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" ) @@ -76,36 +78,36 @@ func (t *txt) Commands(ctx context.Context, out output.Output, cmds Commands) er return nil } -func txtDefaultArray(val input.Value, flag input.Flag) string { - st := val.Strings() +func txtDefaultArray(v value.Value, f flag.Flag) string { + st := v.Strings() switch { - case flag.IsInt(): - for _, i := range val.Ints() { + case f.IsInt(): + for _, i := range v.Ints() { st = append(st, strconv.Itoa(i)) } - case flag.IsInt64(): - for _, i := range val.Int64s() { + case f.IsInt64(): + for _, i := range v.Int64s() { st = append(st, strconv.FormatInt(i, 10)) } - case flag.IsUint(): - for _, u := range val.Uints() { + case f.IsUint(): + for _, u := range v.Uints() { st = append(st, strconv.FormatUint(uint64(u), 10)) } - case flag.IsUint64(): - for _, u := range val.Uint64s() { + case f.IsUint64(): + for _, u := range v.Uint64s() { st = append(st, strconv.FormatUint(u, 10)) } - case flag.IsFloat64(): - for _, f := range val.Float64s() { + case f.IsFloat64(): + for _, f := range v.Float64s() { st = append(st, strconv.FormatFloat(f, 'g', -1, 64)) } - case flag.IsDuration(): - for _, d := range val.Durations() { + case f.IsDuration(): + for _, d := range v.Durations() { st = append(st, d.String()) } - case flag.IsTime(): - for _, d := range val.Times() { + case f.IsTime(): + for _, d := range v.Times() { st = append(st, d.Format(time.RFC3339)) } } @@ -113,32 +115,32 @@ func txtDefaultArray(val input.Value, flag input.Flag) string { 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 buf.WriteString(" [default: ") switch { - case flag.IsArray(): - buf.WriteString(txtDefaultArray(val, flag)) - case flag.IsInt(): - buf.WriteString(strconv.Itoa(val.Int())) - case flag.IsInt64(): - buf.WriteString(strconv.FormatInt(val.Int64(), 10)) - case flag.IsUint(): - buf.WriteString(strconv.FormatUint(uint64(val.Uint()), 10)) - case flag.IsUint64(): - buf.WriteString(strconv.FormatUint(val.Uint64(), 10)) - case flag.IsFloat64(): - buf.WriteString(strconv.FormatFloat(val.Float64(), 'g', -1, 64)) - case flag.IsDuration(): - buf.WriteString(val.Duration().String()) - case flag.IsTime(): - buf.WriteString(val.Time().Format(time.RFC3339)) - case flag.IsAny(): - buf.WriteString(fmt.Sprint(val.Any())) + case f.IsArray(): + buf.WriteString(txtDefaultArray(v, f)) + case f.IsInt(): + buf.WriteString(strconv.Itoa(v.Int())) + case f.IsInt64(): + buf.WriteString(strconv.FormatInt(v.Int64(), 10)) + case f.IsUint(): + buf.WriteString(strconv.FormatUint(uint64(v.Uint()), 10)) + case f.IsUint64(): + buf.WriteString(strconv.FormatUint(v.Uint64(), 10)) + case f.IsFloat64(): + buf.WriteString(strconv.FormatFloat(v.Float64(), 'g', -1, 64)) + case f.IsDuration(): + buf.WriteString(v.Duration().String()) + case f.IsTime(): + buf.WriteString(v.Time().Format(time.RFC3339)) + case f.IsAny(): + buf.WriteString(fmt.Sprint(v.Any())) default: - buf.WriteString(val.String()) + buf.WriteString(v.String()) } buf.WriteString("]") diff --git a/example/pkg/command/args.go b/example/pkg/command/args.go index bb2b46f..3cf145a 100644 --- a/example/pkg/command/args.go +++ b/example/pkg/command/args.go @@ -16,8 +16,8 @@ func Args() *console.Command { Configure: func(ctx context.Context, def *input.Definition) error { def.SetOptions( option.Bool("foo", "foo option", option.Short("f")), - input.NewOption("bar", "required bar option", option.Required, option.Short("b")), - input.NewOption("cat", "cat option", option.Short("c")), + option.New("bar", "required bar option", option.Required, option.Short("b")), + option.New("cat", "cat option", option.Short("c")), ) return nil diff --git a/example/pkg/command/create_user.go b/example/pkg/command/create_user.go index ae9425f..620e896 100644 --- a/example/pkg/command/create_user.go +++ b/example/pkg/command/create_user.go @@ -15,7 +15,7 @@ func CreateUser(required bool) *console.Command { Description: "Creates a new user.", Help: "This command allows you to create a user...", Configure: func(ctx context.Context, cfg *input.Definition) error { - var opts []func(*input.Argument) + var opts []func(*argument.Argument) if required { opts = append(opts, argument.Required) } diff --git a/example/pkg/command/hello.go b/example/pkg/command/hello.go index 4d73e5b..85948f5 100644 --- a/example/pkg/command/hello.go +++ b/example/pkg/command/hello.go @@ -25,7 +25,7 @@ func Hello() *console.Command { }, Configure: func(_ context.Context, def *input.Definition) error { def.SetArguments( - input.NewArgument("name", "Same name", argument.Default("World")), + argument.New("name", "Same name", argument.Default("World")), ) return nil diff --git a/example/pkg/command/long.go b/example/pkg/command/long.go index 9ecced1..d383b14 100644 --- a/example/pkg/command/long.go +++ b/example/pkg/command/long.go @@ -6,9 +6,10 @@ import ( "gitoa.ru/go-4devs/console" "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/validator" "gitoa.ru/go-4devs/console/output" - "gitoa.ru/go-4devs/console/validator" ) const defaultTimeout = time.Second * 30 @@ -41,7 +42,7 @@ func Long() *console.Command { def.SetOptions(option.Duration("timeout", "set duration run command", option.Default(defaultTimeout), option.Short("t"), - option.Valid(validator.NotBlank(input.ValueDuration)), + option.Valid(validator.NotBlank(flag.Duration)), )) return nil diff --git a/help.go b/help.go index 2d80c89..a22c072 100644 --- a/help.go +++ b/help.go @@ -9,9 +9,10 @@ import ( "gitoa.ru/go-4devs/console/descriptor" "gitoa.ru/go-4devs/console/input" "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/validator" "gitoa.ru/go-4devs/console/output" - "gitoa.ru/go-4devs/console/validator" ) //nolint: gochecknoinits @@ -73,14 +74,14 @@ To display the list of available commands, please use the list comm formats := descriptor.Descriptors() config. SetArguments( - input.NewArgument(HelpArgumentCommandName, "The command name", argument.Default("help")), + argument.New(HelpArgumentCommandName, "The command name", argument.Default("help")), ). 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.Default(formats[0]), option.Valid( - validator.NotBlank(input.ValueString), + validator.NotBlank(flag.String), validator.Enum(formats...), ), ), diff --git a/input/argument.go b/input/argument/argument.go similarity index 57% rename from input/argument.go rename to input/argument/argument.go index 742f27c..9914073 100644 --- a/input/argument.go +++ b/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{ Name: name, Description: description, @@ -16,9 +21,9 @@ func NewArgument(name, description string, opts ...func(*Argument)) Argument { type Argument struct { Name string Description string - Default Value - Flag Flag - Valid []func(Value) error + Default value.Value + Flag flag.Flag + Valid []func(value.Value) error } func (a Argument) HasDefault() bool { @@ -37,12 +42,16 @@ func (a Argument) IsArray() bool { return a.Flag.IsArray() } -func (a Argument) Validate(v Value) error { +func (a Argument) Validate(v value.Value) error { for _, valid := range a.Valid { if err := valid(v); err != nil { - return ErrorArgument(a.Name, err) + return Error(a.Name, err) } } return nil } + +func Error(name string, err error) error { + return err +} diff --git a/input/argument/option.go b/input/argument/option.go index 942feae..4fc1d57 100644 --- a/input/argument/option.go +++ b/input/argument/option.go @@ -1,26 +1,26 @@ package argument import ( - "gitoa.ru/go-4devs/console/input" + "gitoa.ru/go-4devs/console/input/flag" "gitoa.ru/go-4devs/console/input/value" ) -func Required(a *input.Argument) { - a.Flag |= input.ValueRequired +func Required(a *Argument) { + a.Flag |= flag.Required } -func Default(v interface{}) func(*input.Argument) { - return func(a *input.Argument) { +func Default(v interface{}) func(*Argument) { + return func(a *Argument) { a.Default = value.New(v) } } -func Flag(flag input.Flag) func(*input.Argument) { - return func(a *input.Argument) { +func Flag(flag flag.Flag) func(*Argument) { + return func(a *Argument) { a.Flag = flag } } -func Array(a *input.Argument) { - a.Flag |= input.ValueArray +func Array(a *Argument) { + a.Flag |= flag.Array } diff --git a/input/argv/input.go b/input/argv/input.go index 6babff9..e7f524c 100644 --- a/input/argv/input.go +++ b/input/argv/input.go @@ -7,6 +7,7 @@ import ( "sync" "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/wrap" ) @@ -24,8 +25,8 @@ func WithErrorHandle(h func(error) error) func(*Input) { func New(args []string, opts ...func(*Input)) *wrap.Input { i := &Input{ args: args, - arguments: make(map[string]input.AppendValue), - options: make(map[string]input.AppendValue), + arguments: make(map[string]value.AppendValue), + options: make(map[string]value.AppendValue), errorHandle: func(err error) error { return err }, @@ -40,13 +41,13 @@ func New(args []string, opts ...func(*Input)) *wrap.Input { type Input struct { args []string - arguments map[string]input.AppendValue - options map[string]input.AppendValue + arguments map[string]value.AppendValue + options map[string]value.AppendValue mu sync.RWMutex 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 { return v, nil } @@ -54,14 +55,14 @@ func (i *Input) ReadOption(ctx context.Context, name string) (input.Value, error 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() defer i.mu.Unlock() 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 { return v, nil } @@ -69,7 +70,7 @@ func (i *Input) ReadArgument(ctx context.Context, name string) (input.Value, err 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() defer i.mu.Unlock() @@ -129,11 +130,11 @@ func (i *Input) parseLongOption(arg string, def *input.Definition) error { 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] 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 diff --git a/input/array/input.go b/input/array/input.go index 5bf1704..0b9bd62 100644 --- a/input/array/input.go +++ b/input/array/input.go @@ -25,8 +25,8 @@ func Option(name string, v interface{}) func(*Input) { func New(opts ...func(*Input)) *wrap.Input { i := &Input{ - args: make(map[string]input.Value), - opt: make(map[string]input.Value), + args: make(map[string]value.Value), + opt: make(map[string]value.Value), } for _, opt := range opts { @@ -37,12 +37,12 @@ func New(opts ...func(*Input)) *wrap.Input { } type Input struct { - args map[string]input.Value - opt map[string]input.Value + args map[string]value.Value + opt map[string]value.Value 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 { return o, nil } @@ -56,13 +56,13 @@ func (i *Input) HasOption(name string) bool { return has } -func (i *Input) SetOption(name string, val input.Value) { +func (i *Input) SetOption(name string, val value.Value) { i.mu.Lock() i.opt[name] = val 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 { return a, nil } @@ -76,7 +76,7 @@ func (i *Input) HasArgument(name string) bool { return has } -func (i *Input) SetArgument(name string, val input.Value) { +func (i *Input) SetArgument(name string, val value.Value) { i.mu.Lock() i.args[name] = val i.mu.Unlock() diff --git a/input/definition.go b/input/definition.go index 1ae9cca..c3f526e 100644 --- a/input/definition.go +++ b/input/definition.go @@ -1,17 +1,22 @@ package input +import ( + "gitoa.ru/go-4devs/console/input/argument" + "gitoa.ru/go-4devs/console/input/option" +) + func NewDefinition() *Definition { return &Definition{ - options: make(map[string]Option), - args: make(map[string]Argument), + options: make(map[string]option.Option), + args: make(map[string]argument.Argument), short: make(map[string]string), } } type Definition struct { - options map[string]Option + options map[string]option.Option posOpt []string - args map[string]Argument + args map[string]argument.Argument posArgs []string short map[string]string } @@ -24,11 +29,11 @@ func (d *Definition) Arguments() []string { return d.posArgs } -func (d *Definition) SetOption(name, description string, opts ...func(*Option)) *Definition { - return d.SetOptions(NewOption(name, description, opts...)) +func (d *Definition) SetOption(name, description string, opts ...func(*option.Option)) *Definition { + 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 { if _, has := d.options[opt.Name]; !has { d.posOpt = append([]string{opt.Name}, d.posOpt...) @@ -43,11 +48,11 @@ func (d *Definition) SetOptions(opts ...Option) *Definition { return d } -func (d *Definition) SetArgument(name, description string, opts ...func(*Argument)) *Definition { - return d.SetArguments(NewArgument(name, description, opts...)) +func (d *Definition) SetArgument(name, description string, opts ...func(*argument.Argument)) *Definition { + 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 { if _, ok := d.args[arg.Name]; !ok { d.posArgs = append(d.posArgs, arg.Name) @@ -59,9 +64,9 @@ func (d *Definition) SetArguments(args ...Argument) *Definition { return d } -func (d *Definition) Argument(pos int) (Argument, error) { +func (d *Definition) Argument(pos int) (argument.Argument, error) { if len(d.posArgs) == 0 { - return Argument{}, ErrNoArgs + return argument.Argument{}, ErrNoArgs } lastPos := len(d.posArgs) - 1 @@ -71,25 +76,25 @@ func (d *Definition) Argument(pos int) (Argument, error) { return arg, nil } - return Argument{}, ErrToManyArgs + return argument.Argument{}, ErrToManyArgs } 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] if !ok { - return Option{}, ErrNotFound + return option.Option{}, ErrNotFound } 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 { return opt, nil } - return Option{}, ErrNotFound + return option.Option{}, ErrNotFound } diff --git a/input/flag.go b/input/flag.go deleted file mode 100644 index 9d719d3..0000000 --- a/input/flag.go +++ /dev/null @@ -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 -} diff --git a/input/flag/flag.go b/input/flag/flag.go new file mode 100644 index 0000000..d94b8ee --- /dev/null +++ b/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 + } +} diff --git a/input/flag_string.go b/input/flag/flag_string.go similarity index 74% rename from input/flag_string.go rename to input/flag/flag_string.go index 6040dca..e901776 100644 --- a/input/flag_string.go +++ b/input/flag/flag_string.go @@ -1,6 +1,6 @@ // Code generated by "stringer -type=Flag -linecomment"; DO NOT EDIT. -package input +package flag import "strconv" @@ -8,18 +8,18 @@ func _() { // An "invalid array index" compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. var x [1]struct{} - _ = x[ValueString-0] - _ = x[ValueRequired-2] - _ = x[ValueArray-4] - _ = x[ValueInt-8] - _ = x[ValueInt64-16] - _ = x[ValueUint-32] - _ = x[ValueUint64-64] - _ = x[ValueFloat64-128] - _ = x[ValueBool-256] - _ = x[ValueDuration-512] - _ = x[ValueTime-1024] - _ = x[ValueAny-2048] + _ = x[String-0] + _ = x[Required-2] + _ = x[Array-4] + _ = x[Int-8] + _ = x[Int64-16] + _ = x[Uint-32] + _ = x[Uint64-64] + _ = x[Float64-128] + _ = x[Bool-256] + _ = x[Duration-512] + _ = x[Time-1024] + _ = x[Any-2048] } const _Flag_name = "stringrequiredarrayintint64uintuint64float64booldurationtimeany" diff --git a/input/input.go b/input/input.go index 53679db..7b687ac 100644 --- a/input/input.go +++ b/input/input.go @@ -2,20 +2,22 @@ package input import ( "context" + + "gitoa.ru/go-4devs/console/input/value" ) type ReadInput interface { Bind(ctx context.Context, def *Definition) error - ReadOption(ctx context.Context, name string) (Value, error) - SetOption(name string, value Value) + ReadOption(ctx context.Context, name string) (value.Value, error) + SetOption(name string, v value.Value) - ReadArgument(ctx context.Context, name string) (Value, error) - SetArgument(name string, value Value) + ReadArgument(ctx context.Context, name string) (value.Value, error) + SetArgument(name string, v value.Value) } type Input interface { - Option(ctx context.Context, name string) Value - Argument(ctx context.Context, name string) Value + Option(ctx context.Context, name string) value.Value + Argument(ctx context.Context, name string) value.Value ReadInput } diff --git a/input/option.go b/input/option.go index 1017513..de1ab6f 100644 --- a/input/option.go +++ b/input/option.go @@ -1,53 +1 @@ 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 -} diff --git a/input/option/helpers.go b/input/option/helpers.go index 397d5c5..036b17a 100644 --- a/input/option/helpers.go +++ b/input/option/helpers.go @@ -1,35 +1,37 @@ 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 { - return input.NewOption(name, description, append(opts, Value(input.ValueBool))...) +func Bool(name, description string, opts ...func(*Option)) Option { + return New(name, description, append(opts, Value(flag.Bool))...) } -func Duration(name, description string, opts ...func(*input.Option)) input.Option { - return input.NewOption(name, description, append(opts, Value(input.ValueDuration))...) +func Duration(name, description string, opts ...func(*Option)) Option { + return New(name, description, append(opts, Value(flag.Duration))...) } -func Float64(name, description string, opts ...func(*input.Option)) input.Option { - return input.NewOption(name, description, append(opts, Value(input.ValueFloat64))...) +func Float64(name, description string, opts ...func(*Option)) Option { + return New(name, description, append(opts, Value(flag.Float64))...) } -func Int(name, description string, opts ...func(*input.Option)) input.Option { - return input.NewOption(name, description, append(opts, Value(input.ValueInt))...) +func Int(name, description string, opts ...func(*Option)) Option { + return New(name, description, append(opts, Value(flag.Int))...) } -func Int64(name, description string, opts ...func(*input.Option)) input.Option { - return input.NewOption(name, description, append(opts, Value(input.ValueInt64))...) +func Int64(name, description string, opts ...func(*Option)) Option { + return New(name, description, append(opts, Value(flag.Int64))...) } -func Time(name, description string, opts ...func(*input.Option)) input.Option { - return input.NewOption(name, description, append(opts, Value(input.ValueTime))...) +func Time(name, description string, opts ...func(*Option)) Option { + return New(name, description, append(opts, Value(flag.Time))...) } -func Uint(name, description string, opts ...func(*input.Option)) input.Option { - return input.NewOption(name, description, append(opts, Value(input.ValueUint))...) +func Uint(name, description string, opts ...func(*Option)) Option { + return New(name, description, append(opts, Value(flag.Uint))...) } -func Uint64(name, descriontion string, opts ...func(*input.Option)) input.Option { - return input.NewOption(name, descriontion, append(opts, Value(input.ValueUint64))...) +func Uint64(name, descriontion string, opts ...func(*Option)) Option { + return New(name, descriontion, append(opts, Value(flag.Uint64))...) } diff --git a/input/option/option.go b/input/option/option.go index ad69b30..d14ffe6 100644 --- a/input/option/option.go +++ b/input/option/option.go @@ -1,44 +1,100 @@ package option import ( - "gitoa.ru/go-4devs/console/input" + "gitoa.ru/go-4devs/console/input/flag" "gitoa.ru/go-4devs/console/input/value" ) -func Required(o *input.Option) { - o.Flag |= input.ValueRequired +func Required(o *Option) { + o.Flag |= flag.Required } -func Default(in interface{}) func(*input.Option) { - return func(o *input.Option) { +func Default(in interface{}) func(*Option) { + return func(o *Option) { o.Default = value.New(in) } } -func Short(s string) func(*input.Option) { - return func(o *input.Option) { +func Short(s string) func(*Option) { + return func(o *Option) { o.Short = s } } -func Array(o *input.Option) { - o.Flag |= input.ValueArray +func Array(o *Option) { + o.Flag |= flag.Array } -func Value(flag input.Flag) func(*input.Option) { - return func(o *input.Option) { +func Value(flag flag.Flag) func(*Option) { + return func(o *Option) { o.Flag |= flag } } -func Flag(in input.Flag) func(*input.Option) { - return func(o *input.Option) { +func Flag(in flag.Flag) func(*Option) { + return func(o *Option) { o.Flag = in } } -func Valid(f ...func(input.Value) error) func(*input.Option) { - return func(o *input.Option) { +func Valid(f ...func(value.Value) error) func(*Option) { + return func(o *Option) { 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 +} diff --git a/validator/enum.go b/input/validator/enum.go similarity index 52% rename from validator/enum.go rename to input/validator/enum.go index cf70d07..c6197ce 100644 --- a/validator/enum.go +++ b/input/validator/enum.go @@ -1,9 +1,9 @@ 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 { - return func(in input.Value) error { +func Enum(enum ...string) func(value.Value) error { + return func(in value.Value) error { v := in.String() for _, e := range enum { if e == v { diff --git a/validator/enum_test.go b/input/validator/enum_test.go similarity index 91% rename from validator/enum_test.go rename to input/validator/enum_test.go index c889219..b1844e0 100644 --- a/validator/enum_test.go +++ b/input/validator/enum_test.go @@ -4,8 +4,8 @@ import ( "errors" "testing" + "gitoa.ru/go-4devs/console/input/validator" "gitoa.ru/go-4devs/console/input/value" - "gitoa.ru/go-4devs/console/validator" ) func TestEnum(t *testing.T) { diff --git a/validator/error.go b/input/validator/error.go similarity index 100% rename from validator/error.go rename to input/validator/error.go diff --git a/validator/not_blank.go b/input/validator/not_blank.go similarity index 50% rename from validator/not_blank.go rename to input/validator/not_blank.go index e9fbbd2..3bb82cd 100644 --- a/validator/not_blank.go +++ b/input/validator/not_blank.go @@ -1,32 +1,33 @@ package validator import ( - "gitoa.ru/go-4devs/console/input" + "gitoa.ru/go-4devs/console/input/flag" + "gitoa.ru/go-4devs/console/input/value" ) //nolint: gocyclo -func NotBlank(flag input.Flag) func(input.Value) error { - return func(in input.Value) error { +func NotBlank(f flag.Flag) func(value.Value) error { + return func(in value.Value) error { switch { - case flag.IsAny() && in.Any() != nil: + case f.IsAny() && in.Any() != nil: return nil - case flag.IsArray(): - return arrayNotBlank(flag, in) - case flag.IsInt() && in.Int() != 0: + case f.IsArray(): + return arrayNotBlank(f, in) + case f.IsInt() && in.Int() != 0: return nil - case flag.IsInt64() && in.Int64() != 0: + case f.IsInt64() && in.Int64() != 0: return nil - case flag.IsUint() && in.Uint() != 0: + case f.IsUint() && in.Uint() != 0: return nil - case flag.IsUint64() && in.Uint64() != 0: + case f.IsUint64() && in.Uint64() != 0: return nil - case flag.IsFloat64() && in.Float64() != 0: + case f.IsFloat64() && in.Float64() != 0: return nil - case flag.IsDuration() && in.Duration() != 0: + case f.IsDuration() && in.Duration() != 0: return nil - case flag.IsTime() && !in.Time().IsZero(): + case f.IsTime() && !in.Time().IsZero(): return nil - case flag.IsString() && len(in.String()) > 0: + case f.IsString() && len(in.String()) > 0: return nil } @@ -35,9 +36,9 @@ func NotBlank(flag input.Flag) func(input.Value) error { } //nolint: gocyclo,gocognit -func arrayNotBlank(flag input.Flag, in input.Value) error { +func arrayNotBlank(f flag.Flag, in value.Value) error { switch { - case flag.IsInt() && len(in.Ints()) > 0: + case f.IsInt() && len(in.Ints()) > 0: for _, i := range in.Ints() { if i == 0 { return ErrNotBlank @@ -45,7 +46,7 @@ func arrayNotBlank(flag input.Flag, in input.Value) error { } return nil - case flag.IsInt64() && len(in.Int64s()) > 0: + case f.IsInt64() && len(in.Int64s()) > 0: for _, i := range in.Int64s() { if i == 0 { return ErrNotBlank @@ -53,7 +54,7 @@ func arrayNotBlank(flag input.Flag, in input.Value) error { } return nil - case flag.IsUint() && len(in.Uints()) > 0: + case f.IsUint() && len(in.Uints()) > 0: for _, u := range in.Uints() { if u == 0 { return ErrNotBlank @@ -61,7 +62,7 @@ func arrayNotBlank(flag input.Flag, in input.Value) error { } return nil - case flag.IsUint64() && len(in.Uint64s()) > 0: + case f.IsUint64() && len(in.Uint64s()) > 0: for _, u := range in.Uint64s() { if u == 0 { return ErrNotBlank @@ -69,7 +70,7 @@ func arrayNotBlank(flag input.Flag, in input.Value) error { } return nil - case flag.IsFloat64() && len(in.Float64s()) > 0: + case f.IsFloat64() && len(in.Float64s()) > 0: for _, f := range in.Float64s() { if f == 0 { return ErrNotBlank @@ -77,9 +78,9 @@ func arrayNotBlank(flag input.Flag, in input.Value) error { } return nil - case flag.IsBool() && len(in.Bools()) > 0: + case f.IsBool() && len(in.Bools()) > 0: return nil - case flag.IsDuration() && len(in.Durations()) > 0: + case f.IsDuration() && len(in.Durations()) > 0: for _, d := range in.Durations() { if d == 0 { return ErrNotBlank @@ -87,7 +88,7 @@ func arrayNotBlank(flag input.Flag, in input.Value) error { } return nil - case flag.IsTime() && len(in.Times()) > 0: + case f.IsTime() && len(in.Times()) > 0: for _, t := range in.Times() { if t.IsZero() { return ErrNotBlank @@ -95,7 +96,7 @@ func arrayNotBlank(flag input.Flag, in input.Value) error { } return nil - case flag.IsString() && len(in.Strings()) > 0: + case f.IsString() && len(in.Strings()) > 0: for _, st := range in.Strings() { if len(st) == 0 { return ErrNotBlank diff --git a/validator/not_blank_test.go b/input/validator/not_blank_test.go similarity index 69% rename from validator/not_blank_test.go rename to input/validator/not_blank_test.go index 6352008..6bcd610 100644 --- a/validator/not_blank_test.go +++ b/input/validator/not_blank_test.go @@ -5,90 +5,90 @@ import ( "testing" "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/validator" ) func TestNotBlank(t *testing.T) { cases := map[string]struct { - flag input.Flag - value input.Value - empty input.Value + flag flag.Flag + value value.Value + empty value.Value }{ - "any": {flag: input.ValueAny, value: value.New(float32(1))}, + "any": {flag: flag.Any, value: value.New(float32(1))}, "array int": { - flag: input.ValueInt | input.ValueArray, + flag: flag.Int | flag.Array, value: value.New([]int{1}), empty: value.New([]int{10, 20, 0}), }, "array int64": { - flag: input.ValueInt64 | input.ValueArray, + flag: flag.Int64 | flag.Array, value: value.New([]int64{1}), empty: value.New([]int64{0}), }, "array uint": { - flag: input.ValueUint | input.ValueArray, + flag: flag.Uint | flag.Array, value: value.New([]uint{1}), empty: value.New([]uint{1, 0}), }, "array uint64": { - flag: input.ValueUint64 | input.ValueArray, + flag: flag.Uint64 | flag.Array, value: value.New([]uint64{1}), empty: value.New([]uint64{0}), }, "array float64": { - flag: input.ValueFloat64 | input.ValueArray, + flag: flag.Float64 | flag.Array, value: value.New([]float64{0.2}), empty: value.New([]float64{0}), }, "array bool": { - flag: input.ValueBool | input.ValueArray, + flag: flag.Bool | flag.Array, value: value.New([]bool{true, false}), empty: value.New([]bool{}), }, "array duration": { - flag: input.ValueDuration | input.ValueArray, + flag: flag.Duration | flag.Array, value: value.New([]time.Duration{time.Second}), empty: value.New([]time.Duration{time.Second, 0}), }, "array time": { - flag: input.ValueTime | input.ValueArray, + flag: flag.Time | flag.Array, value: value.New([]time.Time{time.Now()}), empty: value.New([]time.Time{{}, time.Now()}), }, "array string": { - flag: input.ValueArray, + flag: flag.Array, value: value.New([]string{"value"}), empty: value.New([]string{""}), }, "int": { - flag: input.ValueInt, + flag: flag.Int, value: value.New(int(1)), }, "int64": { - flag: input.ValueInt64, + flag: flag.Int64, value: value.New(int64(2)), }, "uint": { - flag: input.ValueUint, + flag: flag.Uint, value: value.New(uint(1)), empty: value.New([]uint{1}), }, "uint64": { - flag: input.ValueUint64, + flag: flag.Uint64, value: value.New(uint64(10)), }, "float64": { - flag: input.ValueFloat64, + flag: flag.Float64, value: value.New(float64(.00001)), }, "duration": { - flag: input.ValueDuration, + flag: flag.Duration, value: value.New(time.Minute), 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("")}, } diff --git a/input/validator/valid.go b/input/validator/valid.go new file mode 100644 index 0000000..0345f9d --- /dev/null +++ b/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 + } +} diff --git a/validator/valid_test.go b/input/validator/valid_test.go similarity index 80% rename from validator/valid_test.go rename to input/validator/valid_test.go index 466c1ed..45fe75a 100644 --- a/validator/valid_test.go +++ b/input/validator/valid_test.go @@ -4,9 +4,9 @@ import ( "errors" "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/validator" ) func TestValid(t *testing.T) { @@ -14,7 +14,7 @@ func TestValid(t *testing.T) { invalidValue := value.New([]string{"one"}) valid := validator.Valid( - validator.NotBlank(input.ValueString), + validator.NotBlank(flag.String), validator.Enum("one", "two"), ) diff --git a/input/value.go b/input/value.go deleted file mode 100644 index bb7e976..0000000 --- a/input/value.go +++ /dev/null @@ -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 - } -} diff --git a/input/value/any.go b/input/value/any.go index 08955f6..0f4be91 100644 --- a/input/value/any.go +++ b/input/value/any.go @@ -1,11 +1,11 @@ package value -import "gitoa.ru/go-4devs/console/input" +import "gitoa.ru/go-4devs/console/input/flag" type Any struct { Empty Val []interface{} - Flag input.Flag + Flag flag.Flag } func (a *Any) Any() interface{} { diff --git a/input/value/bool.go b/input/value/bool.go index f3a99f5..1291817 100644 --- a/input/value/bool.go +++ b/input/value/bool.go @@ -3,13 +3,13 @@ package value import ( "strconv" - "gitoa.ru/go-4devs/console/input" + "gitoa.ru/go-4devs/console/input/flag" ) type Bool struct { Empty Val []bool - Flag input.Flag + Flag flag.Flag } func (b *Bool) Append(in string) error { @@ -36,7 +36,7 @@ func (b *Bool) Bools() []bool { } func (b *Bool) Any() interface{} { - if b.Flag&input.ValueArray > 0 { + if b.Flag.IsArray() { return b.Bools() } diff --git a/input/value/duration.go b/input/value/duration.go index 0935443..13e6482 100644 --- a/input/value/duration.go +++ b/input/value/duration.go @@ -3,13 +3,13 @@ package value import ( "time" - "gitoa.ru/go-4devs/console/input" + "gitoa.ru/go-4devs/console/input/flag" ) type Duration struct { Empty Val []time.Duration - Flag input.Flag + Flag flag.Flag } func (d *Duration) Append(in string) error { @@ -36,7 +36,7 @@ func (d *Duration) Durations() []time.Duration { } func (d *Duration) Any() interface{} { - if d.Flag&input.ValueArray > 0 { + if d.Flag.IsArray() { return d.Durations() } diff --git a/input/value/empty.go b/input/value/empty.go index fd4b9fe..9e239ea 100644 --- a/input/value/empty.go +++ b/input/value/empty.go @@ -1,16 +1,13 @@ package value import ( - "fmt" "time" - - "gitoa.ru/go-4devs/console/input" ) type Empty struct{} func (e *Empty) Append(string) error { - return fmt.Errorf("%w: in empty value", input.ErrInvalidName) + return ErrAppendEmpty } func (e *Empty) String() string { diff --git a/input/value/float64.go b/input/value/float64.go index b50c1e8..aa36cd9 100644 --- a/input/value/float64.go +++ b/input/value/float64.go @@ -3,13 +3,13 @@ package value import ( "strconv" - "gitoa.ru/go-4devs/console/input" + "gitoa.ru/go-4devs/console/input/flag" ) type Float64 struct { Empty Val []float64 - Flag input.Flag + Flag flag.Flag } func (f *Float64) Append(in string) error { @@ -36,7 +36,7 @@ func (f *Float64) Float64s() []float64 { } func (f *Float64) Any() interface{} { - if f.Flag&input.ValueFloat64 > 0 { + if f.Flag.IsArray() { return f.Float64s() } diff --git a/input/value/int.go b/input/value/int.go index 6ad95e7..6821924 100644 --- a/input/value/int.go +++ b/input/value/int.go @@ -3,13 +3,13 @@ package value import ( "strconv" - "gitoa.ru/go-4devs/console/input" + "gitoa.ru/go-4devs/console/input/flag" ) type Int struct { Empty Val []int - Flag input.Flag + Flag flag.Flag } func (i *Int) Append(in string) error { @@ -36,7 +36,7 @@ func (i *Int) Ints() []int { } func (i *Int) Any() interface{} { - if i.Flag&input.ValueArray > 0 { + if i.Flag.IsArray() { return i.Ints() } diff --git a/input/value/int64.go b/input/value/int64.go index bb7deb8..5ed8258 100644 --- a/input/value/int64.go +++ b/input/value/int64.go @@ -3,13 +3,13 @@ package value import ( "strconv" - "gitoa.ru/go-4devs/console/input" + "gitoa.ru/go-4devs/console/input/flag" ) type Int64 struct { Empty Val []int64 - Flag input.Flag + Flag flag.Flag } func (i *Int64) Int64() int64 { @@ -25,7 +25,7 @@ func (i *Int64) Int64s() []int64 { } func (i *Int64) Any() interface{} { - if i.Flag&input.ValueArray > 0 { + if i.Flag.IsArray() { return i.Int64s() } diff --git a/input/value/read.go b/input/value/read.go index 8e90448..144ddde 100644 --- a/input/value/read.go +++ b/input/value/read.go @@ -1,17 +1,20 @@ package value import ( - "fmt" - - "gitoa.ru/go-4devs/console/input" + "errors" ) -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 { - input.Value + Value } func (r *Read) Append(string) error { - return fmt.Errorf("%w: read value", input.ErrInvalidName) + return ErrAppendRead } diff --git a/input/value/string.go b/input/value/string.go index d138bae..9409f51 100644 --- a/input/value/string.go +++ b/input/value/string.go @@ -1,11 +1,11 @@ package value -import "gitoa.ru/go-4devs/console/input" +import "gitoa.ru/go-4devs/console/input/flag" type String struct { Empty Val []string - Flag input.Flag + Flag flag.Flag } func (s *String) Append(in string) error { diff --git a/input/value/time.go b/input/value/time.go index 9986d4a..c5c12a9 100644 --- a/input/value/time.go +++ b/input/value/time.go @@ -3,13 +3,13 @@ package value import ( "time" - "gitoa.ru/go-4devs/console/input" + "gitoa.ru/go-4devs/console/input/flag" ) type Time struct { Empty Val []time.Time - Flag input.Flag + Flag flag.Flag } func (t *Time) Append(in string) error { @@ -36,7 +36,7 @@ func (t *Time) Times() []time.Time { } func (t *Time) Amy() interface{} { - if t.Flag&input.ValueArray > 0 { + if t.Flag.IsArray() { return t.Times() } diff --git a/input/value/uint.go b/input/value/uint.go index 1561dac..9187e6b 100644 --- a/input/value/uint.go +++ b/input/value/uint.go @@ -3,13 +3,13 @@ package value import ( "strconv" - "gitoa.ru/go-4devs/console/input" + "gitoa.ru/go-4devs/console/input/flag" ) type Uint struct { Empty Val []uint - Flag input.Flag + Flag flag.Flag } func (u *Uint) Append(in string) error { @@ -36,7 +36,7 @@ func (u *Uint) Uints() []uint { } func (u *Uint) Any() interface{} { - if u.Flag&input.ValueArray > 0 { + if u.Flag.IsArray() { return u.Uints() } diff --git a/input/value/uint64.go b/input/value/uint64.go index a8b96e8..52ddd73 100644 --- a/input/value/uint64.go +++ b/input/value/uint64.go @@ -3,13 +3,13 @@ package value import ( "strconv" - "gitoa.ru/go-4devs/console/input" + "gitoa.ru/go-4devs/console/input/flag" ) type Uint64 struct { Empty Val []uint64 - Flag input.Flag + Flag flag.Flag } func (u *Uint64) Append(in string) error { @@ -36,7 +36,7 @@ func (u *Uint64) Uint64s() []uint64 { } func (u *Uint64) Any() interface{} { - if u.Flag&input.ValueArray > 0 { + if u.Flag.IsArray() { return u.Uint64s() } diff --git a/input/value/value.go b/input/value/value.go index 182bcb5..dd1766b 100644 --- a/input/value/value.go +++ b/input/value/value.go @@ -3,81 +3,109 @@ package value import ( "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 -func New(v interface{}) input.Value { +func New(v interface{}) Value { switch val := v.(type) { case string: - return &String{Val: []string{val}, Flag: input.ValueString} + return &String{Val: []string{val}, Flag: flag.String} case int: - return &Int{Val: []int{val}, Flag: input.ValueInt} + return &Int{Val: []int{val}, Flag: flag.Int} case int64: - return &Int64{Val: []int64{val}, Flag: input.ValueInt64} + return &Int64{Val: []int64{val}, Flag: flag.Int64} case uint: - return &Uint{Val: []uint{val}, Flag: input.ValueUint} + return &Uint{Val: []uint{val}, Flag: flag.Uint} case uint64: - return &Uint64{Val: []uint64{val}, Flag: input.ValueUint64} + return &Uint64{Val: []uint64{val}, Flag: flag.Uint64} case float64: - return &Float64{Val: []float64{val}, Flag: input.ValueFloat64} + return &Float64{Val: []float64{val}, Flag: flag.Float64} case bool: - return &Bool{Val: []bool{val}, Flag: input.ValueBool} + return &Bool{Val: []bool{val}, Flag: flag.Bool} case time.Duration: - return &Duration{Val: []time.Duration{val}, Flag: input.ValueDuration} + return &Duration{Val: []time.Duration{val}, Flag: flag.Duration} case time.Time: - return &Time{Val: []time.Time{val}, Flag: input.ValueTime} + return &Time{Val: []time.Time{val}, Flag: flag.Time} case []int64: - return &Int64{Val: val, Flag: input.ValueInt64 | input.ValueArray} + return &Int64{Val: val, Flag: flag.Int64 | flag.Array} case []uint: - return &Uint{Val: val, Flag: input.ValueUint | input.ValueArray} + return &Uint{Val: val, Flag: flag.Uint | flag.Array} case []uint64: - return &Uint64{Val: val, Flag: input.ValueUint64 | input.ValueArray} + return &Uint64{Val: val, Flag: flag.Uint64 | flag.Array} case []float64: - return &Float64{Val: val, Flag: input.ValueFloat64 | input.ValueArray} + return &Float64{Val: val, Flag: flag.Float64 | flag.Array} case []bool: - return &Bool{Val: val, Flag: input.ValueBool | input.ValueArray} + return &Bool{Val: val, Flag: flag.Bool | flag.Array} case []time.Duration: - return &Duration{Val: val, Flag: input.ValueDuration | input.ValueArray} + return &Duration{Val: val, Flag: flag.Duration | flag.Array} case []time.Time: - return &Time{Val: val, Flag: input.ValueTime | input.ValueArray} + return &Time{Val: val, Flag: flag.Time | flag.Array} case []string: - return &String{Val: val, Flag: input.ValueString | input.ValueArray} + return &String{Val: val, Flag: flag.String | flag.Array} case []int: - return &Int{Val: val, Flag: input.ValueInt | input.ValueArray} + return &Int{Val: val, Flag: flag.Int | flag.Array} case []interface{}: - return &Any{Val: val, Flag: input.ValueAny | input.ValueArray} - case input.Value: + return &Any{Val: val, Flag: flag.Any | flag.Array} + case Value: return val default: if v != nil { - return &Any{Val: []interface{}{v}, Flag: input.ValueAny} + return &Any{Val: []interface{}{v}, Flag: flag.Any} } return &Empty{} } } -func ByFlag(flag input.Flag) input.AppendValue { +func ByFlag(f flag.Flag) AppendValue { switch { - case flag.IsInt(): - return &Int{Flag: flag | input.ValueInt} - case flag.IsInt64(): - return &Int64{Flag: flag | input.ValueInt64} - case flag.IsUint(): - return &Uint{Flag: flag | input.ValueUint} - case flag.IsUint64(): - return &Uint64{Flag: flag | input.ValueUint64} - case flag.IsFloat64(): - return &Float64{Flag: flag | input.ValueFloat64} - case flag.IsBool(): - return &Bool{Flag: flag | input.ValueBool} - case flag.IsDuration(): - return &Duration{Flag: flag | input.ValueDuration} - case flag.IsTime(): - return &Time{Flag: flag | input.ValueTime} - case flag.IsAny(): - return &Any{Flag: flag | input.ValueAny} + case f.IsInt(): + return &Int{Flag: f | flag.Int} + case f.IsInt64(): + return &Int64{Flag: f | flag.Int64} + case f.IsUint(): + return &Uint{Flag: f | flag.Uint} + case f.IsUint64(): + return &Uint64{Flag: f | flag.Uint64} + case f.IsFloat64(): + return &Float64{Flag: f | flag.Float64} + case f.IsBool(): + return &Bool{Flag: f | flag.Bool} + case f.IsDuration(): + return &Duration{Flag: f | flag.Duration} + case f.IsTime(): + return &Time{Flag: f | flag.Time} + case f.IsAny(): + return &Any{Flag: f | flag.Any} default: return &String{} } diff --git a/input/wrap/input.go b/input/wrap/input.go index 55a7368..1e678b9 100644 --- a/input/wrap/input.go +++ b/input/wrap/input.go @@ -12,7 +12,7 @@ type Input struct { 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 { return v } @@ -20,7 +20,7 @@ func (i *Input) Option(ctx context.Context, name string) input.Value { 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 { return v } @@ -40,10 +40,6 @@ func (i *Input) Bind(ctx context.Context, def *input.Definition) error { 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 { for _, name := range def.Options() { opt, err := def.Option(name) diff --git a/list.go b/list.go index 7c0cad1..bf7e92d 100644 --- a/list.go +++ b/list.go @@ -7,9 +7,10 @@ import ( "gitoa.ru/go-4devs/console/descriptor" "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/validator" "gitoa.ru/go-4devs/console/output" - "gitoa.ru/go-4devs/console/validator" ) const defaultLenNamespace = 2 @@ -92,10 +93,10 @@ You can also output the information in other formats by using the --for formats := descriptor.Descriptors() config. SetArguments( - input.NewArgument("namespace", "The namespace name"), + argument.New("namespace", "The namespace name"), ). 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.Default(formats[0]), option.Valid( diff --git a/validator/valid.go b/validator/valid.go deleted file mode 100644 index cad205c..0000000 --- a/validator/valid.go +++ /dev/null @@ -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 - } -}