From 5d28dac9b2e1d153f33551b968ab4c92cfce23ce Mon Sep 17 00:00:00 2001 From: Quey-Liang Kao Date: Mon, 14 Aug 2017 14:41:40 +0800 Subject: Implement the "an" feature: Adding notes to todos This patch introduce a new attribute of a todo item, which is "Notes", of type []string. The following enhancing patches will contain the listing, removing and editing features. --- todo.go | 7 +++++++ todolist/app.go | 15 +++++++++++++++ todolist/parser.go | 12 ++++++++++++ todolist/parser_test.go | 12 ++++++++++++ todolist/todo_item.go | 1 + todolist/todos.json | 2 +- 6 files changed, 48 insertions(+), 1 deletion(-) diff --git a/todo.go b/todo.go index 1eea73c..77faccb 100644 --- a/todo.go +++ b/todo.go @@ -122,6 +122,11 @@ func usage() { yellow.Println("\ttodo d 33") fmt.Println("\tDeletes a todo with id 33\n") + blueBold.Println("\nManipulating notes") + fmt.Println(" You can add additional information to a existing todo.\n") + yellow.Println("\ttodo an 12 check http://this.web.site") + fmt.Println("\tAdds notes \"check http://this.web.site\" to the todo with id 12\n") + blueBold.Println("\nGarbage Collection") yellow.Println("\ttodo gc") fmt.Println("\tDeletes all archived todos.\n") @@ -153,6 +158,8 @@ func routeInput(command string, input string) { app.EditTodo(input) case "ex", "expand": app.ExpandTodo(input) + case "an": + app.ManipulateNotes(input) case "gc": app.GarbageCollect() case "p", "prioritize": diff --git a/todolist/app.go b/todolist/app.go index 42b1361..c2bd66a 100644 --- a/todolist/app.go +++ b/todolist/app.go @@ -132,6 +132,21 @@ func (a *App) ExpandTodo(input string) { fmt.Println("Todo expanded.") } +func (a *App) ManipulateNotes(input string) { + a.Load() + id, todo := a.getId(input) + parser := &Parser{} + if id == -1 { + return + } + + retStr := parser.ParseNotes(todo, input) + if retStr != "" { + a.Save() + fmt.Println("Notes " + retStr + "ed.") + } +} + func (a *App) ArchiveCompleted() { a.Load() for _, todo := range a.TodoList.Todos() { diff --git a/todolist/parser.go b/todolist/parser.go index cdfb179..207791d 100644 --- a/todolist/parser.go +++ b/todolist/parser.go @@ -83,6 +83,18 @@ func (p *Parser) Contexts(input string) []string { return p.matchWords(input, r) } +func (p *Parser) ParseNotes(todo *Todo, input string) string { + r, _ := regexp.Compile(`(\w+) \d+\s+(.*)?`) + matches := r.FindStringSubmatch(input) + if matches[1] == "an" { + todo.Notes = append(todo.Notes, matches[2]) + return "add" + } + + fmt.Println("Could not match command or id") + return "" +} + func (p *Parser) hasDue(input string) bool { r1, _ := regexp.Compile(`due \w+$`) r2, _ := regexp.Compile(`due \w+ \d+$`) diff --git a/todolist/parser_test.go b/todolist/parser_test.go index 476edaa..9412bdf 100644 --- a/todolist/parser_test.go +++ b/todolist/parser_test.go @@ -74,6 +74,18 @@ func TestParseContexts(t *testing.T) { } } +func TestParseNotes(t *testing.T) { + parser := &Parser{} + todo := parser.ParseNewTodo("add search engine survey") + + if parser.ParseNotes(todo, "an 1 www.google.com") != "add" { + t.Error("Expected Notes to be added") + } + if todo.Notes[0] != "www.google.com" { + t.Error("Expected note 1 to be 'www.google.com' but got", todo.Notes[0]) + } +} + func TestDueToday(t *testing.T) { assert := assert.New(t) parser := &Parser{} diff --git a/todolist/todo_item.go b/todolist/todo_item.go index 0c30707..5b9bcbc 100644 --- a/todolist/todo_item.go +++ b/todolist/todo_item.go @@ -15,6 +15,7 @@ type Todo struct { CompletedDate string `json:"completedDate"` Archived bool `json:"archived"` IsPriority bool `json:"isPriority"` + Notes []string `json:"notes"` } func NewTodo() *Todo { diff --git a/todolist/todos.json b/todolist/todos.json index 7f511ed..39593be 100644 --- a/todolist/todos.json +++ b/todolist/todos.json @@ -1 +1 @@ -[{"id":1,"subject":"this is the first subject","projects":["test1"],"contexts":["root"],"due":"2016-04-04","completed":false,"completedDate":"","archived":true,"isPriority":false},{"id":2,"subject":" audit userify for 2FA","projects":["test1"],"contexts":["root","more"],"due":"","completed":true,"completedDate":"","archived":false,"isPriority":false}] \ No newline at end of file +[{"id":1,"subject":"this is the first subject","projects":["test1"],"contexts":["root"],"due":"2016-04-04","completed":false,"completedDate":"","archived":true,"isPriority":false,"notes":null},{"id":2,"subject":" audit userify for 2FA","projects":["test1"],"contexts":["root","more"],"due":"","completed":true,"completedDate":"","archived":false,"isPriority":false,"notes":null}] \ No newline at end of file -- cgit v1.3 From 26ec23620d50be79ea664a9095b3653be79e3874 Mon Sep 17 00:00:00 2001 From: Quey-Liang Kao Date: Mon, 14 Aug 2017 15:45:22 +0800 Subject: Implement the "ln" feature: Listing notes of a todo --- todo.go | 5 +++-- todolist/app.go | 4 +++- todolist/formatter.go | 11 +++++++++++ todolist/parser.go | 11 +++++++++-- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/todo.go b/todo.go index 77faccb..e48eda2 100644 --- a/todo.go +++ b/todo.go @@ -123,9 +123,10 @@ func usage() { fmt.Println("\tDeletes a todo with id 33\n") blueBold.Println("\nManipulating notes") - fmt.Println(" You can add additional information to a existing todo.\n") yellow.Println("\ttodo an 12 check http://this.web.site") fmt.Println("\tAdds notes \"check http://this.web.site\" to the todo with id 12\n") + yellow.Println("\ttodo ln 12") + fmt.Println("\tLists notes of the todo with id 12\n") blueBold.Println("\nGarbage Collection") yellow.Println("\ttodo gc") @@ -158,7 +159,7 @@ func routeInput(command string, input string) { app.EditTodo(input) case "ex", "expand": app.ExpandTodo(input) - case "an": + case "an", "ln": app.ManipulateNotes(input) case "gc": app.GarbageCollect() diff --git a/todolist/app.go b/todolist/app.go index c2bd66a..4d526c9 100644 --- a/todolist/app.go +++ b/todolist/app.go @@ -143,7 +143,9 @@ func (a *App) ManipulateNotes(input string) { retStr := parser.ParseNotes(todo, input) if retStr != "" { a.Save() - fmt.Println("Notes " + retStr + "ed.") + if retStr != "list" { + fmt.Println("Notes " + retStr + "ed.") + } } } diff --git a/todolist/formatter.go b/todolist/formatter.go index c0f3313..847be04 100644 --- a/todolist/formatter.go +++ b/todolist/formatter.go @@ -43,6 +43,17 @@ func (f *Formatter) Print() { f.Writer.Flush() } +func (f *Formatter) PrintNotes() { + cyan := color.New(color.FgCyan).SprintFunc() + todo := f.GroupedTodos.Groups[""][0] + f.printTodo(todo) + for nid, note := range todo.Notes { + fmt.Fprintf(f.Writer, " %s\t%s\t\n", + cyan(strconv.Itoa(nid)), note) + } + f.Writer.Flush() +} + func (f *Formatter) printTodo(todo *Todo) { yellow := color.New(color.FgYellow) if todo.IsPriority { diff --git a/todolist/parser.go b/todolist/parser.go index 207791d..1c3b7f8 100644 --- a/todolist/parser.go +++ b/todolist/parser.go @@ -84,11 +84,18 @@ func (p *Parser) Contexts(input string) []string { } func (p *Parser) ParseNotes(todo *Todo, input string) string { - r, _ := regexp.Compile(`(\w+) \d+\s+(.*)?`) + r, _ := regexp.Compile(`(\w+) \d+\s*(.*)?`) matches := r.FindStringSubmatch(input) - if matches[1] == "an" { + switch matches[1] { + case "an": todo.Notes = append(todo.Notes, matches[2]) return "add" + case "ln": + groups := map[string][]*Todo{} + groups[""] = append(groups[""], todo) + formatter := NewFormatter(&GroupedTodos{Groups: groups}) + formatter.PrintNotes() + return "list" } fmt.Println("Could not match command or id") -- cgit v1.3 From c4d6dbdb100bb66db9b184c653617c47a63e91ca Mon Sep 17 00:00:00 2001 From: Quey-Liang Kao Date: Mon, 14 Aug 2017 16:12:53 +0800 Subject: Implement the "dn" feature: Deleteing notes --- todo.go | 4 +++- todolist/parser.go | 17 +++++++++++++++++ todolist/parser_test.go | 7 +++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/todo.go b/todo.go index e48eda2..9619bdb 100644 --- a/todo.go +++ b/todo.go @@ -127,6 +127,8 @@ func usage() { fmt.Println("\tAdds notes \"check http://this.web.site\" to the todo with id 12\n") yellow.Println("\ttodo ln 12") fmt.Println("\tLists notes of the todo with id 12\n") + yellow.Println("\ttodo dn 12 3") + fmt.Println("\tDeletes the 3rd note of the todo with id 12\n") blueBold.Println("\nGarbage Collection") yellow.Println("\ttodo gc") @@ -159,7 +161,7 @@ func routeInput(command string, input string) { app.EditTodo(input) case "ex", "expand": app.ExpandTodo(input) - case "an", "ln": + case "an", "ln", "dn": app.ManipulateNotes(input) case "gc": app.GarbageCollect() diff --git a/todolist/parser.go b/todolist/parser.go index 1c3b7f8..3883454 100644 --- a/todolist/parser.go +++ b/todolist/parser.go @@ -90,12 +90,29 @@ func (p *Parser) ParseNotes(todo *Todo, input string) string { case "an": todo.Notes = append(todo.Notes, matches[2]) return "add" + case "ln": groups := map[string][]*Todo{} groups[""] = append(groups[""], todo) formatter := NewFormatter(&GroupedTodos{Groups: groups}) formatter.PrintNotes() return "list" + + case "dn": + rmid, err := strconv.Atoi(matches[2]) + if err != nil { + fmt.Println("wrong note id") + return "" + } + + for id, _ := range todo.Notes { + if id == rmid { + todo.Notes = append(todo.Notes[:rmid], todo.Notes[rmid+1:]...) + return "delete" + } + } + fmt.Println("Could not found note id") + return "" } fmt.Println("Could not match command or id") diff --git a/todolist/parser_test.go b/todolist/parser_test.go index 9412bdf..e5c7007 100644 --- a/todolist/parser_test.go +++ b/todolist/parser_test.go @@ -84,6 +84,13 @@ func TestParseNotes(t *testing.T) { if todo.Notes[0] != "www.google.com" { t.Error("Expected note 1 to be 'www.google.com' but got", todo.Notes[0]) } + + if parser.ParseNotes(todo, "dn 1 0") != "delete" { + t.Error("Expected Notes to be deleted") + } + if len(todo.Notes) != 0 { + t.Error("Expected no note") + } } func TestDueToday(t *testing.T) { -- cgit v1.3 From 7c24f39a0fc8bb07dc9db4f5fecd3468705b1e37 Mon Sep 17 00:00:00 2001 From: Quey-Liang Kao Date: Mon, 14 Aug 2017 16:34:33 +0800 Subject: Implement the "en" feature: Editting notes --- todo.go | 4 +++- todolist/parser.go | 30 ++++++++++++++++++++++++++++-- todolist/parser_test.go | 7 +++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/todo.go b/todo.go index 9619bdb..cda6cc3 100644 --- a/todo.go +++ b/todo.go @@ -129,6 +129,8 @@ func usage() { fmt.Println("\tLists notes of the todo with id 12\n") yellow.Println("\ttodo dn 12 3") fmt.Println("\tDeletes the 3rd note of the todo with id 12\n") + yellow.Println("\ttodo en 12 3 check http://that.web.site") + fmt.Println("\tEditing the 3rd note of the todo with id 12 to \"http://that.web.site\" \n") blueBold.Println("\nGarbage Collection") yellow.Println("\ttodo gc") @@ -161,7 +163,7 @@ func routeInput(command string, input string) { app.EditTodo(input) case "ex", "expand": app.ExpandTodo(input) - case "an", "ln", "dn": + case "an", "ln", "dn", "en": app.ManipulateNotes(input) case "gc": app.GarbageCollect() diff --git a/todolist/parser.go b/todolist/parser.go index 3883454..42af133 100644 --- a/todolist/parser.go +++ b/todolist/parser.go @@ -99,9 +99,8 @@ func (p *Parser) ParseNotes(todo *Todo, input string) string { return "list" case "dn": - rmid, err := strconv.Atoi(matches[2]) + rmid, err := p.getNoteID(matches[2]) if err != nil { - fmt.Println("wrong note id") return "" } @@ -113,12 +112,39 @@ func (p *Parser) ParseNotes(todo *Todo, input string) string { } fmt.Println("Could not found note id") return "" + + case "en": + r1, _ := regexp.Compile(`(\d)+\s+(.*)?`) + tail := r1.FindStringSubmatch(matches[2]) + edid, err := p.getNoteID(tail[1]) + if err != nil { + return "" + } + + for id, _ := range todo.Notes { + if id == edid { + todo.Notes[id] = tail[2] + return "edit" + } + } + + fmt.Println("Could not found note id") + return "" } fmt.Println("Could not match command or id") return "" } +func (p *Parser) getNoteID(input string) (int, error) { + ret, err := strconv.Atoi(input) + if err != nil { + fmt.Println("wrong note id") + return -1, err + } + return ret, nil +} + func (p *Parser) hasDue(input string) bool { r1, _ := regexp.Compile(`due \w+$`) r2, _ := regexp.Compile(`due \w+ \d+$`) diff --git a/todolist/parser_test.go b/todolist/parser_test.go index e5c7007..2c4fd25 100644 --- a/todolist/parser_test.go +++ b/todolist/parser_test.go @@ -85,6 +85,13 @@ func TestParseNotes(t *testing.T) { t.Error("Expected note 1 to be 'www.google.com' but got", todo.Notes[0]) } + if parser.ParseNotes(todo, "en 1 0 www.duckduckgo.com") != "edit" { + t.Error("Expected Notes to be editted") + } + if todo.Notes[0] != "www.duckduckgo.com" { + t.Error("Expected note 1 to be 'www.duckduckgo.com' but got", todo.Notes[0]) + } + if parser.ParseNotes(todo, "dn 1 0") != "delete" { t.Error("Expected Notes to be deleted") } -- cgit v1.3 From 7bd6749e7fdfbc636b15cb18d89081eb78f870a8 Mon Sep 17 00:00:00 2001 From: Quey-Liang Kao Date: Sun, 20 Aug 2017 22:06:05 +0800 Subject: Fix out-of-date usage according to internal API changes Since the getId() function has been changed, the call in ManipulateNotes() is fixed in this patch. --- todolist/app.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/todolist/app.go b/todolist/app.go index 96da67f..66b30c8 100644 --- a/todolist/app.go +++ b/todolist/app.go @@ -139,9 +139,11 @@ func (a *App) ExpandTodo(input string) { func (a *App) ManipulateNotes(input string) { a.Load() - id, todo := a.getId(input) + id := a.getId(input) parser := &Parser{} - if id == -1 { + todo := a.TodoList.FindById(id) + if todo == nil { + fmt.Println("No such id.") return } -- cgit v1.3 From 34639c4285621177efb10b82ddb07cd0017af56a Mon Sep 17 00:00:00 2001 From: Quey-Liang Kao Date: Sun, 20 Aug 2017 22:45:31 +0800 Subject: Redefine sub-commands: "ln" and "n" Sub-command "ln" is redefined to the function of listing all todos with their notes; "n" replaces original "ln", listing the notes of a specific todo. --- todo.go | 8 +++++--- todolist/app.go | 3 ++- todolist/filter.go | 4 ++-- todolist/formatter.go | 19 +++++++------------ todolist/parser.go | 4 ++-- 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/todo.go b/todo.go index cda6cc3..d2bc7ab 100644 --- a/todo.go +++ b/todo.go @@ -123,9 +123,11 @@ func usage() { fmt.Println("\tDeletes a todo with id 33\n") blueBold.Println("\nManipulating notes") + yellow.Println("\ttodo ln") + fmt.Println("\tlists all todos with their notes") yellow.Println("\ttodo an 12 check http://this.web.site") fmt.Println("\tAdds notes \"check http://this.web.site\" to the todo with id 12\n") - yellow.Println("\ttodo ln 12") + yellow.Println("\ttodo n 12") fmt.Println("\tLists notes of the todo with id 12\n") yellow.Println("\ttodo dn 12 3") fmt.Println("\tDeletes the 3rd note of the todo with id 12\n") @@ -143,7 +145,7 @@ func usage() { func routeInput(command string, input string) { app := todolist.NewApp() switch command { - case "l", "list", "agenda": + case "l", "ln", "list", "agenda": app.ListTodos(input) case "a", "add": app.AddTodo(input) @@ -163,7 +165,7 @@ func routeInput(command string, input string) { app.EditTodo(input) case "ex", "expand": app.ExpandTodo(input) - case "an", "ln", "dn", "en": + case "an", "n", "dn", "en": app.ManipulateNotes(input) case "gc": app.GarbageCollect() diff --git a/todolist/app.go b/todolist/app.go index 66b30c8..79e3aad 100644 --- a/todolist/app.go +++ b/todolist/app.go @@ -173,7 +173,8 @@ func (a *App) ListTodos(input string) { grouped := a.getGroups(input, filtered) formatter := NewFormatter(grouped) - formatter.Print() + re, _ := regexp.Compile(`^ln`) + formatter.Print(re.MatchString(input)) } func (a *App) PrioritizeTodo(input string) { diff --git a/todolist/filter.go b/todolist/filter.go index dd61d11..88b28a7 100644 --- a/todolist/filter.go +++ b/todolist/filter.go @@ -38,7 +38,7 @@ func (f *TodoFilter) filterArchived(input string) []*Todo { return f.Todos } - r, _ := regexp.Compile(`l archived$`) + r, _ := regexp.Compile(`ln? archived$`) if r.MatchString(input) { return f.getArchived() } else { @@ -47,7 +47,7 @@ func (f *TodoFilter) filterArchived(input string) []*Todo { } func (f *TodoFilter) filterPrioritized(input string) []*Todo { - r, _ := regexp.Compile(`l p`) + r, _ := regexp.Compile(`ln? p`) if r.MatchString(input) { return f.getPrioritized() } else { diff --git a/todolist/formatter.go b/todolist/formatter.go index 847be04..e7863db 100644 --- a/todolist/formatter.go +++ b/todolist/formatter.go @@ -25,7 +25,7 @@ func NewFormatter(todos *GroupedTodos) *Formatter { return formatter } -func (f *Formatter) Print() { +func (f *Formatter) Print(printNotes bool) { cyan := color.New(color.FgCyan).SprintFunc() var keys []string @@ -38,22 +38,17 @@ func (f *Formatter) Print() { fmt.Fprintf(f.Writer, "\n %s\n", cyan(key)) for _, todo := range f.GroupedTodos.Groups[key] { f.printTodo(todo) + if printNotes { + for nid, note := range todo.Notes { + fmt.Fprintf(f.Writer, " %s\t%s\t\n", + cyan(strconv.Itoa(nid)), note) + } + } } } f.Writer.Flush() } -func (f *Formatter) PrintNotes() { - cyan := color.New(color.FgCyan).SprintFunc() - todo := f.GroupedTodos.Groups[""][0] - f.printTodo(todo) - for nid, note := range todo.Notes { - fmt.Fprintf(f.Writer, " %s\t%s\t\n", - cyan(strconv.Itoa(nid)), note) - } - f.Writer.Flush() -} - func (f *Formatter) printTodo(todo *Todo) { yellow := color.New(color.FgYellow) if todo.IsPriority { diff --git a/todolist/parser.go b/todolist/parser.go index 42af133..8f5e180 100644 --- a/todolist/parser.go +++ b/todolist/parser.go @@ -91,11 +91,11 @@ func (p *Parser) ParseNotes(todo *Todo, input string) string { todo.Notes = append(todo.Notes, matches[2]) return "add" - case "ln": + case "n": groups := map[string][]*Todo{} groups[""] = append(groups[""], todo) formatter := NewFormatter(&GroupedTodos{Groups: groups}) - formatter.PrintNotes() + formatter.Print(true) return "list" case "dn": -- cgit v1.3 From a716a04c831e4fb23cdd558756d8f393e4ef8d73 Mon Sep 17 00:00:00 2001 From: Quey-Liang Kao Date: Tue, 29 Aug 2017 17:00:18 +0800 Subject: Refactor previous commits Rewrite the `ManipulateNotes` function into `HandleNotes`, which routes the note sub-commands to calls of newly-written `Parse*Note` functions. On successful parse, these functions return true, and false otherwise. Related tests are also refined. --- todo.go | 2 +- todolist/app.go | 26 +++++++++----- todolist/parser.go | 95 +++++++++++++++++++++++++++---------------------- todolist/parser_test.go | 72 ++++++++++++++++++++++++++++++++++--- 4 files changed, 139 insertions(+), 56 deletions(-) diff --git a/todo.go b/todo.go index d2bc7ab..645a880 100644 --- a/todo.go +++ b/todo.go @@ -166,7 +166,7 @@ func routeInput(command string, input string) { case "ex", "expand": app.ExpandTodo(input) case "an", "n", "dn", "en": - app.ManipulateNotes(input) + app.HandleNotes(input) case "gc": app.GarbageCollect() case "p", "prioritize": diff --git a/todolist/app.go b/todolist/app.go index 79e3aad..92ee64d 100644 --- a/todolist/app.go +++ b/todolist/app.go @@ -137,23 +137,33 @@ func (a *App) ExpandTodo(input string) { fmt.Println("Todo expanded.") } -func (a *App) ManipulateNotes(input string) { +func (a *App) HandleNotes(input string) { a.Load() id := a.getId(input) - parser := &Parser{} + if id == -1 { + return + } todo := a.TodoList.FindById(id) if todo == nil { fmt.Println("No such id.") return } + parser := &Parser{} - retStr := parser.ParseNotes(todo, input) - if retStr != "" { - a.Save() - if retStr != "list" { - fmt.Println("Notes " + retStr + "ed.") - } + if parser.ParseAddNote(todo, input) { + fmt.Println("Note added.") + } else if parser.ParseDeleteNote(todo, input) { + fmt.Println("Note deleted.") + } else if parser.ParseEditNote(todo, input) { + fmt.Println("Note edited.") + } else if parser.ParseShowNote(todo, input) { + groups := map[string][]*Todo{} + groups[""] = append(groups[""], todo) + formatter := NewFormatter(&GroupedTodos{Groups: groups}) + formatter.Print(true) + return } + a.Save() } func (a *App) ArchiveCompleted() { diff --git a/todolist/parser.go b/todolist/parser.go index 8f5e180..6ad8007 100644 --- a/todolist/parser.go +++ b/todolist/parser.go @@ -83,57 +83,66 @@ func (p *Parser) Contexts(input string) []string { return p.matchWords(input, r) } -func (p *Parser) ParseNotes(todo *Todo, input string) string { - r, _ := regexp.Compile(`(\w+) \d+\s*(.*)?`) +func (p *Parser) ParseAddNote(todo *Todo, input string) bool { + r, _ := regexp.Compile(`^an\s+\d+\s+(.*)`) matches := r.FindStringSubmatch(input) - switch matches[1] { - case "an": - todo.Notes = append(todo.Notes, matches[2]) - return "add" - - case "n": - groups := map[string][]*Todo{} - groups[""] = append(groups[""], todo) - formatter := NewFormatter(&GroupedTodos{Groups: groups}) - formatter.Print(true) - return "list" - - case "dn": - rmid, err := p.getNoteID(matches[2]) - if err != nil { - return "" - } + if len(matches) != 2 { + return false + } - for id, _ := range todo.Notes { - if id == rmid { - todo.Notes = append(todo.Notes[:rmid], todo.Notes[rmid+1:]...) - return "delete" - } - } - fmt.Println("Could not found note id") - return "" + todo.Notes = append(todo.Notes, matches[1]) + return true +} - case "en": - r1, _ := regexp.Compile(`(\d)+\s+(.*)?`) - tail := r1.FindStringSubmatch(matches[2]) - edid, err := p.getNoteID(tail[1]) - if err != nil { - return "" - } +func (p *Parser) ParseDeleteNote(todo *Todo, input string) bool { + r, _ := regexp.Compile(`^dn\s+\d+\s+(\d+)`) + matches := r.FindStringSubmatch(input) + if len(matches) != 2 { + return false + } + + rmid, err := p.getNoteID(matches[1]) + if err != nil { + return false + } - for id, _ := range todo.Notes { - if id == edid { - todo.Notes[id] = tail[2] - return "edit" - } + for id, _ := range todo.Notes { + if id == rmid { + todo.Notes = append(todo.Notes[:rmid], todo.Notes[rmid+1:]...) + return true } + } + return false +} - fmt.Println("Could not found note id") - return "" +func (p *Parser) ParseEditNote(todo *Todo, input string) bool { + r, _ := regexp.Compile(`^en\s+\d+\s+(\d+)\s+(.*)`) + matches := r.FindStringSubmatch(input) + if len(matches) != 3 { + return false + } + + edid, err := p.getNoteID(matches[1]) + if err != nil { + return false } - fmt.Println("Could not match command or id") - return "" + for id, _ := range todo.Notes { + if id == edid { + todo.Notes[id] = matches[2] + return true + } + } + return false +} + +func (p *Parser) ParseShowNote(todo *Todo, input string) bool { + r, _ := regexp.Compile(`^n\s+\d+`) + matches := r.FindStringSubmatch(input) + if len(matches) != 1 { + return false + } + return true } func (p *Parser) getNoteID(input string) (int, error) { diff --git a/todolist/parser_test.go b/todolist/parser_test.go index 2c4fd25..313ad9f 100644 --- a/todolist/parser_test.go +++ b/todolist/parser_test.go @@ -74,25 +74,89 @@ func TestParseContexts(t *testing.T) { } } -func TestParseNotes(t *testing.T) { +func TestParseAddNote(t *testing.T) { + parser := &Parser{} + todo := parser.ParseNewTodo("add write the test functions") + + b1 := parser.ParseAddNote(todo, "an 1 TestPasrseAddNote") + b2 := parser.ParseAddNote(todo, "an 1 TestPasrseDeleteNote") + b3 := parser.ParseAddNote(todo, "an 1 TestPasrseEditNote") + + if !b1 || !b2 || !b3 { + t.Error("Fail adding notes, expected 3 notes but", len(todo.Notes)) + } +} + +func TestParseDeleteNote(t *testing.T) { + parser := &Parser{} + todo := parser.ParseNewTodo("add buy notebook") + + todo.Notes = append(todo.Notes, "ASUStek") + todo.Notes = append(todo.Notes, "Apple") + todo.Notes = append(todo.Notes, "Dell") + todo.Notes = append(todo.Notes, "Acer") + + b1 := parser.ParseDeleteNote(todo, "dn 1 1") + b2 := parser.ParseDeleteNote(todo, "dn 1 1") + + if !b1 || !b2 { + t.Error("Fail deleting notes, expected 2 notes left but", len(todo.Notes)) + } + + if todo.Notes[0] != "ASUStek" || todo.Notes[1] != "Acer" { + t.Error("Fail deleting notes,", todo.Notes[0], "and", todo.Notes[1], "are left") + } +} + +func TestParseEditNote(t *testing.T) { + parser := &Parser{} + todo := parser.ParseNewTodo("add record the weather") + + todo.Notes = append(todo.Notes, "Aug 29 Wed") + todo.Notes = append(todo.Notes, "Cloudy") + todo.Notes = append(todo.Notes, "40°C") + todo.Notes = append(todo.Notes, "Tokyo") + + parser.ParseEditNote(todo, "en 1 0 Aug 29 Tue") + if todo.Notes[0] != "Aug 29 Tue" { + t.Error("Fail editing notes, note 0 should be \"Aug 29 Tue\" but got", todo.Notes[0]) + } + + parser.ParseEditNote(todo, "en 1 1 Sunny") + if todo.Notes[1] != "Sunny" { + t.Error("Fail editing notes, note 1 should be \"Sunny\" but got", todo.Notes[1]) + } + + parser.ParseEditNote(todo, "en 1 2 22°C") + if todo.Notes[2] != "22°C" { + t.Error("Fail editing notes, note 2 should be \"22°C\" but got", todo.Notes[2]) + } + + parser.ParseEditNote(todo, "en 1 3 Seoul") + if todo.Notes[3] != "Seoul" { + t.Error("Fail editing notes, note 3 should be \"Seoul\" but got", todo.Notes[3]) + } +} + +func TestHandleNotes(t *testing.T) { parser := &Parser{} todo := parser.ParseNewTodo("add search engine survey") - if parser.ParseNotes(todo, "an 1 www.google.com") != "add" { + if !parser.ParseAddNote(todo, "an 1 www.google.com") { t.Error("Expected Notes to be added") } if todo.Notes[0] != "www.google.com" { t.Error("Expected note 1 to be 'www.google.com' but got", todo.Notes[0]) } - if parser.ParseNotes(todo, "en 1 0 www.duckduckgo.com") != "edit" { + if !parser.ParseEditNote(todo, "en 1 0 www.duckduckgo.com") { t.Error("Expected Notes to be editted") } if todo.Notes[0] != "www.duckduckgo.com" { t.Error("Expected note 1 to be 'www.duckduckgo.com' but got", todo.Notes[0]) } - if parser.ParseNotes(todo, "dn 1 0") != "delete" { + if !parser.ParseDeleteNote(todo, "dn 1 0") { t.Error("Expected Notes to be deleted") } if len(todo.Notes) != 0 { -- cgit v1.3