andrey1s
4 years ago
41 changed files with 659 additions and 612 deletions
@ -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 |
|||
} |
@ -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 |
|||
} |
@ -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 |
|||
} |
@ -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]] |
|||
} |
@ -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 |
|||
} |
@ -0,0 +1,22 @@ |
|||
package output |
|||
|
|||
import ( |
|||
"context" |
|||
|
|||
"gitoa.ru/go-4devs/console/output/formatter" |
|||
"gitoa.ru/go-4devs/console/output/verbosity" |
|||
) |
|||
|
|||
func Format(out Output, format *formatter.Formatter) Output { |
|||
return func(ctx context.Context, v verbosity.Verbosity, msg string, kv ...KeyValue) (int, error) { |
|||
return out(ctx, v, format.Format(ctx, msg), kv...) |
|||
} |
|||
} |
|||
|
|||
func Ansi(out Output) Output { |
|||
return Format(out, formatter.Ansi()) |
|||
} |
|||
|
|||
func None(out Output) Output { |
|||
return Format(out, formatter.None()) |
|||
} |
@ -0,0 +1,13 @@ |
|||
package output |
|||
|
|||
import ( |
|||
"context" |
|||
|
|||
"gitoa.ru/go-4devs/console/output/verbosity" |
|||
) |
|||
|
|||
func Quiet() Output { |
|||
return func(context.Context, verbosity.Verbosity, string, ...KeyValue) (int, error) { |
|||
return 0, nil |
|||
} |
|||
} |
@ -0,0 +1,17 @@ |
|||
package output |
|||
|
|||
import ( |
|||
"context" |
|||
|
|||
"gitoa.ru/go-4devs/console/output/verbosity" |
|||
) |
|||
|
|||
func Verbosity(out Output, verb verbosity.Verbosity) Output { |
|||
return func(ctx context.Context, v verbosity.Verbosity, msg string, kv ...KeyValue) (int, error) { |
|||
if verb >= v { |
|||
return out(ctx, v, msg, kv...) |
|||
} |
|||
|
|||
return 0, nil |
|||
} |
|||
} |
@ -1,23 +0,0 @@ |
|||
package verbosity |
|||
|
|||
import ( |
|||
"context" |
|||
|
|||
"gitoa.ru/go-4devs/console/output" |
|||
) |
|||
|
|||
func Verb(out output.Output, verb output.Verbosity) output.Output { |
|||
return func(ctx context.Context, v output.Verbosity, msg string, kv ...output.KeyValue) (int, error) { |
|||
if verb >= v { |
|||
return out(ctx, v, msg, kv...) |
|||
} |
|||
|
|||
return 0, nil |
|||
} |
|||
} |
|||
|
|||
func Quiet() output.Output { |
|||
return func(context.Context, output.Verbosity, string, ...output.KeyValue) (int, error) { |
|||
return 0, nil |
|||
} |
|||
} |
@ -0,0 +1,13 @@ |
|||
package verbosity |
|||
|
|||
//go:generate stringer -type=Verbosity -linecomment
|
|||
|
|||
type Verbosity int |
|||
|
|||
const ( |
|||
Quiet Verbosity = iota - 1 // quiet
|
|||
Norm // norm
|
|||
Info // info
|
|||
Debug // debug
|
|||
Trace // trace
|
|||
) |
@ -0,0 +1,28 @@ |
|||
// Code generated by "stringer -type=Verbosity -linecomment"; DO NOT EDIT.
|
|||
|
|||
package verbosity |
|||
|
|||
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[Quiet - -1] |
|||
_ = x[Norm-0] |
|||
_ = x[Info-1] |
|||
_ = x[Debug-2] |
|||
_ = x[Trace-3] |
|||
} |
|||
|
|||
const _Verbosity_name = "quietnorminfodebugtrace" |
|||
|
|||
var _Verbosity_index = [...]uint8{0, 5, 9, 13, 18, 23} |
|||
|
|||
func (i Verbosity) String() string { |
|||
i -= -1 |
|||
if i < 0 || i >= Verbosity(len(_Verbosity_index)-1) { |
|||
return "Verbosity(" + strconv.FormatInt(int64(i+-1), 10) + ")" |
|||
} |
|||
return _Verbosity_name[_Verbosity_index[i]:_Verbosity_index[i+1]] |
|||
} |
@ -1,22 +0,0 @@ |
|||
package wrap |
|||
|
|||
import ( |
|||
"context" |
|||
|
|||
"gitoa.ru/go-4devs/console/output" |
|||
"gitoa.ru/go-4devs/console/output/formatter" |
|||
) |
|||
|
|||
func Format(out output.Output, format *formatter.Formatter) output.Output { |
|||
return func(ctx context.Context, v output.Verbosity, msg string, kv ...output.KeyValue) (int, error) { |
|||
return out(ctx, v, format.Format(ctx, msg), kv...) |
|||
} |
|||
} |
|||
|
|||
func Ansi(out output.Output) output.Output { |
|||
return Format(out, formatter.Ansi()) |
|||
} |
|||
|
|||
func None(out output.Output) output.Output { |
|||
return Format(out, formatter.None()) |
|||
} |
@ -0,0 +1,45 @@ |
|||
package output |
|||
|
|||
import ( |
|||
"bytes" |
|||
"context" |
|||
"fmt" |
|||
"io" |
|||
"os" |
|||
"strings" |
|||
|
|||
"gitoa.ru/go-4devs/console/output/verbosity" |
|||
) |
|||
|
|||
const newline = "\n" |
|||
|
|||
func Stderr() Output { |
|||
return New(os.Stderr, FormatString) |
|||
} |
|||
|
|||
func Stdout() Output { |
|||
return New(os.Stdout, FormatString) |
|||
} |
|||
|
|||
func Buffer(buf *bytes.Buffer) Output { |
|||
return New(buf, FormatString) |
|||
} |
|||
|
|||
func FormatString(_ verbosity.Verbosity, msg string, kv ...KeyValue) string { |
|||
if len(kv) > 0 { |
|||
nline := "" |
|||
if msg[len(msg)-1:] == newline { |
|||
nline = newline |
|||
} |
|||
|
|||
return "msg=\"" + strings.TrimSpace(msg) + "\", " + KeyValues(kv).String() + nline |
|||
} |
|||
|
|||
return msg |
|||
} |
|||
|
|||
func New(w io.Writer, format func(verb verbosity.Verbosity, msg string, kv ...KeyValue) string) Output { |
|||
return func(ctx context.Context, verb verbosity.Verbosity, msg string, kv ...KeyValue) (int, error) { |
|||
return fmt.Fprint(w, format(verb, msg, kv...)) |
|||
} |
|||
} |
@ -1,45 +0,0 @@ |
|||
package writer |
|||
|
|||
import ( |
|||
"bytes" |
|||
"context" |
|||
"fmt" |
|||
"io" |
|||
"os" |
|||
"strings" |
|||
|
|||
"gitoa.ru/go-4devs/console/output" |
|||
) |
|||
|
|||
const newline = "\n" |
|||
|
|||
func Stderr() output.Output { |
|||
return New(os.Stderr, String) |
|||
} |
|||
|
|||
func Stdout() output.Output { |
|||
return New(os.Stdout, String) |
|||
} |
|||
|
|||
func Buffer(buf *bytes.Buffer) output.Output { |
|||
return New(buf, String) |
|||
} |
|||
|
|||
func String(_ output.Verbosity, msg string, kv ...output.KeyValue) string { |
|||
if len(kv) > 0 { |
|||
nline := "" |
|||
if msg[len(msg)-1:] == newline { |
|||
nline = newline |
|||
} |
|||
|
|||
return "msg=\"" + strings.TrimSpace(msg) + "\", " + output.KeyValues(kv).String() + nline |
|||
} |
|||
|
|||
return msg |
|||
} |
|||
|
|||
func New(w io.Writer, format func(verb output.Verbosity, msg string, kv ...output.KeyValue) string) output.Output { |
|||
return func(ctx context.Context, verb output.Verbosity, msg string, kv ...output.KeyValue) (int, error) { |
|||
return fmt.Fprint(w, format(verb, msg, kv...)) |
|||
} |
|||
} |
Loading…
Reference in new issue