argset shape
This commit is contained in:
parent
d1209b8af1
commit
b772ca5df4
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
17
plan/main.go
17
plan/main.go
|
@ -5,7 +5,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
"go-mod.ewintr.nl/planner/plan/command"
|
"go-mod.ewintr.nl/planner/plan/command"
|
||||||
"go-mod.ewintr.nl/planner/plan/storage/sqlite"
|
"go-mod.ewintr.nl/planner/plan/storage/sqlite"
|
||||||
"go-mod.ewintr.nl/planner/sync/client"
|
"go-mod.ewintr.nl/planner/sync/client"
|
||||||
|
@ -32,19 +31,17 @@ func main() {
|
||||||
|
|
||||||
syncClient := client.New(conf.SyncURL, conf.ApiKey)
|
syncClient := client.New(conf.SyncURL, conf.ApiKey)
|
||||||
|
|
||||||
app := &cli.App{
|
cli := command.CLI{
|
||||||
Name: "plan",
|
Commands: []command.Command{
|
||||||
Usage: "Plan your day with events",
|
|
||||||
Commands: []*cli.Command{
|
|
||||||
command.NewAddCmd(localIDRepo, eventRepo, syncRepo),
|
command.NewAddCmd(localIDRepo, eventRepo, syncRepo),
|
||||||
command.NewListCmd(localIDRepo, eventRepo),
|
// command.NewListCmd(localIDRepo, eventRepo),
|
||||||
command.NewUpdateCmd(localIDRepo, eventRepo, syncRepo),
|
// command.NewUpdateCmd(localIDRepo, eventRepo, syncRepo),
|
||||||
command.NewDeleteCmd(localIDRepo, eventRepo, syncRepo),
|
// command.NewDeleteCmd(localIDRepo, eventRepo, syncRepo),
|
||||||
command.NewSyncCmd(syncClient, syncRepo, localIDRepo, eventRepo),
|
// 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)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue