Browse Source

add map input

pull/2/head v0.0.1
andrey1s 4 years ago
parent
commit
596026ae92
  1. 3
      console.go
  2. 7
      input/argument/argument.go
  3. 20
      input/argv.go
  4. 110
      input/array.go
  5. 7
      input/chain.go
  6. 87
      input/map.go
  7. 7
      input/option/option.go
  8. 2
      input/validator/not_blank_test.go
  9. 8
      input/value/empty.go

3
console.go

@ -3,7 +3,6 @@ package console
import ( import (
"context" "context"
"errors" "errors"
"log"
"os" "os"
"gitoa.ru/go-4devs/console/input" "gitoa.ru/go-4devs/console/input"
@ -117,7 +116,7 @@ func showHelp(ctx context.Context, cmd *Command, in input.Input, out output.Outp
if err != nil { if err != nil {
return err return err
} }
log.Println(a)
w := input.Chain(a, in) w := input.Chain(a, in)
return Run(ctx, help, w, out) return Run(ctx, help, w, out)

7
input/argument/argument.go

@ -1,6 +1,7 @@
package argument package argument
import ( import (
"gitoa.ru/go-4devs/console/input/errs"
"gitoa.ru/go-4devs/console/input/value" "gitoa.ru/go-4devs/console/input/value"
"gitoa.ru/go-4devs/console/input/value/flag" "gitoa.ru/go-4devs/console/input/value/flag"
) )
@ -45,13 +46,9 @@ func (a Argument) IsArray() bool {
func (a Argument) Validate(v value.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 Error(a.Name, err) return errs.Argument(a.Name, err)
} }
} }
return nil return nil
} }
func Error(name string, err error) error {
return err
}

20
input/argv.go

@ -7,7 +7,6 @@ import (
"gitoa.ru/go-4devs/console/input/errs" "gitoa.ru/go-4devs/console/input/errs"
"gitoa.ru/go-4devs/console/input/option" "gitoa.ru/go-4devs/console/input/option"
"gitoa.ru/go-4devs/console/input/value"
) )
const doubleDash = `--` const doubleDash = `--`
@ -72,9 +71,7 @@ func (i *Argv) parseLongOption(arg string, def *Definition) error {
} }
func (i *Argv) appendOption(name string, data *string, opt option.Option) error { func (i *Argv) appendOption(name string, data *string, opt option.Option) error {
v, ok := i.GetOption(name) if i.HasOption(name) && !opt.IsArray() {
if ok && !opt.IsArray() {
return fmt.Errorf("%w: got: array, expect: %s", errs.ErrUnexpectedType, opt.Flag.Type()) return fmt.Errorf("%w: got: array, expect: %s", errs.ErrUnexpectedType, opt.Flag.Type())
} }
@ -92,12 +89,7 @@ func (i *Argv) appendOption(name string, data *string, opt option.Option) error
return errs.Option(name, errs.ErrRequired) return errs.Option(name, errs.ErrRequired)
} }
if !ok { if err := i.AppendOption(opt.Flag, name, val); err != nil {
v = value.ByFlag(opt.Flag)
i.SetOption(name, v)
}
if err := v.Append(val); err != nil {
return errs.Option(name, err) return errs.Option(name, err)
} }
@ -139,13 +131,7 @@ func (i *Argv) parseArgument(arg string, def *Definition) error {
return err return err
} }
v, ok := i.GetArgument(opt.Name) if err := i.AppendArgument(opt.Flag, opt.Name, arg); err != nil {
if !ok {
v = value.ByFlag(opt.Flag)
i.SetArgument(opt.Name, v)
}
if err := v.Append(arg); err != nil {
return errs.Argument(opt.Name, err) return errs.Argument(opt.Name, err)
} }

110
input/array.go

