wip
This commit is contained in:
parent
84d2b9eb18
commit
65d8ec66ef
|
@ -9,6 +9,12 @@ import (
|
|||
"go-mod.ewintr.nl/planner/plan/storage"
|
||||
)
|
||||
|
||||
const (
|
||||
FlagOn = "on"
|
||||
FlagAt = "at"
|
||||
FlagFor = "for"
|
||||
)
|
||||
|
||||
type AddCmd struct {
|
||||
localIDRepo storage.LocalID
|
||||
eventRepo storage.Event
|
||||
|
@ -23,41 +29,40 @@ func NewAddCmd(localRepo storage.LocalID, eventRepo storage.Event, syncRepo stor
|
|||
}
|
||||
}
|
||||
|
||||
func (add *AddCmd) Do(args []string) (bool, error) {
|
||||
func (add *AddCmd) Parse(args []string) (*ArgSet, error) {
|
||||
if len(args) == 0 || args[0] != "add" {
|
||||
return false, nil
|
||||
return nil, ErrWrongCommand
|
||||
}
|
||||
title, flags, err := ParseArgs(args[1:])
|
||||
as, err := ParseArgs(args[1:])
|
||||
if err != nil {
|
||||
return false, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if nameStr == "" {
|
||||
return fmt.Errorf("%w: name is required", ErrInvalidArg)
|
||||
if as.Main == "" {
|
||||
return nil, fmt.Errorf("%w: title is required", ErrInvalidArg)
|
||||
}
|
||||
if onStr == "" {
|
||||
return fmt.Errorf("%w: date is required", ErrInvalidArg)
|
||||
if !as.HasFlag(FlagOn) {
|
||||
return nil, fmt.Errorf("%w: date is required", ErrInvalidArg)
|
||||
}
|
||||
if atStr == "" && frStr != "" {
|
||||
return fmt.Errorf("%w: can not have duration without start time", ErrInvalidArg)
|
||||
if !as.HasFlag(FlagAt) && !as.HasFlag(FlagFor) {
|
||||
return nil, fmt.Errorf("%w: can not have duration without start time", ErrInvalidArg)
|
||||
}
|
||||
if atStr == "" && frStr == "" {
|
||||
frStr = "24h"
|
||||
if !as.HasFlag(FlagAt) && !as.HasFlag(FlagFor) {
|
||||
as.SetFlag(FlagFor, "24h")
|
||||
}
|
||||
if err := add.Action(title, flags); err != nil {
|
||||
return false, err
|
||||
if err := add.Action(as); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
return as, nil
|
||||
}
|
||||
|
||||
func (add *AddCmd) Action(nameStr, onStr, atStr, frStr string) error {
|
||||
|
||||
func (add *AddCmd) Action(as *ArgSet) error {
|
||||
startFormat := "2006-01-02"
|
||||
startStr := onStr
|
||||
if atStr != "" {
|
||||
startStr := flags["on"]
|
||||
if at, okAt := flags["at"]; !okAt {
|
||||
startFormat = fmt.Sprintf("%s 15:04", startFormat)
|
||||
startStr = fmt.Sprintf("%s %s", startStr, atStr)
|
||||
startStr = fmt.Sprintf("%s %s", startStr, at)
|
||||
}
|
||||
start, err := time.Parse(startFormat, startStr)
|
||||
if err != nil {
|
||||
|
@ -67,27 +72,27 @@ func (add *AddCmd) Action(nameStr, onStr, atStr, frStr string) error {
|
|||
e := item.Event{
|
||||
ID: uuid.New().String(),
|
||||
EventBody: item.EventBody{
|
||||
Title: nameStr,
|
||||
Title: title,
|
||||
Start: start,
|
||||
},
|
||||
}
|
||||
|
||||
if frStr != "" {
|
||||
fr, err := time.ParseDuration(frStr)
|
||||
if forStr, okFor := flags["for"]; okFor {
|
||||
fr, err := time.ParseDuration(forStr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: could not parse duration: %s", ErrInvalidArg, err)
|
||||
}
|
||||
e.Duration = fr
|
||||
}
|
||||
if err := eventRepo.Store(e); err != nil {
|
||||
if err := add.eventRepo.Store(e); err != nil {
|
||||
return fmt.Errorf("could not store event: %v", err)
|
||||
}
|
||||
|
||||
localID, err := localIDRepo.Next()
|
||||
localID, err := add.localIDRepo.Next()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create next local id: %v", err)
|
||||
}
|
||||
if err := localIDRepo.Store(e.ID, localID); err != nil {
|
||||
if err := add.localIDRepo.Store(e.ID, localID); err != nil {
|
||||
return fmt.Errorf("could not store local id: %v", err)
|
||||
}
|
||||
|
||||
|
@ -95,7 +100,7 @@ func (add *AddCmd) Action(nameStr, onStr, atStr, frStr string) error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("could not convert event to sync item: %v", err)
|
||||
}
|
||||
if err := syncRepo.Store(it); err != nil {
|
||||
if err := add.syncRepo.Store(it); err != nil {
|
||||
return fmt.Errorf("could not store sync item: %v", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,11 +7,31 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
ErrWrongCommand = errors.New("wrong command")
|
||||
ErrInvalidArg = errors.New("invalid argument")
|
||||
)
|
||||
|
||||
type ArgSet struct {
|
||||
Main string
|
||||
Flags map[string]string
|
||||
}
|
||||
|
||||
func (as *ArgSet) HasFlag(name string) bool {
|
||||
_, ok := as.Flags[name]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (as *ArgSet) Flag(name string) string {
|
||||
return as.Flags[name]
|
||||
}
|
||||
|
||||
func (as *ArgSet) SetFlag(name, value string) {
|
||||
as.Flags[name] = value
|
||||
}
|
||||
|
||||
type Command interface {
|
||||
Do(args []string) (bool, error)
|
||||
Parse(args []string) (*ArgSet, error)
|
||||
Do(args *ArgSet) error
|
||||
}
|
||||
|
||||
type CLI struct {
|
||||
|
@ -20,39 +40,44 @@ type CLI struct {
|
|||
|
||||
func (cli *CLI) Run(args []string) error {
|
||||
for _, c := range cli.Commands {
|
||||
worked, err := c.Do(args)
|
||||
if err != nil {
|
||||
as, err := c.Parse(args)
|
||||
switch {
|
||||
case errors.Is(err, ErrWrongCommand):
|
||||
continue
|
||||
case err != nil:
|
||||
return err
|
||||
}
|
||||
if worked {
|
||||
return nil
|
||||
default:
|
||||
return c.Do(as)
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("could not find matching command")
|
||||
}
|
||||
|
||||
func ParseArgs(args []string) (string, map[string]string, error) {
|
||||
func ParseArgs(args []string) (*ArgSet, error) {
|
||||
flags := make(map[string]string)
|
||||
rem := make([]string, 0)
|
||||
var inRem bool
|
||||
main := make([]string, 0)
|
||||
var inMain bool
|
||||
for i := 0; i < len(args); i++ {
|
||||
if strings.HasPrefix(args[i], "-") {
|
||||
inRem = false
|
||||
inMain = false
|
||||
if i+1 >= len(args) {
|
||||
return "", nil, fmt.Errorf("flag wihout value")
|
||||
return &ArgSet{}, fmt.Errorf("flag wihout value")
|
||||
}
|
||||
flags[strings.TrimPrefix(args[i], "-")] = args[i+1]
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
if !inRem && len(rem) > 0 {
|
||||
return "", nil, fmt.Errorf("two rems")
|
||||
if !inMain && len(main) > 0 {
|
||||
return &ArgSet{}, fmt.Errorf("two mains")
|
||||
}
|
||||
inRem = true
|
||||
rem = append(rem, args[i])
|
||||
inMain = true
|
||||
main = append(main, args[i])
|
||||
}
|
||||
|
||||
return strings.Join(rem, " "), flags, nil
|
||||
return &ArgSet{
|
||||
Main: strings.Join(main, " "),
|
||||
Flags: flags,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -2,31 +2,20 @@ package command_test
|
|||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"go-mod.ewintr.nl/planner/plan/command"
|
||||
)
|
||||
|
||||
func TestCommand(t *testing.T) {
|
||||
func TestParseArgs(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cmds := []*command.Command{
|
||||
{
|
||||
Name: "default",
|
||||
Default: true,
|
||||
},
|
||||
}
|
||||
cli := command.CLI{
|
||||
CMDS: cmds,
|
||||
}
|
||||
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
args string
|
||||
exp *command.Command
|
||||
args []string
|
||||
expRem string
|
||||
expFlags map[string]string
|
||||
expErr bool
|
||||
}{
|
||||
{
|
||||
name: "default",
|
||||
exp: cmds[0],
|
||||
name: "empty",
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
|
|
Loading…
Reference in New Issue