Skip to content

Commit

Permalink
default parsers for common flags
Browse files Browse the repository at this point in the history
Signed-off-by: Artem Bortnikov <[email protected]>
  • Loading branch information
BROngineer committed Jun 20, 2024
1 parent cb25f46 commit 6ffc286
Show file tree
Hide file tree
Showing 34 changed files with 742 additions and 508 deletions.
4 changes: 2 additions & 2 deletions examples/custom/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type logParams struct {
}

type customParser[T any] struct {
*parser.DefaultParser
*parser.EmbeddedParser
}

func (p *customParser[T]) ParseCmd(input string) (any, error) {
Expand All @@ -57,7 +57,7 @@ func (p *customParser[T]) ParseEnv(_ string) (any, error) {
}

func newCustomParser[T any]() *customParser[T] {
return &customParser[T]{&parser.DefaultParser{}}
return &customParser[T]{&parser.EmbeddedParser{}}
}

func parse(args []string) (params, error) {
Expand Down
39 changes: 23 additions & 16 deletions flag/bool.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,43 +12,50 @@ type Bool struct {
*fbool
}

func (f *Bool) FromCommandLine(input string) error {
type boolParser struct {
*embeddedParser
}

func defaultBoolParser() *boolParser {
return &boolParser{&embeddedParser{}}
}

func (p *boolParser) ParseCmd(input string) (any, error) {
var (
v bool
err error
parsed bool
err error
)
if f.IsVisited() {
return errors.FlagVisited(f.Name())
if p.IsVisited() {
return nil, errors.ErrFlagVisited
}
switch input {
case "":
v = true
parsed = true
default:
v, err = strconv.ParseBool(input)
parsed, err = strconv.ParseBool(input)
if err != nil {
return errors.ParseError(f.Name(), err)
return nil, err
}
}
f.value = &v
f.visited = true
return nil
return &parsed, nil
}

func (f *Bool) FromEnvVariable(input string) error {
func (p *boolParser) ParseEnv(input string) (any, error) {
var (
parsed bool
err error
)
if parsed, err = strconv.ParseBool(input); err != nil {
return errors.ParseError(f.Name(), err)
return nil, err
}
f.value = &parsed
f.visited = true
return nil
return &parsed, nil
}

func NewBool(name string, opts ...Option) *Bool {
f := newFlag[bool](name)
applyForFlag(f, opts...)
if f.Parser() == nil {
f.setParser(defaultBoolParser())
}
return &Bool{f}
}
37 changes: 22 additions & 15 deletions flag/boolslice.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,46 +13,53 @@ type BoolSlice struct {
*boolSlice
}

func (f *BoolSlice) FromCommandLine(input string) error {
type boolSliceParser struct {
*embeddedParser
}

func defaultBoolSliceParser() *boolSliceParser {
return &boolSliceParser{&embeddedParser{}}
}

func (p *boolSliceParser) ParseCmd(input string) (any, error) {
var empty string
if input == empty {
return errors.NoValueProvided(f.Name())
return nil, errors.ErrNoValueProvided
}
s := strings.Split(input, f.Separator())
s := strings.Split(input, p.Separator())
parsed := make([]bool, 0, len(s))
for _, el := range s {
v, err := strconv.ParseBool(el)
if err != nil {
return errors.ParseError(f.Name(), err)
return nil, err
}
parsed = append(parsed, v)
}
if f.IsVisited() {
stored := DerefOrDie[[]bool](f.Value())
if p.IsVisited() {
stored := DerefOrDie[[]bool](p.CurrentValue())
parsed = append(stored, parsed...)
}
f.value = &parsed
f.visited = true
return nil
return &parsed, nil
}

func (f *BoolSlice) FromEnvVariable(value string) error {
s := strings.Split(value, f.Separator())
func (p *boolSliceParser) ParseEnv(value string) (any, error) {
s := strings.Split(value, p.Separator())
parsed := make([]bool, 0, len(s))
for _, el := range s {
v, err := strconv.ParseBool(el)
if err != nil {
return errors.ParseError(f.Name(), err)
return nil, err
}
parsed = append(parsed, v)
}
f.value = &parsed
f.visited = true
return nil
return &parsed, nil
}

func NewBoolSlice(name string, opts ...Option) *BoolSlice {
f := newFlag[[]bool](name)
applyForFlag(f, opts...)
if f.Parser() == nil {
f.setParser(defaultBoolSliceParser())
}
return &BoolSlice{f}
}
44 changes: 31 additions & 13 deletions flag/counter.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package flag

import (
"strconv"

"github.com/brongineer/helium/errors"
)

type counter = flag[int]
Expand All @@ -12,25 +10,41 @@ type Counter struct {
*counter
}

func (f *Counter) FromCommandLine(_ string) error {
current := DerefOrDie[int](f.Value())
v := current + 1
f.value = &v
f.visited = true
return nil
type counterParser struct {
*embeddedParser
}

func defaultCounterParser() *counterParser {
return &counterParser{&embeddedParser{}}
}

func (f *Counter) FromEnvVariable(input string) error {
func (p *counterParser) ParseCmd(input string) (any, error) {
var (
empty string
parsed int
err error
)
current := DerefOrDie[int](p.CurrentValue())
if input == empty {
parsed = current + 1
} else {
parsed, err = strconv.Atoi(input)
if err != nil {
return nil, err
}
}
return &parsed, nil
}

func (p *counterParser) ParseEnv(input string) (any, error) {
var (
parsed int
err error
)
if parsed, err = strconv.Atoi(input); err != nil {
return errors.ParseError(f.Name(), err)
return nil, err
}
f.value = &parsed
f.visited = true
return nil
return &parsed, nil
}

func NewCounter(name string, opts ...Option) *Counter {
Expand All @@ -39,5 +53,9 @@ func NewCounter(name string, opts ...Option) *Counter {
if f.defaultValue == nil {
f.setDefaultValue(0)
}
f.value = f.defaultValue
if f.Parser() == nil {
f.setParser(defaultCounterParser())
}
return &Counter{f}
}
35 changes: 21 additions & 14 deletions flag/duration.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,45 @@ type Duration struct {
*duration
}

func (f *Duration) FromCommandLine(input string) error {
if f.IsVisited() {
return errors.FlagVisited(f.Name())
type durationParser struct {
*embeddedParser
}

func defaultDurationParser() *durationParser {
return &durationParser{&embeddedParser{}}
}

func (p *durationParser) ParseCmd(input string) (any, error) {
if p.IsVisited() {
return nil, errors.ErrFlagVisited
}
var empty string
if input == empty {
return errors.NoValueProvided(f.Name())
return nil, errors.ErrNoValueProvided
}
v, err := time.ParseDuration(input)
parsed, err := time.ParseDuration(input)
if err != nil {
return errors.ParseError(f.Name(), err)
return nil, err
}
f.value = &v
f.visited = true
return nil
return &parsed, nil
}

func (f *Duration) FromEnvVariable(input string) error {
func (p *durationParser) ParseEnv(input string) (any, error) {
var (
parsed time.Duration
err error
)
if parsed, err = time.ParseDuration(input); err != nil {
return errors.ParseError(f.Name(), err)
return nil, err
}
f.value = &parsed
f.visited = true
return nil
return &parsed, err
}

func NewDuration(name string, opts ...Option) *Duration {
f := newFlag[time.Duration](name)
applyForFlag(f, opts...)
if f.Parser() == nil {
f.setParser(defaultDurationParser())
}
return &Duration{f}
}
37 changes: 22 additions & 15 deletions flag/durationslice.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,46 +13,53 @@ type DurationSlice struct {
*durationSlice
}

func (f *DurationSlice) FromCommandLine(input string) error {
type durationSliceParser struct {
*embeddedParser
}

func defaultDurationSliceParser() *durationSliceParser {
return &durationSliceParser{&embeddedParser{}}
}

func (p *durationSliceParser) ParseCmd(input string) (any, error) {
var empty string
if input == empty {
return errors.NoValueProvided(f.Name())
return nil, errors.ErrNoValueProvided
}
s := strings.Split(input, f.Separator())
s := strings.Split(input, p.Separator())
parsed := make([]time.Duration, 0, len(s))
for _, el := range s {
v, err := time.ParseDuration(el)
if err != nil {
return errors.ParseError(f.Name(), err)
return nil, err
}
parsed = append(parsed, v)
}
if f.IsVisited() {
stored := DerefOrDie[[]time.Duration](f.Value())
if p.IsVisited() {
stored := DerefOrDie[[]time.Duration](p.CurrentValue())
parsed = append(stored, parsed...)
}
f.value = &parsed
f.visited = true
return nil
return &parsed, nil
}

func (f *DurationSlice) FromEnvVariable(input string) error {
s := strings.Split(input, f.Separator())
func (p *durationSliceParser) ParseEnv(input string) (any, error) {
s := strings.Split(input, p.Separator())
parsed := make([]time.Duration, 0, len(s))
for _, el := range s {
v, err := time.ParseDuration(el)
if err != nil {
return errors.ParseError(f.Name(), err)
return nil, err
}
parsed = append(parsed, v)
}
f.value = &parsed
f.visited = true
return nil
return &parsed, nil
}

func NewDurationSlice(name string, opts ...Option) *DurationSlice {
f := newFlag[[]time.Duration](name)
applyForFlag(f, opts...)
if f.Parser() == nil {
f.setParser(defaultDurationSliceParser())
}
return &DurationSlice{f}
}
Loading

0 comments on commit 6ffc286

Please sign in to comment.