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