argset shape

This commit is contained in:
Erik Winter 2024-11-11 09:23:30 +01:00
parent d1209b8af1
commit b772ca5df4
5 changed files with 121 additions and 56 deletions

View File

@ -20,8 +20,7 @@ type AddCmd struct {
localIDRepo storage.LocalID
eventRepo storage.Event
syncRepo storage.Sync
title string
flags map[string]Flag
argSet *ArgSet
}
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,
eventRepo: eventRepo,
syncRepo: syncRepo,
flags: map[string]Flag{
FlagOn: &FlagDate{},
FlagAt: &FlagTime{},
FlagFor: &FlagDuration{},
argSet: &ArgSet{
Flags: map[string]Flag{
FlagOn: &FlagDate{},
FlagAt: &FlagTime{},
FlagFor: &FlagDuration{},
},
},
}
}
func (add *AddCmd) Parse(as *ArgSet) error {
if len(as.Main) == 0 || as.Main[0] != "add " {
func (add *AddCmd) Parse(main []string, flags map[string]string) error {
if len(main) == 0 || main[0] != "add " {
return ErrWrongCommand
}
add.title = strings.Join(as.Main[1:], " ")
for k := range add.flags {
if err := add.flags[k].Set(as.Flags[k]); err != nil {
as := add.argSet
as.Main = strings.Join(main[1:], " ")
for k := range as.Flags {
if err := as.Set(k, flags[k]); err != nil {
return fmt.Errorf("could not set %s: %v", k, err)
}
}
if add.title == "" {
if as.Main == "" {
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)
}
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)
}
if !add.flags[FlagAt].IsSet() && !add.flags[FlagFor].IsSet() {
if err := add.flags[FlagFor].Set("24h"); err != nil {
if !as.IsSet(FlagAt) && !as.IsSet(FlagFor) {
if err := as.Flags[FlagFor].Set("24h"); err != nil {
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 {
startFormat := "2006-01-02"
startStr := as.Flag(FlagOn)
if as.HasFlag(FlagAt) {
startFormat = fmt.Sprintf("%s 15:04", startFormat)
startStr = fmt.Sprintf("%s %s", startStr, as.Flag(FlagAt))
}
start, err := time.Parse(startFormat, startStr)
if err != nil {
return fmt.Errorf("%w: could not parse start time and date: %v", ErrInvalidArg, err)
as := add.argSet
start := as.GetTime(FlagOn)
if as.IsSet(FlagAt) {
at := as.GetTime(FlagAt)
h := time.Duration(at.Hour()) * time.Hour
m := time.Duration(at.Minute()) * time.Minute
start = start.Add(h).Add(m)
}
e := item.Event{
@ -85,12 +85,8 @@ func (add *AddCmd) Do() error {
},
}
if as.HasFlag(FlagFor) {
fr, err := time.ParseDuration(as.Flag(FlagFor))
if err != nil {
return fmt.Errorf("%w: could not parse duration: %s", ErrInvalidArg, err)
}
e.Duration = fr
if as.IsSet(FlagFor) {
e.Duration = as.GetDuration(FlagFor)
}
if err := add.eventRepo.Store(e); err != nil {
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"
)
type ArgSet struct {
Main []string
Flags map[string]string
}
type Command interface {
Parse(args *ArgSet) error
Parse([]string, map[string]string) error
Do() error
}
@ -21,12 +16,12 @@ type CLI struct {
}
func (cli *CLI) Run(args []string) error {
as, err := ParseFlags(args)
main, flags, err := ParseFlags(args)
if err != nil {
return err
}
for _, c := range cli.Commands {
err := c.Parse(as)
err := c.Parse(main, flags)
switch {
case errors.Is(err, ErrWrongCommand):
continue
@ -40,7 +35,7 @@ func (cli *CLI) Run(args []string) error {
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)
main := make([]string, 0)
var inMain bool
@ -48,7 +43,7 @@ func ParseFlags(args []string) (*ArgSet, error) {
if strings.HasPrefix(args[i], "-") {
inMain = false
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]
i++
@ -56,14 +51,11 @@ func ParseFlags(args []string) (*ArgSet, error) {
}
if !inMain && len(main) > 0 {
return nil, fmt.Errorf("two mains")
return nil, nil, fmt.Errorf("two mains")
}
inMain = true
main = append(main, args[i])
}
return &ArgSet{
Main: main,
Flags: flags,
}, nil
return main, flags, nil
}

View File

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

View File

@ -5,7 +5,6 @@ import (
"os"
"path/filepath"
"github.com/urfave/cli/v2"
"go-mod.ewintr.nl/planner/plan/command"
"go-mod.ewintr.nl/planner/plan/storage/sqlite"
"go-mod.ewintr.nl/planner/sync/client"
@ -32,19 +31,17 @@ func main() {
syncClient := client.New(conf.SyncURL, conf.ApiKey)
app := &cli.App{
Name: "plan",
Usage: "Plan your day with events",
Commands: []*cli.Command{
cli := command.CLI{
Commands: []command.Command{
command.NewAddCmd(localIDRepo, eventRepo, syncRepo),
command.NewListCmd(localIDRepo, eventRepo),
command.NewUpdateCmd(localIDRepo, eventRepo, syncRepo),
command.NewDeleteCmd(localIDRepo, eventRepo, syncRepo),
command.NewSyncCmd(syncClient, syncRepo, localIDRepo, eventRepo),
// command.NewListCmd(localIDRepo, eventRepo),
// command.NewUpdateCmd(localIDRepo, eventRepo, syncRepo),
// command.NewDeleteCmd(localIDRepo, eventRepo, syncRepo),
// command.NewSyncCmd(syncClient, syncRepo, localIDRepo, eventRepo),
},
}
if err := app.Run(os.Args); err != nil {
if err := cli.Run(os.Args); err != nil {
fmt.Println(err)
os.Exit(1)
}