add map input
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
106
input/array.go
106
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 v := a.Map.Argument(ctx, name); !value.IsEmpty(v) {
|
||||||
if err := arg.Validate(v); err != nil {
|
if err := arg.Validate(v); err != nil {
|
||||||
return errs.Argument(name, err)
|
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()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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
Normal file
87
input/map.go
Normal file
@@ -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)
|
||||||
|
}
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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{}
|
||||||
|
|||||||
Reference in New Issue
Block a user