diff --git a/plan/command/add.go b/plan/command/add.go index 7aaaab4..2e2f694 100644 --- a/plan/command/add.go +++ b/plan/command/add.go @@ -86,26 +86,26 @@ type Add struct { args AddArgs } -func (a *Add) Do(deps Dependencies) error { +func (a *Add) Do(deps Dependencies) ([][]string, error) { if err := deps.TaskRepo.Store(a.args.task); err != nil { - return fmt.Errorf("could not store event: %v", err) + return nil, fmt.Errorf("could not store event: %v", err) } localID, err := deps.LocalIDRepo.Next() if err != nil { - return fmt.Errorf("could not create next local id: %v", err) + return nil, fmt.Errorf("could not create next local id: %v", err) } if err := deps.LocalIDRepo.Store(a.args.task.ID, localID); err != nil { - return fmt.Errorf("could not store local id: %v", err) + return nil, fmt.Errorf("could not store local id: %v", err) } it, err := a.args.task.Item() if err != nil { - return fmt.Errorf("could not convert event to sync item: %v", err) + return nil, fmt.Errorf("could not convert event to sync item: %v", err) } if err := deps.SyncRepo.Store(it); err != nil { - return fmt.Errorf("could not store sync item: %v", err) + return nil, fmt.Errorf("could not store sync item: %v", err) } - return nil + return nil, nil } diff --git a/plan/command/add_test.go b/plan/command/add_test.go index ad14feb..faeb2f8 100644 --- a/plan/command/add_test.go +++ b/plan/command/add_test.go @@ -66,7 +66,7 @@ func TestAdd(t *testing.T) { if tc.expErr { return } - if err := cmd.Do(command.Dependencies{ + if _, err := cmd.Do(command.Dependencies{ TaskRepo: taskRepo, LocalIDRepo: localIDRepo, SyncRepo: syncRepo, diff --git a/plan/command/command.go b/plan/command/command.go index f4ac5fd..b8715fc 100644 --- a/plan/command/command.go +++ b/plan/command/command.go @@ -6,6 +6,7 @@ import ( "slices" "strings" + "go-mod.ewintr.nl/planner/plan/format" "go-mod.ewintr.nl/planner/plan/storage" "go-mod.ewintr.nl/planner/sync/client" ) @@ -32,7 +33,7 @@ type CommandArgs interface { } type Command interface { - Do(deps Dependencies) error + Do(deps Dependencies) ([][]string, error) } type CLI struct { @@ -52,17 +53,29 @@ func NewCLI(deps Dependencies) *CLI { } func (cli *CLI) Run(args []string) error { - main, flags := FindFields(args) + main, fields := FindFields(args) for _, ca := range cli.cmdArgs { - cmd, err := ca.Parse(main, flags) + cmd, err := ca.Parse(main, fields) switch { case errors.Is(err, ErrWrongCommand): continue case err != nil: return err - default: - return cmd.Do(cli.deps) } + + data, err := cmd.Do(cli.deps) + if err != nil { + return err + } + + switch { + case len(data) == 0: + case len(data) == 1 && len(data[0]) == 1: + fmt.Println(data[0][0]) + default: + fmt.Printf("\n%s\n", format.Table(data)) + } + return nil } return fmt.Errorf("could not find matching command") diff --git a/plan/command/delete.go b/plan/command/delete.go index cc2c777..7017323 100644 --- a/plan/command/delete.go +++ b/plan/command/delete.go @@ -34,11 +34,11 @@ type Delete struct { args DeleteArgs } -func (del *Delete) Do(deps Dependencies) error { +func (del *Delete) Do(deps Dependencies) ([][]string, error) { var id string idMap, err := deps.LocalIDRepo.FindAll() if err != nil { - return fmt.Errorf("could not get local ids: %v", err) + return nil, fmt.Errorf("could not get local ids: %v", err) } for tskID, lid := range idMap { if del.args.LocalID == lid { @@ -46,30 +46,30 @@ func (del *Delete) Do(deps Dependencies) error { } } if id == "" { - return fmt.Errorf("could not find local id") + return nil, fmt.Errorf("could not find local id") } tsk, err := deps.TaskRepo.Find(id) if err != nil { - return fmt.Errorf("could not get task: %v", err) + return nil, fmt.Errorf("could not get task: %v", err) } it, err := tsk.Item() if err != nil { - return fmt.Errorf("could not convert task to sync item: %v", err) + return nil, fmt.Errorf("could not convert task to sync item: %v", err) } it.Deleted = true if err := deps.SyncRepo.Store(it); err != nil { - return fmt.Errorf("could not store sync item: %v", err) + return nil, fmt.Errorf("could not store sync item: %v", err) } if err := deps.LocalIDRepo.Delete(id); err != nil { - return fmt.Errorf("could not delete local id: %v", err) + return nil, fmt.Errorf("could not delete local id: %v", err) } if err := deps.TaskRepo.Delete(id); err != nil { - return fmt.Errorf("could not delete task: %v", err) + return nil, fmt.Errorf("could not delete task: %v", err) } - return nil + return nil, nil } diff --git a/plan/command/delete_test.go b/plan/command/delete_test.go index bfd39e3..8e148e4 100644 --- a/plan/command/delete_test.go +++ b/plan/command/delete_test.go @@ -61,12 +61,12 @@ func TestDelete(t *testing.T) { if tc.expParseErr { return } - actDoErr := cmd.Do(command.Dependencies{ + _, actDoErr := cmd.Do(command.Dependencies{ TaskRepo: taskRepo, LocalIDRepo: localIDRepo, SyncRepo: syncRepo, - }) != nil - if tc.expDoErr != actDoErr { + }) + if tc.expDoErr != (actDoErr != nil) { t.Errorf("exp false, got %v", actDoErr) } if tc.expDoErr { diff --git a/plan/command/list.go b/plan/command/list.go index b31bca8..05ed941 100644 --- a/plan/command/list.go +++ b/plan/command/list.go @@ -22,22 +22,22 @@ func (la ListArgs) Parse(main []string, flags map[string]string) (Command, error type List struct { } -func (list *List) Do(deps Dependencies) error { +func (list *List) Do(deps Dependencies) ([][]string, error) { localIDs, err := deps.LocalIDRepo.FindAll() if err != nil { - return fmt.Errorf("could not get local ids: %v", err) + return nil, fmt.Errorf("could not get local ids: %v", err) } all, err := deps.TaskRepo.FindAll() if err != nil { - return err + return nil, err } for _, e := range all { lid, ok := localIDs[e.ID] if !ok { - return fmt.Errorf("could not find local id for %s", e.ID) + return nil, fmt.Errorf("could not find local id for %s", e.ID) } fmt.Printf("%s\t%d\t%s\t%s\t%s\n", e.ID, lid, e.Title, e.Date.String(), e.Duration.String()) } - return nil + return nil, nil } diff --git a/plan/command/list_test.go b/plan/command/list_test.go index 953ba39..1707407 100644 --- a/plan/command/list_test.go +++ b/plan/command/list_test.go @@ -54,7 +54,7 @@ func TestList(t *testing.T) { if tc.expErr { return } - if err := cmd.Do(command.Dependencies{ + if _, err := cmd.Do(command.Dependencies{ TaskRepo: taskRepo, LocalIDRepo: localRepo, }); err != nil { diff --git a/plan/command/show.go b/plan/command/show.go index 91c8ed9..4368c1f 100644 --- a/plan/command/show.go +++ b/plan/command/show.go @@ -5,7 +5,6 @@ import ( "fmt" "strconv" - "go-mod.ewintr.nl/planner/plan/format" "go-mod.ewintr.nl/planner/plan/storage" ) @@ -37,18 +36,18 @@ type Show struct { args ShowArgs } -func (s *Show) Do(deps Dependencies) error { +func (s *Show) Do(deps Dependencies) ([][]string, error) { id, err := deps.LocalIDRepo.FindOne(s.args.localID) switch { case errors.Is(err, storage.ErrNotFound): - return fmt.Errorf("could not find local id") + return nil, fmt.Errorf("could not find local id") case err != nil: - return err + return nil, err } tsk, err := deps.TaskRepo.Find(id) if err != nil { - return fmt.Errorf("could not find task") + return nil, fmt.Errorf("could not find task") } var recurStr string @@ -64,7 +63,6 @@ func (s *Show) Do(deps Dependencies) error { {"recur", recurStr}, // {"id", tsk.ID}, } - fmt.Printf("\n%s\n", format.Table(data)) - return nil + return data, nil } diff --git a/plan/command/show_test.go b/plan/command/show_test.go new file mode 100644 index 0000000..cc3e83c --- /dev/null +++ b/plan/command/show_test.go @@ -0,0 +1,86 @@ +package command_test + +import ( + "fmt" + "testing" + + "github.com/google/go-cmp/cmp" + "go-mod.ewintr.nl/planner/item" + "go-mod.ewintr.nl/planner/plan/command" + "go-mod.ewintr.nl/planner/plan/storage/memory" +) + +func TestShow(t *testing.T) { + t.Parallel() + + taskRepo := memory.NewTask() + localRepo := memory.NewLocalID() + tsk := item.Task{ + ID: "id", + Date: item.NewDate(2024, 10, 7), + TaskBody: item.TaskBody{ + Title: "name", + }, + } + if err := taskRepo.Store(tsk); err != nil { + t.Errorf("exp nil, got %v", err) + } + if err := localRepo.Store(tsk.ID, 1); err != nil { + t.Errorf("exp nil, got %v", err) + } + + for _, tc := range []struct { + name string + main []string + expData [][]string + expParseErr bool + expDoErr bool + }{ + { + name: "empty", + main: []string{}, + expParseErr: true, + }, + { + name: "wrong", + main: []string{"delete"}, + expParseErr: true, + }, + { + name: "local id", + main: []string{"1"}, + expData: [][]string{ + {"title", tsk.Title}, + {"local id", fmt.Sprintf("%d", 1)}, + {"date", tsk.Date.String()}, + {"time", tsk.Time.String()}, + {"duration", tsk.Duration.String()}, + {"recur", ""}, + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + cmd, actParseErr := command.NewShowArgs().Parse(tc.main, nil) + if tc.expParseErr != (actParseErr != nil) { + t.Errorf("exp %v, got %v", tc.expParseErr, actParseErr != nil) + } + if tc.expParseErr { + return + } + actData, actDoErr := cmd.Do(command.Dependencies{ + TaskRepo: taskRepo, + LocalIDRepo: localRepo, + }) + if tc.expDoErr != (actDoErr != nil) { + t.Errorf("exp %v, got %v", tc.expDoErr, actDoErr != nil) + } + if tc.expDoErr { + return + } + if diff := cmp.Diff(tc.expData, actData); diff != "" { + t.Errorf("(+exp, -got)%s\n", diff) + } + }) + } + +} diff --git a/plan/command/sync.go b/plan/command/sync.go index 7da90df..ba8474d 100644 --- a/plan/command/sync.go +++ b/plan/command/sync.go @@ -25,37 +25,37 @@ func (sa SyncArgs) Parse(main []string, flags map[string]string) (Command, error type Sync struct{} -func (s *Sync) Do(deps Dependencies) error { +func (s *Sync) Do(deps Dependencies) ([][]string, error) { // local new and updated sendItems, err := deps.SyncRepo.FindAll() if err != nil { - return fmt.Errorf("could not get updated items: %v", err) + return nil, fmt.Errorf("could not get updated items: %v", err) } if err := deps.SyncClient.Update(sendItems); err != nil { - return fmt.Errorf("could not send updated items: %v", err) + return nil, fmt.Errorf("could not send updated items: %v", err) } if err := deps.SyncRepo.DeleteAll(); err != nil { - return fmt.Errorf("could not clear updated items: %v", err) + return nil, fmt.Errorf("could not clear updated items: %v", err) } // get new/updated items ts, err := deps.SyncRepo.LastUpdate() if err != nil { - return fmt.Errorf("could not find timestamp of last update: %v", err) + return nil, fmt.Errorf("could not find timestamp of last update: %v", err) } recItems, err := deps.SyncClient.Updated([]item.Kind{item.KindTask}, ts) if err != nil { - return fmt.Errorf("could not receive updates: %v", err) + return nil, fmt.Errorf("could not receive updates: %v", err) } updated := make([]item.Item, 0) for _, ri := range recItems { if ri.Deleted { if err := deps.LocalIDRepo.Delete(ri.ID); err != nil && !errors.Is(err, storage.ErrNotFound) { - return fmt.Errorf("could not delete local id: %v", err) + return nil, fmt.Errorf("could not delete local id: %v", err) } if err := deps.TaskRepo.Delete(ri.ID); err != nil && !errors.Is(err, storage.ErrNotFound) { - return fmt.Errorf("could not delete task: %v", err) + return nil, fmt.Errorf("could not delete task: %v", err) } continue } @@ -64,12 +64,12 @@ func (s *Sync) Do(deps Dependencies) error { lidMap, err := deps.LocalIDRepo.FindAll() if err != nil { - return fmt.Errorf("could not get local ids: %v", err) + return nil, fmt.Errorf("could not get local ids: %v", err) } for _, u := range updated { var tskBody item.TaskBody if err := json.Unmarshal([]byte(u.Body), &tskBody); err != nil { - return fmt.Errorf("could not unmarshal task body: %v", err) + return nil, fmt.Errorf("could not unmarshal task body: %v", err) } tsk := item.Task{ ID: u.ID, @@ -79,20 +79,20 @@ func (s *Sync) Do(deps Dependencies) error { TaskBody: tskBody, } if err := deps.TaskRepo.Store(tsk); err != nil { - return fmt.Errorf("could not store task: %v", err) + return nil, fmt.Errorf("could not store task: %v", err) } lid, ok := lidMap[u.ID] if !ok { lid, err = deps.LocalIDRepo.Next() if err != nil { - return fmt.Errorf("could not get next local id: %v", err) + return nil, fmt.Errorf("could not get next local id: %v", err) } if err := deps.LocalIDRepo.Store(u.ID, lid); err != nil { - return fmt.Errorf("could not store local id: %v", err) + return nil, fmt.Errorf("could not store local id: %v", err) } } } - return nil + return nil, nil } diff --git a/plan/command/sync_test.go b/plan/command/sync_test.go index 151e174..f76a9b6 100644 --- a/plan/command/sync_test.go +++ b/plan/command/sync_test.go @@ -80,7 +80,7 @@ func TestSyncSend(t *testing.T) { if err != nil { t.Errorf("exp nil, got %v", err) } - if err := cmd.Do(command.Dependencies{ + if _, err := cmd.Do(command.Dependencies{ TaskRepo: taskRepo, LocalIDRepo: localIDRepo, SyncRepo: syncRepo, @@ -206,7 +206,7 @@ func TestSyncReceive(t *testing.T) { if err != nil { t.Errorf("exp nil, got %v", err) } - if err := cmd.Do(command.Dependencies{ + if _, err := cmd.Do(command.Dependencies{ TaskRepo: taskRepo, LocalIDRepo: localIDRepo, SyncRepo: syncRepo, diff --git a/plan/command/update.go b/plan/command/update.go index 1dd70c1..3049307 100644 --- a/plan/command/update.go +++ b/plan/command/update.go @@ -83,11 +83,11 @@ type Update struct { args UpdateArgs } -func (u *Update) Do(deps Dependencies) error { +func (u *Update) Do(deps Dependencies) ([][]string, error) { var id string idMap, err := deps.LocalIDRepo.FindAll() if err != nil { - return fmt.Errorf("could not get local ids: %v", err) + return nil, fmt.Errorf("could not get local ids: %v", err) } for tid, lid := range idMap { if u.args.LocalID == lid { @@ -95,12 +95,12 @@ func (u *Update) Do(deps Dependencies) error { } } if id == "" { - return fmt.Errorf("could not find local id") + return nil, fmt.Errorf("could not find local id") } tsk, err := deps.TaskRepo.Find(id) if err != nil { - return fmt.Errorf("could not find task") + return nil, fmt.Errorf("could not find task") } if u.args.Title != "" { @@ -121,20 +121,20 @@ func (u *Update) Do(deps Dependencies) error { } if !tsk.Valid() { - return fmt.Errorf("task is unvalid") + return nil, fmt.Errorf("task is unvalid") } if err := deps.TaskRepo.Store(tsk); err != nil { - return fmt.Errorf("could not store task: %v", err) + return nil, fmt.Errorf("could not store task: %v", err) } it, err := tsk.Item() if err != nil { - return fmt.Errorf("could not convert task to sync item: %v", err) + return nil, fmt.Errorf("could not convert task to sync item: %v", err) } if err := deps.SyncRepo.Store(it); err != nil { - return fmt.Errorf("could not store sync item: %v", err) + return nil, fmt.Errorf("could not store sync item: %v", err) } - return nil + return nil, nil } diff --git a/plan/command/update_test.go b/plan/command/update_test.go index fa1ab82..fbc14d9 100644 --- a/plan/command/update_test.go +++ b/plan/command/update_test.go @@ -189,12 +189,12 @@ func TestUpdateExecute(t *testing.T) { if tc.expParseErr { return } - actDoErr := cmd.Do(command.Dependencies{ + _, actDoErr := cmd.Do(command.Dependencies{ TaskRepo: taskRepo, LocalIDRepo: localIDRepo, SyncRepo: syncRepo, - }) != nil - if tc.expDoErr != actDoErr { + }) + if tc.expDoErr != (actDoErr != nil) { t.Errorf("exp %v, got %v", tc.expDoErr, actDoErr) } if tc.expDoErr {