first commit
This commit is contained in:
48
input/argument.go
Normal file
48
input/argument.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package input
|
||||
|
||||
func NewArgument(name, description string, opts ...func(*Argument)) Argument {
|
||||
a := Argument{
|
||||
Name: name,
|
||||
Description: description,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(&a)
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
type Argument struct {
|
||||
Name string
|
||||
Description string
|
||||
Default Value
|
||||
Flag Flag
|
||||
Valid []func(Value) error
|
||||
}
|
||||
|
||||
func (a Argument) HasDefault() bool {
|
||||
return a.Default != nil
|
||||
}
|
||||
|
||||
func (a Argument) IsBool() bool {
|
||||
return a.Flag.IsBool()
|
||||
}
|
||||
|
||||
func (a Argument) IsRequired() bool {
|
||||
return a.Flag.IsRequired()
|
||||
}
|
||||
|
||||
func (a Argument) IsArray() bool {
|
||||
return a.Flag.IsArray()
|
||||
}
|
||||
|
||||
func (a Argument) Validate(v Value) error {
|
||||
for _, valid := range a.Valid {
|
||||
if err := valid(v); err != nil {
|
||||
return ErrorArgument(a.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
26
input/argument/option.go
Normal file
26
input/argument/option.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package argument
|
||||
|
||||
import (
|
||||
"gitoa.ru/go-4devs/console/input"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
func Required(a *input.Argument) {
|
||||
a.Flag |= input.ValueRequired
|
||||
}
|
||||
|
||||
func Default(v interface{}) func(*input.Argument) {
|
||||
return func(a *input.Argument) {
|
||||
a.Default = value.New(v)
|
||||
}
|
||||
}
|
||||
|
||||
func Flag(flag input.Flag) func(*input.Argument) {
|
||||
return func(a *input.Argument) {
|
||||
a.Flag = flag
|
||||
}
|
||||
}
|
||||
|
||||
func Array(a *input.Argument) {
|
||||
a.Flag |= input.ValueArray
|
||||
}
|
||||
211
input/argv/input.go
Normal file
211
input/argv/input.go
Normal file
@@ -0,0 +1,211 @@
|
||||
package argv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
"gitoa.ru/go-4devs/console/input/wrap"
|
||||
)
|
||||
|
||||
const doubleDash = `--`
|
||||
|
||||
var _ input.ReadInput = (*Input)(nil)
|
||||
|
||||
func WithErrorHandle(h func(error) error) func(*Input) {
|
||||
return func(i *Input) {
|
||||
i.errorHandle = h
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
errorHandle: func(err error) error {
|
||||
return err
|
||||
},
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(i)
|
||||
}
|
||||
|
||||
return &wrap.Input{ReadInput: i}
|
||||
}
|
||||
|
||||
type Input struct {
|
||||
args []string
|
||||
arguments map[string]input.AppendValue
|
||||
options map[string]input.AppendValue
|
||||
mu sync.RWMutex
|
||||
errorHandle func(error) error
|
||||
}
|
||||
|
||||
func (i *Input) ReadOption(ctx context.Context, name string) (input.Value, error) {
|
||||
if v, ok := i.options[name]; ok {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
return nil, input.ErrNotFound
|
||||
}
|
||||
|
||||
func (i *Input) SetOption(name string, val input.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) {
|
||||
if v, ok := i.arguments[name]; ok {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
return nil, input.ErrNotFound
|
||||
}
|
||||
|
||||
func (i *Input) SetArgument(name string, val input.Value) {
|
||||
i.mu.Lock()
|
||||
defer i.mu.Unlock()
|
||||
|
||||
i.arguments[name] = &value.Read{Value: val}
|
||||
}
|
||||
|
||||
func (i *Input) Bind(ctx context.Context, def *input.Definition) error {
|
||||
options := true
|
||||
|
||||
for len(i.args) > 0 {
|
||||
var err error
|
||||
|
||||
arg := i.args[0]
|
||||
i.args = i.args[1:]
|
||||
|
||||
switch {
|
||||
case options && arg == doubleDash:
|
||||
options = false
|
||||
case options && len(arg) > 2 && arg[0:2] == doubleDash:
|
||||
err = i.parseLongOption(arg[2:], def)
|
||||
case options && arg[0:1] == "-":
|
||||
if len(arg) == 1 {
|
||||
return fmt.Errorf("%w: option name required given '-'", input.ErrInvalidName)
|
||||
}
|
||||
|
||||
err = i.parseShortOption(arg[1:], def)
|
||||
default:
|
||||
err = i.parseArgument(arg, def)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if herr := i.errorHandle(err); herr != nil {
|
||||
return herr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *Input) parseLongOption(arg string, def *input.Definition) error {
|
||||
var value *string
|
||||
|
||||
name := arg
|
||||
|
||||
if strings.Contains(arg, "=") {
|
||||
vals := strings.SplitN(arg, "=", 2)
|
||||
name = vals[0]
|
||||
value = &vals[1]
|
||||
}
|
||||
|
||||
opt, err := def.Option(name)
|
||||
if err != nil {
|
||||
return input.ErrorOption(name, err)
|
||||
}
|
||||
|
||||
return i.appendOption(name, value, opt)
|
||||
}
|
||||
|
||||
func (i *Input) appendOption(name string, data *string, opt input.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))
|
||||
}
|
||||
|
||||
var val string
|
||||
|
||||
switch {
|
||||
case data != nil:
|
||||
val = *data
|
||||
case opt.IsBool():
|
||||
val = "true"
|
||||
case len(i.args) > 0 && len(i.args[0]) > 0 && i.args[0][0:1] != "-":
|
||||
val = i.args[0]
|
||||
i.args = i.args[1:]
|
||||
default:
|
||||
return input.ErrorOption(name, input.ErrRequired)
|
||||
}
|
||||
|
||||
if !ok {
|
||||
v = value.ByFlag(opt.Flag)
|
||||
i.options[name] = v
|
||||
}
|
||||
|
||||
if err := v.Append(val); err != nil {
|
||||
return input.ErrorOption(name, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *Input) parseShortOption(arg string, def *input.Definition) error {
|
||||
name := arg
|
||||
|
||||
var value string
|
||||
|
||||
if len(name) > 1 {
|
||||
name, value = arg[0:1], arg[1:]
|
||||
}
|
||||
|
||||
opt, err := def.ShortOption(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if opt.IsBool() && value != "" {
|
||||
if err := i.parseShortOption(value, def); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
value = ""
|
||||
}
|
||||
|
||||
if value == "" {
|
||||
return i.appendOption(opt.Name, nil, opt)
|
||||
}
|
||||
|
||||
return i.appendOption(opt.Name, &value, opt)
|
||||
}
|
||||
|
||||
func (i *Input) parseArgument(arg string, def *input.Definition) error {
|
||||
opt, err := def.Argument(len(i.arguments))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v, ok := i.arguments[opt.Name]
|
||||
if !ok {
|
||||
v = value.ByFlag(opt.Flag)
|
||||
i.arguments[opt.Name] = v
|
||||
}
|
||||
|
||||
if err := v.Append(arg); err != nil {
|
||||
return input.ErrorArgument(opt.Name, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
87
input/array/input.go
Normal file
87
input/array/input.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package array
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
"gitoa.ru/go-4devs/console/input/wrap"
|
||||
)
|
||||
|
||||
var _ input.ReadInput = (*Input)(nil)
|
||||
|
||||
func Argument(name string, v interface{}) func(*Input) {
|
||||
return func(i *Input) {
|
||||
i.args[name] = value.New(v)
|
||||
}
|
||||
}
|
||||
|
||||
func Option(name string, v interface{}) func(*Input) {
|
||||
return func(i *Input) {
|
||||
i.opt[name] = value.New(v)
|
||||
}
|
||||
}
|
||||
|
||||
func New(opts ...func(*Input)) *wrap.Input {
|
||||
i := &Input{
|
||||
args: make(map[string]input.Value),
|
||||
opt: make(map[string]input.Value),
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(i)
|
||||
}
|
||||
|
||||
return &wrap.Input{ReadInput: i}
|
||||
}
|
||||
|
||||
type Input struct {
|
||||
args map[string]input.Value
|
||||
opt map[string]input.Value
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func (i *Input) ReadOption(_ context.Context, name string) (input.Value, error) {
|
||||
if o, has := i.opt[name]; has {
|
||||
return o, nil
|
||||
}
|
||||
|
||||
return nil, input.ErrorOption(name, input.ErrNotFound)
|
||||
}
|
||||
|
||||
func (i *Input) HasOption(name string) bool {
|
||||
_, has := i.opt[name]
|
||||
|
||||
return has
|
||||
}
|
||||
|
||||
func (i *Input) SetOption(name string, val input.Value) {
|
||||
i.mu.Lock()
|
||||
i.opt[name] = val
|
||||
i.mu.Unlock()
|
||||
}
|
||||
|
||||
func (i *Input) ReadArgument(_ context.Context, name string) (input.Value, error) {
|
||||
if a, has := i.args[name]; has {
|
||||
return a, nil
|
||||
}
|
||||
|
||||
return nil, input.ErrorArgument(name, input.ErrNotFound)
|
||||
}
|
||||
|
||||
func (i *Input) HasArgument(name string) bool {
|
||||
_, has := i.args[name]
|
||||
|
||||
return has
|
||||
}
|
||||
|
||||
func (i *Input) SetArgument(name string, val input.Value) {
|
||||
i.mu.Lock()
|
||||
i.args[name] = val
|
||||
i.mu.Unlock()
|
||||
}
|
||||
|
||||
func (i *Input) Bind(_ context.Context, def *input.Definition) error {
|
||||
return nil
|
||||
}
|
||||
95
input/definition.go
Normal file
95
input/definition.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package input
|
||||
|
||||
func NewDefinition() *Definition {
|
||||
return &Definition{
|
||||
options: make(map[string]Option),
|
||||
args: make(map[string]Argument),
|
||||
short: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
type Definition struct {
|
||||
options map[string]Option
|
||||
posOpt []string
|
||||
args map[string]Argument
|
||||
posArgs []string
|
||||
short map[string]string
|
||||
}
|
||||
|
||||
func (d *Definition) Options() []string {
|
||||
return d.posOpt
|
||||
}
|
||||
|
||||
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) SetOptions(opts ...Option) *Definition {
|
||||
for _, opt := range opts {
|
||||
if _, has := d.options[opt.Name]; !has {
|
||||
d.posOpt = append([]string{opt.Name}, d.posOpt...)
|
||||
}
|
||||
|
||||
d.options[opt.Name] = opt
|
||||
if opt.HasShort() {
|
||||
d.short[opt.Short] = opt.Name
|
||||
}
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Definition) SetArgument(name, description string, opts ...func(*Argument)) *Definition {
|
||||
return d.SetArguments(NewArgument(name, description, opts...))
|
||||
}
|
||||
|
||||
func (d *Definition) SetArguments(args ...Argument) *Definition {
|
||||
for _, arg := range args {
|
||||
if _, ok := d.args[arg.Name]; !ok {
|
||||
d.posArgs = append(d.posArgs, arg.Name)
|
||||
}
|
||||
|
||||
d.args[arg.Name] = arg
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Definition) Argument(pos int) (Argument, error) {
|
||||
if len(d.posArgs) == 0 {
|
||||
return Argument{}, ErrNoArgs
|
||||
}
|
||||
|
||||
lastPos := len(d.posArgs) - 1
|
||||
if lastPos < pos {
|
||||
arg := d.args[d.posArgs[lastPos]]
|
||||
if arg.IsArray() {
|
||||
return arg, nil
|
||||
}
|
||||
|
||||
return Argument{}, ErrToManyArgs
|
||||
}
|
||||
|
||||
return d.args[d.posArgs[pos]], nil
|
||||
}
|
||||
|
||||
func (d *Definition) ShortOption(short string) (Option, error) {
|
||||
name, ok := d.short[short]
|
||||
if !ok {
|
||||
return Option{}, ErrNotFound
|
||||
}
|
||||
|
||||
return d.Option(name)
|
||||
}
|
||||
|
||||
func (d *Definition) Option(name string) (Option, error) {
|
||||
if opt, ok := d.options[name]; ok {
|
||||
return opt, nil
|
||||
}
|
||||
|
||||
return Option{}, ErrNotFound
|
||||
}
|
||||
50
input/error.go
Normal file
50
input/error.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package input
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotFound = errors.New("not found")
|
||||
ErrNoArgs = errors.New("no arguments expected")
|
||||
ErrToManyArgs = errors.New("too many arguments")
|
||||
ErrUnexpectedType = errors.New("unexpected type")
|
||||
ErrRequired = errors.New("is required")
|
||||
ErrAppend = errors.New("failed append")
|
||||
ErrInvalidName = errors.New("invalid name")
|
||||
)
|
||||
|
||||
type Error struct {
|
||||
name string
|
||||
err error
|
||||
t string
|
||||
}
|
||||
|
||||
func (o Error) Error() string {
|
||||
return fmt.Sprintf("%s: '%s' %s", o.t, o.name, o.err)
|
||||
}
|
||||
|
||||
func (o Error) Is(err error) bool {
|
||||
return errors.Is(err, o.err)
|
||||
}
|
||||
|
||||
func (o Error) Unwrap() error {
|
||||
return o.err
|
||||
}
|
||||
|
||||
func ErrorOption(name string, err error) Error {
|
||||
return Error{
|
||||
name: name,
|
||||
err: err,
|
||||
t: "option",
|
||||
}
|
||||
}
|
||||
|
||||
func ErrorArgument(name string, err error) Error {
|
||||
return Error{
|
||||
name: name,
|
||||
err: err,
|
||||
t: "argument",
|
||||
}
|
||||
}
|
||||
76
input/flag.go
Normal file
76
input/flag.go
Normal file
@@ -0,0 +1,76 @@
|
||||
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
|
||||
}
|
||||
47
input/flag_string.go
Normal file
47
input/flag_string.go
Normal file
@@ -0,0 +1,47 @@
|
||||
// Code generated by "stringer -type=Flag -linecomment"; DO NOT EDIT.
|
||||
|
||||
package input
|
||||
|
||||
import "strconv"
|
||||
|
||||
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]
|
||||
}
|
||||
|
||||
const _Flag_name = "stringrequiredarrayintint64uintuint64float64booldurationtimeany"
|
||||
|
||||
var _Flag_map = map[Flag]string{
|
||||
0: _Flag_name[0:6],
|
||||
2: _Flag_name[6:14],
|
||||
4: _Flag_name[14:19],
|
||||
8: _Flag_name[19:22],
|
||||
16: _Flag_name[22:27],
|
||||
32: _Flag_name[27:31],
|
||||
64: _Flag_name[31:37],
|
||||
128: _Flag_name[37:44],
|
||||
256: _Flag_name[44:48],
|
||||
512: _Flag_name[48:56],
|
||||
1024: _Flag_name[56:60],
|
||||
2048: _Flag_name[60:63],
|
||||
}
|
||||
|
||||
func (i Flag) String() string {
|
||||
if str, ok := _Flag_map[i]; ok {
|
||||
return str
|
||||
}
|
||||
return "Flag(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
21
input/input.go
Normal file
21
input/input.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package input
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type ReadInput interface {
|
||||
Bind(ctx context.Context, def *Definition) error
|
||||
|
||||
ReadOption(ctx context.Context, name string) (Value, error)
|
||||
SetOption(name string, value Value)
|
||||
|
||||
ReadArgument(ctx context.Context, name string) (Value, error)
|
||||
SetArgument(name string, value Value)
|
||||
}
|
||||
|
||||
type Input interface {
|
||||
Option(ctx context.Context, name string) Value
|
||||
Argument(ctx context.Context, name string) Value
|
||||
ReadInput
|
||||
}
|
||||
53
input/option.go
Normal file
53
input/option.go
Normal file
@@ -0,0 +1,53 @@
|
||||
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
|
||||
}
|
||||
35
input/option/helpers.go
Normal file
35
input/option/helpers.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package option
|
||||
|
||||
import "gitoa.ru/go-4devs/console/input"
|
||||
|
||||
func Bool(name, description string, opts ...func(*input.Option)) input.Option {
|
||||
return input.NewOption(name, description, append(opts, Value(input.ValueBool))...)
|
||||
}
|
||||
|
||||
func Duration(name, description string, opts ...func(*input.Option)) input.Option {
|
||||
return input.NewOption(name, description, append(opts, Value(input.ValueDuration))...)
|
||||
}
|
||||
|
||||
func Float64(name, description string, opts ...func(*input.Option)) input.Option {
|
||||
return input.NewOption(name, description, append(opts, Value(input.ValueFloat64))...)
|
||||
}
|
||||
|
||||
func Int(name, description string, opts ...func(*input.Option)) input.Option {
|
||||
return input.NewOption(name, description, append(opts, Value(input.ValueInt))...)
|
||||
}
|
||||
|
||||
func Int64(name, description string, opts ...func(*input.Option)) input.Option {
|
||||
return input.NewOption(name, description, append(opts, Value(input.ValueInt64))...)
|
||||
}
|
||||
|
||||
func Time(name, description string, opts ...func(*input.Option)) input.Option {
|
||||
return input.NewOption(name, description, append(opts, Value(input.ValueTime))...)
|
||||
}
|
||||
|
||||
func Uint(name, description string, opts ...func(*input.Option)) input.Option {
|
||||
return input.NewOption(name, description, append(opts, Value(input.ValueUint))...)
|
||||
}
|
||||
|
||||
func Uint64(name, descriontion string, opts ...func(*input.Option)) input.Option {
|
||||
return input.NewOption(name, descriontion, append(opts, Value(input.ValueUint64))...)
|
||||
}
|
||||
44
input/option/option.go
Normal file
44
input/option/option.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package option
|
||||
|
||||
import (
|
||||
"gitoa.ru/go-4devs/console/input"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
func Required(o *input.Option) {
|
||||
o.Flag |= input.ValueRequired
|
||||
}
|
||||
|
||||
func Default(in interface{}) func(*input.Option) {
|
||||
return func(o *input.Option) {
|
||||
o.Default = value.New(in)
|
||||
}
|
||||
}
|
||||
|
||||
func Short(s string) func(*input.Option) {
|
||||
return func(o *input.Option) {
|
||||
o.Short = s
|
||||
}
|
||||
}
|
||||
|
||||
func Array(o *input.Option) {
|
||||
o.Flag |= input.ValueArray
|
||||
}
|
||||
|
||||
func Value(flag input.Flag) func(*input.Option) {
|
||||
return func(o *input.Option) {
|
||||
o.Flag |= flag
|
||||
}
|
||||
}
|
||||
|
||||
func Flag(in input.Flag) func(*input.Option) {
|
||||
return func(o *input.Option) {
|
||||
o.Flag = in
|
||||
}
|
||||
}
|
||||
|
||||
func Valid(f ...func(input.Value) error) func(*input.Option) {
|
||||
return func(o *input.Option) {
|
||||
o.Valid = f
|
||||
}
|
||||
}
|
||||
58
input/value.go
Normal file
58
input/value.go
Normal file
@@ -0,0 +1,58 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
21
input/value/any.go
Normal file
21
input/value/any.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package value
|
||||
|
||||
import "gitoa.ru/go-4devs/console/input"
|
||||
|
||||
type Any struct {
|
||||
Empty
|
||||
Val []interface{}
|
||||
Flag input.Flag
|
||||
}
|
||||
|
||||
func (a *Any) Any() interface{} {
|
||||
if a.Flag.IsArray() {
|
||||
return a.Val
|
||||
}
|
||||
|
||||
if len(a.Val) > 0 {
|
||||
return a.Val[0]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
44
input/value/bool.go
Normal file
44
input/value/bool.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package value
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input"
|
||||
)
|
||||
|
||||
type Bool struct {
|
||||
Empty
|
||||
Val []bool
|
||||
Flag input.Flag
|
||||
}
|
||||
|
||||
func (b *Bool) Append(in string) error {
|
||||
v, err := strconv.ParseBool(in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b.Val = append(b.Val, v)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Bool) Bool() bool {
|
||||
if !b.Flag.IsArray() && len(b.Val) == 1 {
|
||||
return b.Val[0]
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (b *Bool) Bools() []bool {
|
||||
return b.Val
|
||||
}
|
||||
|
||||
func (b *Bool) Any() interface{} {
|
||||
if b.Flag&input.ValueArray > 0 {
|
||||
return b.Bools()
|
||||
}
|
||||
|
||||
return b.Bool()
|
||||
}
|
||||
44
input/value/duration.go
Normal file
44
input/value/duration.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package value
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input"
|
||||
)
|
||||
|
||||
type Duration struct {
|
||||
Empty
|
||||
Val []time.Duration
|
||||
Flag input.Flag
|
||||
}
|
||||
|
||||
func (d *Duration) Append(in string) error {
|
||||
v, err := time.ParseDuration(in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.Val = append(d.Val, v)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Duration) Duration() time.Duration {
|
||||
if !d.Flag.IsArray() && len(d.Val) == 1 {
|
||||
return d.Val[0]
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (d *Duration) Durations() []time.Duration {
|
||||
return d.Val
|
||||
}
|
||||
|
||||
func (d *Duration) Any() interface{} {
|
||||
if d.Flag&input.ValueArray > 0 {
|
||||
return d.Durations()
|
||||
}
|
||||
|
||||
return d.Duration()
|
||||
}
|
||||
90
input/value/empty.go
Normal file
90
input/value/empty.go
Normal file
@@ -0,0 +1,90 @@
|
||||
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)
|
||||
}
|
||||
|
||||
func (e *Empty) String() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (e *Empty) Int() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Empty) Int64() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Empty) Uint() uint {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Empty) Uint64() uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Empty) Float64() float64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Empty) Bool() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (e *Empty) Duration() time.Duration {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Empty) Time() time.Time {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func (e *Empty) Strings() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Ints() []int {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Int64s() []int64 {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Uints() []uint {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Uint64s() []uint64 {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Float64s() []float64 {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Bools() []bool {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Durations() []time.Duration {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Times() []time.Time {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Any() interface{} {
|
||||
return nil
|
||||
}
|
||||
44
input/value/float64.go
Normal file
44
input/value/float64.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package value
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input"
|
||||
)
|
||||
|
||||
type Float64 struct {
|
||||
Empty
|
||||
Val []float64
|
||||
Flag input.Flag
|
||||
}
|
||||
|
||||
func (f *Float64) Append(in string) error {
|
||||
v, err := strconv.ParseFloat(in, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f.Val = append(f.Val, v)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Float64) Float64() float64 {
|
||||
if !f.Flag.IsArray() && len(f.Val) == 1 {
|
||||
return f.Val[0]
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (f *Float64) Float64s() []float64 {
|
||||
return f.Val
|
||||
}
|
||||
|
||||
func (f *Float64) Any() interface{} {
|
||||
if f.Flag&input.ValueFloat64 > 0 {
|
||||
return f.Float64s()
|
||||
}
|
||||
|
||||
return f.Float64()
|
||||
}
|
||||
44
input/value/int.go
Normal file
44
input/value/int.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package value
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input"
|
||||
)
|
||||
|
||||
type Int struct {
|
||||
Empty
|
||||
Val []int
|
||||
Flag input.Flag
|
||||
}
|
||||
|
||||
func (i *Int) Append(in string) error {
|
||||
v, err := strconv.Atoi(in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i.Val = append(i.Val, v)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *Int) Int() int {
|
||||
if !i.Flag.IsArray() && len(i.Val) == 1 {
|
||||
return i.Val[0]
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (i *Int) Ints() []int {
|
||||
return i.Val
|
||||
}
|
||||
|
||||
func (i *Int) Any() interface{} {
|
||||
if i.Flag&input.ValueArray > 0 {
|
||||
return i.Ints()
|
||||
}
|
||||
|
||||
return i.Int()
|
||||
}
|
||||
44
input/value/int64.go
Normal file
44
input/value/int64.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package value
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input"
|
||||
)
|
||||
|
||||
type Int64 struct {
|
||||
Empty
|
||||
Val []int64
|
||||
Flag input.Flag
|
||||
}
|
||||
|
||||
func (i *Int64) Int64() int64 {
|
||||
if !i.Flag.IsArray() && len(i.Val) == 1 {
|
||||
return i.Val[0]
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (i *Int64) Int64s() []int64 {
|
||||
return i.Val
|
||||
}
|
||||
|
||||
func (i *Int64) Any() interface{} {
|
||||
if i.Flag&input.ValueArray > 0 {
|
||||
return i.Int64s()
|
||||
}
|
||||
|
||||
return i.Int64()
|
||||
}
|
||||
|
||||
func (i *Int64) Append(in string) error {
|
||||
v, err := strconv.ParseInt(in, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i.Val = append(i.Val, v)
|
||||
|
||||
return nil
|
||||
}
|
||||
17
input/value/read.go
Normal file
17
input/value/read.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package value
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input"
|
||||
)
|
||||
|
||||
var _ input.AppendValue = (*Read)(nil)
|
||||
|
||||
type Read struct {
|
||||
input.Value
|
||||
}
|
||||
|
||||
func (r *Read) Append(string) error {
|
||||
return fmt.Errorf("%w: read value", input.ErrInvalidName)
|
||||
}
|
||||
39
input/value/string.go
Normal file
39
input/value/string.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package value
|
||||
|
||||
import "gitoa.ru/go-4devs/console/input"
|
||||
|
||||
type String struct {
|
||||
Empty
|
||||
Val []string
|
||||
Flag input.Flag
|
||||
}
|
||||
|
||||
func (s *String) Append(in string) error {
|
||||
s.Val = append(s.Val, in)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *String) String() string {
|
||||
if s.Flag.IsArray() {
|
||||
return ""
|
||||
}
|
||||
|
||||
if len(s.Val) == 1 {
|
||||
return s.Val[0]
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s *String) Strings() []string {
|
||||
return s.Val
|
||||
}
|
||||
|
||||
func (s *String) Any() interface{} {
|
||||
if s.Flag.IsArray() {
|
||||
return s.Strings()
|
||||
}
|
||||
|
||||
return s.String()
|
||||
}
|
||||
44
input/value/time.go
Normal file
44
input/value/time.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package value
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input"
|
||||
)
|
||||
|
||||
type Time struct {
|
||||
Empty
|
||||
Val []time.Time
|
||||
Flag input.Flag
|
||||
}
|
||||
|
||||
func (t *Time) Append(in string) error {
|
||||
v, err := time.Parse(time.RFC3339, in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.Val = append(t.Val, v)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Time) Time() time.Time {
|
||||
if !t.Flag.IsArray() && len(t.Val) == 1 {
|
||||
return t.Val[0]
|
||||
}
|
||||
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func (t *Time) Times() []time.Time {
|
||||
return t.Val
|
||||
}
|
||||
|
||||
func (t *Time) Amy() interface{} {
|
||||
if t.Flag&input.ValueArray > 0 {
|
||||
return t.Times()
|
||||
}
|
||||
|
||||
return t.Time()
|
||||
}
|
||||
44
input/value/uint.go
Normal file
44
input/value/uint.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package value
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input"
|
||||
)
|
||||
|
||||
type Uint struct {
|
||||
Empty
|
||||
Val []uint
|
||||
Flag input.Flag
|
||||
}
|
||||
|
||||
func (u *Uint) Append(in string) error {
|
||||
v, err := strconv.ParseUint(in, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u.Val = append(u.Val, uint(v))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *Uint) Uint() uint {
|
||||
if !u.Flag.IsArray() && len(u.Val) == 1 {
|
||||
return u.Val[0]
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (u *Uint) Uints() []uint {
|
||||
return u.Val
|
||||
}
|
||||
|
||||
func (u *Uint) Any() interface{} {
|
||||
if u.Flag&input.ValueArray > 0 {
|
||||
return u.Uints()
|
||||
}
|
||||
|
||||
return u.Uint()
|
||||
}
|
||||
44
input/value/uint64.go
Normal file
44
input/value/uint64.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package value
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input"
|
||||
)
|
||||
|
||||
type Uint64 struct {
|
||||
Empty
|
||||
Val []uint64
|
||||
Flag input.Flag
|
||||
}
|
||||
|
||||
func (u *Uint64) Append(in string) error {
|
||||
v, err := strconv.ParseUint(in, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u.Val = append(u.Val, v)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *Uint64) Uint64() uint64 {
|
||||
if !u.Flag.IsArray() && len(u.Val) == 1 {
|
||||
return u.Val[0]
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (u *Uint64) Uint64s() []uint64 {
|
||||
return u.Val
|
||||
}
|
||||
|
||||
func (u *Uint64) Any() interface{} {
|
||||
if u.Flag&input.ValueArray > 0 {
|
||||
return u.Uint64s()
|
||||
}
|
||||
|
||||
return u.Uint64()
|
||||
}
|
||||
84
input/value/value.go
Normal file
84
input/value/value.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package value
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input"
|
||||
)
|
||||
|
||||
//nolint: gocyclo
|
||||
func New(v interface{}) input.Value {
|
||||
switch val := v.(type) {
|
||||
case string:
|
||||
return &String{Val: []string{val}, Flag: input.ValueString}
|
||||
case int:
|
||||
return &Int{Val: []int{val}, Flag: input.ValueInt}
|
||||
case int64:
|
||||
return &Int64{Val: []int64{val}, Flag: input.ValueInt64}
|
||||
case uint:
|
||||
return &Uint{Val: []uint{val}, Flag: input.ValueUint}
|
||||
case uint64:
|
||||
return &Uint64{Val: []uint64{val}, Flag: input.ValueUint64}
|
||||
case float64:
|
||||
return &Float64{Val: []float64{val}, Flag: input.ValueFloat64}
|
||||
case bool:
|
||||
return &Bool{Val: []bool{val}, Flag: input.ValueBool}
|
||||
case time.Duration:
|
||||
return &Duration{Val: []time.Duration{val}, Flag: input.ValueDuration}
|
||||
case time.Time:
|
||||
return &Time{Val: []time.Time{val}, Flag: input.ValueTime}
|
||||
case []int64:
|
||||
return &Int64{Val: val, Flag: input.ValueInt64 | input.ValueArray}
|
||||
case []uint:
|
||||
return &Uint{Val: val, Flag: input.ValueUint | input.ValueArray}
|
||||
case []uint64:
|
||||
return &Uint64{Val: val, Flag: input.ValueUint64 | input.ValueArray}
|
||||
case []float64:
|
||||
return &Float64{Val: val, Flag: input.ValueFloat64 | input.ValueArray}
|
||||
case []bool:
|
||||
return &Bool{Val: val, Flag: input.ValueBool | input.ValueArray}
|
||||
case []time.Duration:
|
||||
return &Duration{Val: val, Flag: input.ValueDuration | input.ValueArray}
|
||||
case []time.Time:
|
||||
return &Time{Val: val, Flag: input.ValueTime | input.ValueArray}
|
||||
case []string:
|
||||
return &String{Val: val, Flag: input.ValueString | input.ValueArray}
|
||||
case []int:
|
||||
return &Int{Val: val, Flag: input.ValueInt | input.ValueArray}
|
||||
case []interface{}:
|
||||
return &Any{Val: val, Flag: input.ValueAny | input.ValueArray}
|
||||
case input.Value:
|
||||
return val
|
||||
default:
|
||||
if v != nil {
|
||||
return &Any{Val: []interface{}{v}, Flag: input.ValueAny}
|
||||
}
|
||||
|
||||
return &Empty{}
|
||||
}
|
||||
}
|
||||
|
||||
func ByFlag(flag input.Flag) input.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}
|
||||
default:
|
||||
return &String{}
|
||||
}
|
||||
}
|
||||
105
input/wrap/input.go
Normal file
105
input/wrap/input.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package wrap
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
type Input struct {
|
||||
input.ReadInput
|
||||
}
|
||||
|
||||
func (i *Input) Option(ctx context.Context, name string) input.Value {
|
||||
if v, err := i.ReadOption(ctx, name); err == nil {
|
||||
return v
|
||||
}
|
||||
|
||||
return &value.Empty{}
|
||||
}
|
||||
|
||||
func (i *Input) Argument(ctx context.Context, name string) input.Value {
|
||||
if v, err := i.ReadArgument(ctx, name); err == nil {
|
||||
return v
|
||||
}
|
||||
|
||||
return &value.Empty{}
|
||||
}
|
||||
|
||||
func (i *Input) Bind(ctx context.Context, def *input.Definition) error {
|
||||
if err := i.ReadInput.Bind(ctx, def); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := i.bindArguments(ctx, def); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return i.bindOptions(ctx, def)
|
||||
}
|
||||
|
||||
func (i *Input) bindOptions(ctx context.Context, def *input.Definition) error {
|
||||
for _, name := range def.Options() {
|
||||
opt, err := def.Option(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v, err := i.ReadOption(ctx, name)
|
||||
if err != nil && !errors.Is(err, input.ErrNotFound) {
|
||||
return input.ErrorOption(name, err)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
if err := opt.Validate(v); err != nil {
|
||||
return input.ErrorOption(name, err)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if opt.IsRequired() && !opt.HasDefault() {
|
||||
return input.ErrorOption(name, input.ErrRequired)
|
||||
}
|
||||
|
||||
if opt.HasDefault() {
|
||||
i.SetOption(name, opt.Default)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *Input) bindArguments(ctx context.Context, def *input.Definition) error {
|
||||
for pos, name := range def.Arguments() {
|
||||
arg, err := def.Argument(pos)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v, err := i.ReadArgument(ctx, name)
|
||||
if err != nil && !errors.Is(err, input.ErrNotFound) {
|
||||
return input.ErrorArgument(name, err)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
if err := arg.Validate(v); err != nil {
|
||||
return input.ErrorArgument(name, err)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if arg.IsRequired() && !arg.HasDefault() {
|
||||
return input.ErrorArgument(name, input.ErrRequired)
|
||||
}
|
||||
|
||||
if arg.HasDefault() {
|
||||
i.SetArgument(name, arg.Default)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user