argset shape

This commit is contained in:
Erik Winter 2024-11-11 09:23:30 +01:00
parent d1209b8af1
commit 7553d8ac16
4 changed files with 114 additions and 46 deletions

View File

@ -20,8 +20,7 @@ type AddCmd struct {
localIDRepo storage.LocalID localIDRepo storage.LocalID
eventRepo storage.Event eventRepo storage.Event
syncRepo storage.Sync syncRepo storage.Sync
title string argSet *ArgSet
flags map[string]Flag
} }
func NewAddCmd(localRepo storage.LocalID, eventRepo storage.Event, syncRepo storage.Sync) Command { func NewAddCmd(localRepo storage.LocalID, eventRepo storage.Event, syncRepo storage.Sync) Command {
@ -29,35 +28,38 @@ func NewAddCmd(localRepo storage.LocalID, eventRepo storage.Event, syncRepo stor
localIDRepo: localRepo, localIDRepo: localRepo,
eventRepo: eventRepo, eventRepo: eventRepo,
syncRepo: syncRepo, syncRepo: syncRepo,
flags: map[string]Flag{ argSet: &ArgSet{
Flags: map[string]Flag{
FlagOn: &FlagDate{}, FlagOn: &FlagDate{},
FlagAt: &FlagTime{}, FlagAt: &FlagTime{},
FlagFor: &FlagDuration{}, FlagFor: &FlagDuration{},
}, },
},
} }
} }
func (add *AddCmd) Parse(as *ArgSet) error { func (add *AddCmd) Parse(main []string, flags map[string]string) error {
if len(as.Main) == 0 || as.Main[0] != "add " { if len(main) == 0 || main[0] != "add " {
return ErrWrongCommand return ErrWrongCommand
} }
add.title = strings.Join(as.Main[1:], " ") as := add.argSet
for k := range add.flags { as.Main = strings.Join(main[1:], " ")
if err := add.flags[k].Set(as.Flags[k]); err != nil { for k := range as.Flags {
if err := as.Set(k, flags[k]); err != nil {
return fmt.Errorf("could not set %s: %v", k, err) return fmt.Errorf("could not set %s: %v", k, err)
} }
} }
if add.title == "" { if as.Main == "" {
return fmt.Errorf("%w: title is required", ErrInvalidArg) return fmt.Errorf("%w: title is required", ErrInvalidArg)
} }
if !add.flags[FlagOn].IsSet() { if !as.IsSet(FlagOn) {
return fmt.Errorf("%w: date is required", ErrInvalidArg) return fmt.Errorf("%w: date is required", ErrInvalidArg)
} }
if !add.flags[FlagAt].IsSet() && add.flags[FlagFor].IsSet() { if !as.IsSet(FlagAt) && as.IsSet(FlagFor) {
return fmt.Errorf("%w: can not have duration without start time", ErrInvalidArg) return fmt.Errorf("%w: can not have duration without start time", ErrInvalidArg)
} }
if !add.flags[FlagAt].IsSet() && !add.flags[FlagFor].IsSet() { if !as.IsSet(FlagAt) && !as.IsSet(FlagFor) {
if err := add.flags[FlagFor].Set("24h"); err != nil { if err := as.Flags[FlagFor].Set("24h"); err != nil {
return fmt.Errorf("could not set duration to 24 hours") return fmt.Errorf("could not set duration to 24 hours")
} }
} }
@ -66,15 +68,13 @@ func (add *AddCmd) Parse(as *ArgSet) error {
} }
func (add *AddCmd) Do() error { func (add *AddCmd) Do() error {
startFormat := "2006-01-02" as := add.argSet
startStr := as.Flag(FlagOn) start := as.GetTime(FlagOn)
if as.HasFlag(FlagAt) { if as.IsSet(FlagAt) {
startFormat = fmt.Sprintf("%s 15:04", startFormat) at := as.GetTime(FlagAt)
startStr = fmt.Sprintf("%s %s", startStr, as.Flag(FlagAt)) h := time.Duration(at.Hour()) * time.Hour
} m := time.Duration(at.Minute()) * time.Minute
start, err := time.Parse(startFormat, startStr) start = start.Add(h).Add(m)
if err != nil {
return fmt.Errorf("%w: could not parse start time and date: %v", ErrInvalidArg, err)
} }
e := item.Event{ e := item.Event{
@ -85,12 +85,8 @@ func (add *AddCmd) Do() error {
}, },
} }
if as.HasFlag(FlagFor) { if as.IsSet(FlagFor) {
fr, err := time.ParseDuration(as.Flag(FlagFor)) e.Duration = as.GetDuration(FlagFor)
if err != nil {
return fmt.Errorf("%w: could not parse duration: %s", ErrInvalidArg, err)
}
e.Duration = fr
} }
if err := add.eventRepo.Store(e); err != nil { if err := add.eventRepo.Store(e); err != nil {
return fmt.Errorf("could not store event: %v", err) return fmt.Errorf("could not store event: %v", err)

63
plan/command/argset.go Normal file
View File

@ -0,0 +1,63 @@
package command
import (
"fmt"
"time"
)
type ArgSet struct {
Main string
Flags map[string]Flag
}
func (as *ArgSet) Set(name, val string) error {
f, ok := as.Flags[name]
if !ok {
return fmt.Errorf("unknown flag %s", name)
}
return f.Set(val)
}
func (as *ArgSet) IsSet(name string) bool {
f, ok := as.Flags[name]
if !ok {
return false
}
return f.IsSet()
}
func (as *ArgSet) GetString(name string) string {
flag, ok := as.Flags[name]
if !ok {
return ""
}
val, ok := flag.Get().(string)
if !ok {
return ""
}
return val
}
func (as *ArgSet) GetTime(name string) time.Time {
flag, ok := as.Flags[name]
if !ok {
return time.Time{}
}
val, ok := flag.Get().(time.Time)
if !ok {
return time.Time{}
}
return val
}
func (as *ArgSet) GetDuration(name string) time.Duration {
flag, ok := as.Flags[name]
if !ok {
return time.Duration(0)
}
val, ok := flag.Get().(time.Duration)
if !ok {
return time.Duration(0)
}
return val
}

View File

@ -6,13 +6,8 @@ import (
"strings" "strings"
) )
type ArgSet struct {
Main []string
Flags map[string]string
}
type Command interface { type Command interface {
Parse(args *ArgSet) error Parse([]string, map[string]string) error
Do() error Do() error
} }
@ -21,12 +16,12 @@ type CLI struct {
} }
func (cli *CLI) Run(args []string) error { func (cli *CLI) Run(args []string) error {
as, err := ParseFlags(args) main, flags, err := ParseFlags(args)
if err != nil { if err != nil {
return err return err
} }
for _, c := range cli.Commands { for _, c := range cli.Commands {
err := c.Parse(as) err := c.Parse(main, flags)
switch { switch {
case errors.Is(err, ErrWrongCommand): case errors.Is(err, ErrWrongCommand):
continue continue
@ -40,7 +35,7 @@ func (cli *CLI) Run(args []string) error {
return fmt.Errorf("could not find matching command") return fmt.Errorf("could not find matching command")
} }
func ParseFlags(args []string) (*ArgSet, error) { func ParseFlags(args []string) ([]string, map[string]string, error) {
flags := make(map[string]string) flags := make(map[string]string)
main := make([]string, 0) main := make([]string, 0)
var inMain bool var inMain bool
@ -48,7 +43,7 @@ func ParseFlags(args []string) (*ArgSet, error) {
if strings.HasPrefix(args[i], "-") { if strings.HasPrefix(args[i], "-") {
inMain = false inMain = false
if i+1 >= len(args) { if i+1 >= len(args) {
return nil, fmt.Errorf("flag wihout value") return nil, nil, fmt.Errorf("flag wihout value")
} }
flags[strings.TrimPrefix(args[i], "-")] = args[i+1] flags[strings.TrimPrefix(args[i], "-")] = args[i+1]
i++ i++
@ -56,14 +51,11 @@ func ParseFlags(args []string) (*ArgSet, error) {
} }
if !inMain && len(main) > 0 { if !inMain && len(main) > 0 {
return nil, fmt.Errorf("two mains") return nil, nil, fmt.Errorf("two mains")
} }
inMain = true inMain = true
main = append(main, args[i]) main = append(main, args[i])
} }
return &ArgSet{ return main, flags, nil
Main: main,
Flags: flags,
}, nil
} }

View File

@ -19,6 +19,7 @@ var (
type Flag interface { type Flag interface {
Set(val string) error Set(val string) error
IsSet() bool IsSet() bool
Get() any
} }
type FlagString struct { type FlagString struct {
@ -35,6 +36,10 @@ func (fs *FlagString) IsSet() bool {
return fs.Value != "" return fs.Value != ""
} }
func (fs *FlagString) Get() any {
return fs.Value
}
type FlagDate struct { type FlagDate struct {
Name string Name string
Value time.Time Value time.Time
@ -54,6 +59,10 @@ func (ft *FlagDate) IsSet() bool {
return ft.Value.IsZero() return ft.Value.IsZero()
} }
func (fs *FlagDate) Get() any {
return fs.Value
}
type FlagTime struct { type FlagTime struct {
Name string Name string
Value time.Time Value time.Time
@ -73,6 +82,10 @@ func (fd *FlagTime) IsSet() bool {
return fd.Value.IsZero() return fd.Value.IsZero()
} }
func (fs *FlagTime) Get() any {
return fs.Value
}
type FlagDuration struct { type FlagDuration struct {
Name string Name string
Value time.Duration Value time.Duration
@ -90,3 +103,7 @@ func (fd *FlagDuration) Set(val string) error {
func (fd *FlagDuration) IsSet() bool { func (fd *FlagDuration) IsSet() bool {
return fd.Value.String() != "0s" return fd.Value.String() != "0s"
} }
func (fs *FlagDuration) Get() any {
return fs.Value
}