@ -2,78 +2,56 @@ package input
import ( import (
"context" "context"
"sync"
"gitoa.ru/go-4devs/console/input/errs" "gitoa.ru/go-4devs/console/input/errs"
"gitoa.ru/go-4devs/console/input/value" "gitoa.ru/go-4devs/console/input/value"
) )
type Array struct { type Array struct {
defaults array Map
value array defaults Map
} }
func (a *Array) GetOption(name string) (value.Append, bool) { func (a *Array) Option(ctx context.Context, name string) value.Value {
return a.value.GetOption(name) if v := a.Map.Option(ctx, name); !value.IsEmpty(v) {
}
func (a *Array) SetOption(name string, v interface{}) {
a.value.SetOption(name, v)
}
func (a *Array) LenArguments() int {
return a.value.LenArguments()
}
func (a *Array) GetArgument(name string) (value.Append, bool) {
return a.value.GetArgument(name)
}
func (a *Array) SetArgument(name string, v interface{}) {
a.value.SetArgument(name, v)
}
func (a *Array) Option(_ context.Context, name string) value.Value {
if v, ok := a.value.GetOption(name); ok {
return v return v
} }
if v, ok := a.defaults.GetOption(name); ok { if v := a.defaults.Option(ctx, name); !value.IsEmpty(v) {
return v return v
} }
return value.Empty return value.Empty()
} }
func (a *Array) Argument(_ context.Context, name string) value.Value { func (a *Array) Argument(ctx context.Context, name string) value.Value {
if v, ok := a.value.GetArgument(name); ok { if v := a.Map.Argument(ctx, name); !value.IsEmpty(v) {
return v return v
} }
if v, ok := a.defaults.GetArgument(name); ok { if v := a.defaults.Argument(ctx, name); !value.IsEmpty(v) {
return v return v
} }
return value.Empty return value.Empty()
} }
func (a *Array) Bind(ctx context.Context, d *Definition) error { func (a *Array) Bind(ctx context.Context, d *Definition) error {
if err := a.bindArguments(d); err != nil { if err := a.bindArguments(ctx, d); err != nil {
return err return err
} }
return a.bindOption(d) return a.bindOption(ctx, d)
} }
func (a *Array) bindOption(def *Definition) error { func (a *Array) bindOption(ctx context.Context, def *Definition) error {
for _, name := range def.Options() { for _, name := range def.Options() {
opt, err := def.Option(name) opt, err := def.Option(name)
if err != nil { if err != nil {
return err return err
} }
v, ok := a.value.GetOption(name) if !a.HasOption(name) {
if !ok {
switch { switch {
case opt.HasDefault(): case opt.HasDefault():
a.defaults.SetOption(name, opt.Default) a.defaults.SetOption(name, opt.Default)
@ -86,7 +64,10 @@ func (a *Array) bindOption(def *Definition) error {
} }
} }
a.SetOption(name, v) v := a.Map.Option(ctx, name)
if value.IsEmpty(v) {
continue
}
if err := opt.Validate(v); err != nil { if err := opt.Validate(v); err != nil {
return errs.Option(name, err) return errs.Option(name, err)
@ -96,15 +77,14 @@ func (a *Array) bindOption(def *Definition) error {
return nil return nil
} }
func (a *Array) bindArguments(def *Definition) error { func (a *Array) bindArguments(ctx context.Context, def *Definition) error {
for pos, name := range def.Arguments() { for pos, name := range def.Arguments() {
arg, err := def.Argument(pos) arg, err := def.Argument(pos)
if err != nil { if err != nil {
return err return err
} }
v, ok := a.value.GetArgument(name) if !a.HasArgument(name) {
if !ok {
switch { switch {
case arg.HasDefault(): case arg.HasDefault():
a.defaults.SetArgument(name, arg.Default) a.defaults.SetArgument(name, arg.Default)
@ -117,54 +97,12 @@ func (a *Array) bindArguments(def *Definition) error {
} }
} }
if err := arg.Validate(v); err != nil { if v := a.Map.Argument(ctx, name); !value.IsEmpty(v) {
return errs.Argument(name, err) if err := arg.Validate(v); err != nil {
return errs.Argument(name, err)
}
} }
a.SetArgument(name, v)
} }
return nil return nil
} }
type array struct {
opts map[string]value.Append
args map[string]value.Append
mu sync.Mutex
}
func (a *array) GetOption(name string) (value.Append, bool) {
v, ok := a.opts[name]
return v, ok
}
func (a *array) SetOption(name string, v interface{}) {
if a.opts == nil {
a.opts = make(map[string]value.Append)
}
a.mu.Lock()
a.opts[name] = value.New(v)
a.mu.Unlock()
}
func (a *array) LenArguments() int {
return len(a.args)
}
func (a *array) GetArgument(name string) (value.Append, bool) {
v, ok := a.args[name]
return v, ok
}
func (a *array) SetArgument(name string, v interface{}) {
if a.args == nil {
a.args = make(map[string]value.Append)
}
a.mu.Lock()
a.args[name] = value.New(v)
a.mu.Unlock()
}

7
input/chain.go

@ -2,7 +2,6 @@ package input
import ( import (
"context" "context"
"log"
"gitoa.ru/go-4devs/console/input/value" "gitoa.ru/go-4devs/console/input/value"
) )
@ -14,15 +13,13 @@ func Chain(c ...Input) Input {
type chain []Input type chain []Input
func (c chain) Option(ctx context.Context, name string) value.Value { func (c chain) Option(ctx context.Context, name string) value.Value {
log.Println(name, len(c))
for _, in := range c { for _, in := range c {
log.Printf("%T\n", in)
if val := in.Option(ctx, name); !value.IsEmpty(val) { if val := in.Option(ctx, name); !value.IsEmpty(val) {
return val return val
} }
} }
return value.Empty return value.Empty()
} }
func (c chain) Argument(ctx context.Context, name string) value.Value { func (c chain) Argument(ctx context.Context, name string) value.Value {
@ -32,7 +29,7 @@ func (c chain) Argument(ctx context.Context, name string) value.Value {
} }
} }
return value.Empty return value.Empty()
} }
func (c chain) Bind(ctx context.Context, def *Definition) error { func (c chain) Bind(ctx context.Context, def *Definition) error {

87
input/map.go

@ -0,0 +1,87 @@
package input
import (
"context"
"sync"
"gitoa.ru/go-4devs/console/input/value"
"gitoa.ru/go-4devs/console/input/value/flag"
)
type Map struct {
opts map[string]value.Append
args map[string]value.Append
sync.Mutex
}
func (m *Map) Option(_ context.Context, name string) value.Value {
m.Lock()
defer m.Unlock()
return m.opts[name]
}
func (m *Map) Argument(_ context.Context, name string) value.Value {
m.Lock()
defer m.Unlock()
return m.args[name]
}
func (m *Map) Bind(_ context.Context, _ *Definition) error {
return nil
}
func (m *Map) LenArguments() int {
return len(m.args)
}
func (m *Map) HasOption(name string) bool {
_, ok := m.opts[name]
return ok
}
func (m *Map) SetOption(name string, v interface{}) {
m.Lock()
defer m.Unlock()
if m.opts == nil {
m.opts = make(map[string]value.Append)
}
m.opts[name] = value.New(v)
}
func (m *Map) HasArgument(name string) bool {
_, ok := m.args[name]
return ok
}
func (m *Map) SetArgument(name string, v interface{}) {
m.Lock()
defer m.Unlock()
if m.args == nil {
m.args = make(map[string]value.Append)
}
m.args[name] = value.New(v)
}
func (m *Map) AppendOption(f flag.Flag, name, val string) error {
if _, ok := m.opts[name]; !ok {
m.SetOption(name, value.ByFlag(f))
}
return m.opts[name].Append(val)
}
func (m *Map) AppendArgument(f flag.Flag, name, val string) error {
if _, ok := m.args[name]; !ok {
m.SetArgument(name, value.ByFlag(f))
}
return m.args[name].Append(val)
}

7
input/option/option.go

@ -1,6 +1,7 @@
package option package option
import ( import (
"gitoa.ru/go-4devs/console/input/errs"
"gitoa.ru/go-4devs/console/input/value" "gitoa.ru/go-4devs/console/input/value"
"gitoa.ru/go-4devs/console/input/value/flag" "gitoa.ru/go-4devs/console/input/value/flag"
) )
@ -88,13 +89,9 @@ func (o Option) IsRequired() bool {
func (o Option) Validate(v value.Value) error { func (o Option) Validate(v value.Value) error {
for _, valid := range o.Valid { for _, valid := range o.Valid {
if err := valid(v); err != nil { if err := valid(v); err != nil {
return Error(o.Name, err) return errs.Option(o.Name, err)
} }
} }
return nil return nil
} }
func Error(name string, err error) error {
return err
}

2
input/validator/not_blank_test.go

@ -99,7 +99,7 @@ func TestNotBlank(t *testing.T) {
} }
if ca.empty == nil { if ca.empty == nil {
ca.empty = value.Empty ca.empty = value.Empty()
} }
if err := valid(ca.empty); err == nil || !errors.Is(err, validator.ErrNotBlank) { if err := valid(ca.empty); err == nil || !errors.Is(err, validator.ErrNotBlank) {

8
input/value/empty.go

@ -6,11 +6,15 @@ import (
// nolint: gochecknoglobals // nolint: gochecknoglobals
var ( var (
Empty = &empty{} emptyValue = &empty{}
) )
func Empty() Value {
return emptyValue
}
func IsEmpty(v Value) bool { func IsEmpty(v Value) bool {
return v == nil || v == Empty return v == nil || v == emptyValue
} }
type empty struct{} type empty struct{}

Loading…
Cancel
Save