update input/outpu
This commit is contained in:
153
input/argv.go
Normal file
153
input/argv.go
Normal file
@@ -0,0 +1,153 @@
|
||||
package input
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input/errs"
|
||||
"gitoa.ru/go-4devs/console/input/option"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
const doubleDash = `--`
|
||||
|
||||
type Argv struct {
|
||||
Array
|
||||
Args []string
|
||||
ErrHandle func(error) error
|
||||
}
|
||||
|
||||
func (i *Argv) Bind(ctx context.Context, def *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 '-'", errs.ErrInvalidName)
|
||||
}
|
||||
|
||||
err = i.parseShortOption(arg[1:], def)
|
||||
default:
|
||||
err = i.parseArgument(arg, def)
|
||||
}
|
||||
|
||||
if err != nil && i.ErrHandle != nil {
|
||||
if herr := i.ErrHandle(err); herr != nil {
|
||||
return herr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return i.Array.Bind(ctx, def)
|
||||
}
|
||||
|
||||
func (i *Argv) parseLongOption(arg string, def *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 errs.Option(name, err)
|
||||
}
|
||||
|
||||
return i.appendOption(name, value, opt)
|
||||
}
|
||||
|
||||
func (i *Argv) appendOption(name string, data *string, opt option.Option) error {
|
||||
v, ok := i.GetOption(name)
|
||||
|
||||
if ok && !opt.IsArray() {
|
||||
return fmt.Errorf("%w: got: array, expect: %s", errs.ErrUnexpectedType, opt.Flag.Type())
|
||||
}
|
||||
|
||||
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 errs.Option(name, errs.ErrRequired)
|
||||
}
|
||||
|
||||
if !ok {
|
||||
v = value.ByFlag(opt.Flag)
|
||||
i.SetOption(name, v)
|
||||
}
|
||||
|
||||
if err := v.Append(val); err != nil {
|
||||
return errs.Option(name, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *Argv) parseShortOption(arg string, def *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 *Argv) parseArgument(arg string, def *Definition) error {
|
||||
opt, err := def.Argument(i.LenArguments())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v, ok := i.GetArgument(opt.Name)
|
||||
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 nil
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
package argv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"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"
|
||||
)
|
||||
|
||||
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]value.AppendValue),
|
||||
options: make(map[string]value.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]value.AppendValue
|
||||
options map[string]value.AppendValue
|
||||
mu sync.RWMutex
|
||||
errorHandle func(error) error
|
||||
}
|
||||
|
||||
func (i *Input) ReadOption(ctx context.Context, name string) (value.Value, error) {
|
||||
if v, ok := i.options[name]; ok {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
return nil, input.ErrNotFound
|
||||
}
|
||||
|
||||
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) (value.Value, error) {
|
||||
if v, ok := i.arguments[name]; ok {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
return nil, input.ErrNotFound
|
||||
}
|
||||
|
||||
func (i *Input) SetArgument(name string, val value.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 option.Option) error {
|
||||
v, ok := i.options[name]
|
||||
|
||||
if ok && !opt.IsArray() {
|
||||
return fmt.Errorf("%w: got: array, expect: %s", input.ErrUnexpectedType, opt.Flag.Type())
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
168
input/array.go
Normal file
168
input/array.go
Normal file
@@ -0,0 +1,168 @@
|
||||
package input
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input/errs"
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
type Array struct {
|
||||
defaults array
|
||||
value array
|
||||
}
|
||||
|
||||
func (a *Array) GetOption(name string) (value.Append, bool) {
|
||||
return a.value.GetOption(name)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
if v, ok := a.defaults.GetOption(name); ok {
|
||||
return v
|
||||
}
|
||||
|
||||
return value.Empty
|
||||
}
|
||||
|
||||
func (a *Array) Argument(_ context.Context, name string) value.Value {
|
||||
if v, ok := a.value.GetArgument(name); ok {
|
||||
return v
|
||||
}
|
||||
|
||||
if v, ok := a.defaults.GetArgument(name); ok {
|
||||
return v
|
||||
}
|
||||
|
||||
return value.Empty
|
||||
}
|
||||
|
||||
func (a *Array) Bind(ctx context.Context, d *Definition) error {
|
||||
if err := a.bindArguments(ctx, d); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.bindOption(ctx, d)
|
||||
}
|
||||
|
||||
func (a *Array) bindOption(ctx context.Context, def *Definition) error {
|
||||
for _, name := range def.Options() {
|
||||
opt, err := def.Option(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v, ok := a.value.GetOption(name)
|
||||
if !ok {
|
||||
switch {
|
||||
case opt.HasDefault():
|
||||
a.defaults.SetOption(name, opt.Default)
|
||||
continue
|
||||
case opt.IsRequired():
|
||||
return errs.Option(name, errs.ErrRequired)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if err := opt.Validate(v); err != nil {
|
||||
return errs.Option(name, err)
|
||||
}
|
||||
|
||||
a.SetOption(name, v)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Array) bindArguments(ctx context.Context, def *Definition) error {
|
||||
for pos, name := range def.Arguments() {
|
||||
arg, err := def.Argument(pos)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v, ok := a.value.GetArgument(name)
|
||||
if !ok {
|
||||
switch {
|
||||
case arg.HasDefault():
|
||||
a.defaults.SetArgument(name, arg.Default)
|
||||
continue
|
||||
case arg.IsRequired():
|
||||
return errs.Argument(name, errs.ErrRequired)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if err := arg.Validate(v); err != nil {
|
||||
return errs.Argument(name, err)
|
||||
}
|
||||
|
||||
a.SetArgument(name, v)
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
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]value.Value),
|
||||
opt: make(map[string]value.Value),
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(i)
|
||||
}
|
||||
|
||||
return &wrap.Input{ReadInput: i}
|
||||
}
|
||||
|
||||
type Input struct {
|
||||
args map[string]value.Value
|
||||
opt map[string]value.Value
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func (i *Input) ReadOption(_ context.Context, name string) (value.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 value.Value) {
|
||||
i.mu.Lock()
|
||||
i.opt[name] = val
|
||||
i.mu.Unlock()
|
||||
}
|
||||
|
||||
func (i *Input) ReadArgument(_ context.Context, name string) (value.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 value.Value) {
|
||||
i.mu.Lock()
|
||||
i.args[name] = val
|
||||
i.mu.Unlock()
|
||||
}
|
||||
|
||||
func (i *Input) Bind(_ context.Context, def *input.Definition) error {
|
||||
return nil
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package input
|
||||
|
||||
import (
|
||||
"gitoa.ru/go-4devs/console/input/argument"
|
||||
"gitoa.ru/go-4devs/console/input/errs"
|
||||
"gitoa.ru/go-4devs/console/input/option"
|
||||
)
|
||||
|
||||
@@ -66,7 +67,7 @@ func (d *Definition) SetArguments(args ...argument.Argument) *Definition {
|
||||
|
||||
func (d *Definition) Argument(pos int) (argument.Argument, error) {
|
||||
if len(d.posArgs) == 0 {
|
||||
return argument.Argument{}, ErrNoArgs
|
||||
return argument.Argument{}, errs.ErrNoArgs
|
||||
}
|
||||
|
||||
lastPos := len(d.posArgs) - 1
|
||||
@@ -76,7 +77,7 @@ func (d *Definition) Argument(pos int) (argument.Argument, error) {
|
||||
return arg, nil
|
||||
}
|
||||
|
||||
return argument.Argument{}, ErrToManyArgs
|
||||
return argument.Argument{}, errs.ErrToManyArgs
|
||||
}
|
||||
|
||||
return d.args[d.posArgs[pos]], nil
|
||||
@@ -85,7 +86,7 @@ func (d *Definition) Argument(pos int) (argument.Argument, error) {
|
||||
func (d *Definition) ShortOption(short string) (option.Option, error) {
|
||||
name, ok := d.short[short]
|
||||
if !ok {
|
||||
return option.Option{}, ErrNotFound
|
||||
return option.Option{}, errs.ErrNotFound
|
||||
}
|
||||
|
||||
return d.Option(name)
|
||||
@@ -96,5 +97,5 @@ func (d *Definition) Option(name string) (option.Option, error) {
|
||||
return opt, nil
|
||||
}
|
||||
|
||||
return option.Option{}, ErrNotFound
|
||||
return option.Option{}, errs.ErrNotFound
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package input
|
||||
package errs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -15,6 +15,14 @@ var (
|
||||
ErrInvalidName = errors.New("invalid name")
|
||||
)
|
||||
|
||||
func New(name, t string, err error) Error {
|
||||
return Error{
|
||||
name: name,
|
||||
t: t,
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
type Error struct {
|
||||
name string
|
||||
err error
|
||||
@@ -33,7 +41,7 @@ func (o Error) Unwrap() error {
|
||||
return o.err
|
||||
}
|
||||
|
||||
func ErrorOption(name string, err error) Error {
|
||||
func Option(name string, err error) Error {
|
||||
return Error{
|
||||
name: name,
|
||||
err: err,
|
||||
@@ -41,7 +49,7 @@ func ErrorOption(name string, err error) Error {
|
||||
}
|
||||
}
|
||||
|
||||
func ErrorArgument(name string, err error) Error {
|
||||
func Argument(name string, err error) Error {
|
||||
return Error{
|
||||
name: name,
|
||||
err: err,
|
||||
@@ -6,18 +6,8 @@ import (
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
type ReadInput interface {
|
||||
Bind(ctx context.Context, def *Definition) error
|
||||
|
||||
ReadOption(ctx context.Context, name string) (value.Value, error)
|
||||
SetOption(name string, v 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.Value
|
||||
Argument(ctx context.Context, name string) value.Value
|
||||
ReadInput
|
||||
Bind(ctx context.Context, def *Definition) error
|
||||
}
|
||||
|
||||
18
input/type.go
Normal file
18
input/type.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package input
|
||||
|
||||
//go:generate stringer -type=Type -linecomment
|
||||
|
||||
type Type int
|
||||
|
||||
const (
|
||||
Argument Type = iota // argument
|
||||
Option // option
|
||||
)
|
||||
|
||||
func (t Type) IsArgument() bool {
|
||||
return t == Argument
|
||||
}
|
||||
|
||||
func (t Type) IsOption() bool {
|
||||
return t == Option
|
||||
}
|
||||
24
input/type_string.go
Normal file
24
input/type_string.go
Normal file
@@ -0,0 +1,24 @@
|
||||
// Code generated by "stringer -type=Type -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[Argument-0]
|
||||
_ = x[Option-1]
|
||||
}
|
||||
|
||||
const _Type_name = "argumentoption"
|
||||
|
||||
var _Type_index = [...]uint8{0, 8, 14}
|
||||
|
||||
func (i Type) String() string {
|
||||
if i < 0 || i >= Type(len(_Type_index)-1) {
|
||||
return "Type(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _Type_name[_Type_index[i]:_Type_index[i+1]]
|
||||
}
|
||||
@@ -99,7 +99,7 @@ func TestNotBlank(t *testing.T) {
|
||||
}
|
||||
|
||||
if ca.empty == nil {
|
||||
ca.empty = &value.Empty{}
|
||||
ca.empty = value.Empty
|
||||
}
|
||||
|
||||
if err := valid(ca.empty); err == nil || !errors.Is(err, validator.ErrNotBlank) {
|
||||
|
||||
@@ -3,7 +3,7 @@ package value
|
||||
import "gitoa.ru/go-4devs/console/input/flag"
|
||||
|
||||
type Any struct {
|
||||
Empty
|
||||
empty
|
||||
Val []interface{}
|
||||
Flag flag.Flag
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
type Bool struct {
|
||||
Empty
|
||||
empty
|
||||
Val []bool
|
||||
Flag flag.Flag
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
type Duration struct {
|
||||
Empty
|
||||
empty
|
||||
Val []time.Duration
|
||||
Flag flag.Flag
|
||||
}
|
||||
|
||||
@@ -4,84 +4,90 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Empty struct{}
|
||||
var Empty = &empty{}
|
||||
|
||||
func (e *Empty) Append(string) error {
|
||||
func IsEmpty(v Value) bool {
|
||||
return v == Empty
|
||||
}
|
||||
|
||||
type empty struct{}
|
||||
|
||||
func (e *empty) Append(string) error {
|
||||
return ErrAppendEmpty
|
||||
}
|
||||
|
||||
func (e *Empty) String() string {
|
||||
func (e *empty) String() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (e *Empty) Int() int {
|
||||
func (e *empty) Int() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Empty) Int64() int64 {
|
||||
func (e *empty) Int64() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Empty) Uint() uint {
|
||||
func (e *empty) Uint() uint {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Empty) Uint64() uint64 {
|
||||
func (e *empty) Uint64() uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Empty) Float64() float64 {
|
||||
func (e *empty) Float64() float64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Empty) Bool() bool {
|
||||
func (e *empty) Bool() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (e *Empty) Duration() time.Duration {
|
||||
func (e *empty) Duration() time.Duration {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (e *Empty) Time() time.Time {
|
||||
func (e *empty) Time() time.Time {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func (e *Empty) Strings() []string {
|
||||
func (e *empty) Strings() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Ints() []int {
|
||||
func (e *empty) Ints() []int {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Int64s() []int64 {
|
||||
func (e *empty) Int64s() []int64 {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Uints() []uint {
|
||||
func (e *empty) Uints() []uint {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Uint64s() []uint64 {
|
||||
func (e *empty) Uint64s() []uint64 {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Float64s() []float64 {
|
||||
func (e *empty) Float64s() []float64 {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Bools() []bool {
|
||||
func (e *empty) Bools() []bool {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Durations() []time.Duration {
|
||||
func (e *empty) Durations() []time.Duration {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Times() []time.Time {
|
||||
func (e *empty) Times() []time.Time {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Empty) Any() interface{} {
|
||||
func (e *empty) Any() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
type Float64 struct {
|
||||
Empty
|
||||
empty
|
||||
Val []float64
|
||||
Flag flag.Flag
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
type Int struct {
|
||||
Empty
|
||||
empty
|
||||
Val []int
|
||||
Flag flag.Flag
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
type Int64 struct {
|
||||
Empty
|
||||
empty
|
||||
Val []int64
|
||||
Flag flag.Flag
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var _ AppendValue = (*Read)(nil)
|
||||
var _ Append = (*Read)(nil)
|
||||
|
||||
var (
|
||||
ErrAppendRead = errors.New("invalid append data to read value")
|
||||
|
||||
@@ -3,7 +3,7 @@ package value
|
||||
import "gitoa.ru/go-4devs/console/input/flag"
|
||||
|
||||
type String struct {
|
||||
Empty
|
||||
empty
|
||||
Val []string
|
||||
Flag flag.Flag
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
type Time struct {
|
||||
Empty
|
||||
empty
|
||||
Val []time.Time
|
||||
Flag flag.Flag
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
type Uint struct {
|
||||
Empty
|
||||
empty
|
||||
Val []uint
|
||||
Flag flag.Flag
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
type Uint64 struct {
|
||||
Empty
|
||||
empty
|
||||
Val []uint64
|
||||
Flag flag.Flag
|
||||
}
|
||||
|
||||
@@ -29,13 +29,13 @@ type Value interface {
|
||||
Times() []time.Time
|
||||
}
|
||||
|
||||
type AppendValue interface {
|
||||
type Append interface {
|
||||
Value
|
||||
Append(string) error
|
||||
}
|
||||
|
||||
//nolint: gocyclo
|
||||
func New(v interface{}) Value {
|
||||
func New(v interface{}) Append {
|
||||
switch val := v.(type) {
|
||||
case string:
|
||||
return &String{Val: []string{val}, Flag: flag.String}
|
||||
@@ -75,18 +75,20 @@ func New(v interface{}) Value {
|
||||
return &Int{Val: val, Flag: flag.Int | flag.Array}
|
||||
case []interface{}:
|
||||
return &Any{Val: val, Flag: flag.Any | flag.Array}
|
||||
case Value:
|
||||
case Append:
|
||||
return val
|
||||
case Value:
|
||||
return &Read{Value: val}
|
||||
default:
|
||||
if v != nil {
|
||||
return &Any{Val: []interface{}{v}, Flag: flag.Any}
|
||||
}
|
||||
|
||||
return &Empty{}
|
||||
return &empty{}
|
||||
}
|
||||
}
|
||||
|
||||
func ByFlag(f flag.Flag) AppendValue {
|
||||
func ByFlag(f flag.Flag) Append {
|
||||
switch {
|
||||
case f.IsInt():
|
||||
return &Int{Flag: f | flag.Int}
|
||||
|
||||
36
input/wrap.go
Normal file
36
input/wrap.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package input
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"gitoa.ru/go-4devs/console/input/value"
|
||||
)
|
||||
|
||||
type Wrap struct {
|
||||
Input
|
||||
Array
|
||||
}
|
||||
|
||||
func (w *Wrap) Option(ctx context.Context, name string) value.Value {
|
||||
if v, ok := w.Array.GetOption(name); ok {
|
||||
return v
|
||||
}
|
||||
|
||||
return w.Input.Option(ctx, name)
|
||||
}
|
||||
|
||||
func (w *Wrap) Argument(ctx context.Context, name string) value.Value {
|
||||
if v, ok := w.Array.GetArgument(name); ok {
|
||||
return v
|
||||
}
|
||||
|
||||
return w.Input.Argument(ctx, name)
|
||||
}
|
||||
|
||||
func (w *Wrap) Bind(ctx context.Context, def *Definition) error {
|
||||
if err := w.Input.Bind(ctx, def); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return w.Array.Bind(ctx, def)
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
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) value.Value {
|
||||
if v, err := i.ReadOption(ctx, name); err == nil {
|
||||
return v
|
||||
}
|
||||
|
||||
return &value.Empty{}
|
||||
}
|
||||
|
||||
func (i *Input) Argument(ctx context.Context, name string) value.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