diff options
| -rw-r--r-- | todo.go | 13 | ||||
| -rw-r--r-- | todolist/app.go | 22 | ||||
| -rw-r--r-- | todolist/filter.go | 22 | ||||
| -rw-r--r-- | todolist/formatter.go | 52 | ||||
| -rw-r--r-- | todolist/todo_item.go | 17 | ||||
| -rw-r--r-- | todolist/todo_list.go | 14 | ||||
| -rw-r--r-- | todolist/todo_list_test.go | 20 | ||||
| -rw-r--r-- | todolist/todos.json | 2 |
8 files changed, 134 insertions, 28 deletions
@@ -81,6 +81,15 @@ func usage() { yellow.Println("\ttodo uc 33") fmt.Println("\tUncompletes a todo with id 33\n") + blueBold.Println("\nPrioritizing") + fmt.Println("Todos have a priority flag, which will make them bold when listed.\n") + yellow.Println("\ttodo p 33") + fmt.Println("\tPrioritizes a todo with id 33\n") + yellow.Println("\ttodo up 33") + fmt.Println("\tUn-prioritizes a todo with id 33\n") + yellow.Println("\ttodo l p") + fmt.Println("\tlist all priority todos\n") + blueBold.Println("\nArchiving") fmt.Println("You can archive todos once they are done, or if you might come back to them.") fmt.Println("By default, todo will only show unarchived todos.\n") @@ -131,6 +140,10 @@ func routeInput(command string, input string) { app.EditTodoDue(input) case "ex", "expand": app.ExpandTodo(input) + case "p", "prioritize": + app.PrioritizeTodo(input) + case "up", "unprioritize": + app.UnprioritizeTodo(input) case "init": app.InitializeRepo() case "web": diff --git a/todolist/app.go b/todolist/app.go index 1ab6b20..495d087 100644 --- a/todolist/app.go +++ b/todolist/app.go @@ -150,6 +150,28 @@ func (a *App) ListTodos(input string) { formatter.Print() } +func (a *App) PrioritizeTodo(input string) { + a.Load() + id, _ := a.getId(input) + if id == -1 { + return + } + a.TodoList.Prioritize(id) + a.Save() + fmt.Println("Todo prioritized.") +} + +func (a *App) UnprioritizeTodo(input string) { + a.Load() + id, _ := a.getId(input) + if id == -1 { + return + } + a.TodoList.Unprioritize(id) + a.Save() + fmt.Println("Todo un-prioritized.") +} + func (a *App) getId(input string) (int, *Todo) { re, _ := regexp.Compile("\\d+") if re.MatchString(input) { diff --git a/todolist/filter.go b/todolist/filter.go index 2b25109..b577e60 100644 --- a/todolist/filter.go +++ b/todolist/filter.go @@ -12,6 +12,7 @@ func NewFilter(todos []*Todo) *TodoFilter { func (f *TodoFilter) Filter(input string) []*Todo { f.Todos = f.filterArchived(input) + f.Todos = f.filterPrioritized(input) f.Todos = f.filterProjects(input) f.Todos = f.filterContexts(input) f.Todos = NewDateFilter(f.Todos).FilterDate(input) @@ -38,6 +39,15 @@ func (f *TodoFilter) filterArchived(input string) []*Todo { } } +func (f *TodoFilter) filterPrioritized(input string) []*Todo { + r, _ := regexp.Compile(`l p`) + if r.MatchString(input) { + return f.getPrioritized() + } else { + return f.Todos + } +} + func (f *TodoFilter) filterProjects(input string) []*Todo { if !f.isFilteringByProjects(input) { return f.Todos @@ -81,7 +91,17 @@ func (f *TodoFilter) filterContexts(input string) []*Todo { func (f *TodoFilter) getArchived() []*Todo { var ret []*Todo for _, todo := range f.Todos { - if todo.Archived == true { + if todo.Archived { + ret = append(ret, todo) + } + } + return ret +} + +func (f *TodoFilter) getPrioritized() []*Todo { + var ret []*Todo + for _, todo := range f.Todos { + if todo.IsPriority { ret = append(ret, todo) } } diff --git a/todolist/formatter.go b/todolist/formatter.go index 43d9b1e..c0f3313 100644 --- a/todolist/formatter.go +++ b/todolist/formatter.go @@ -44,20 +44,28 @@ func (f *Formatter) Print() { } func (f *Formatter) printTodo(todo *Todo) { - yellow := color.New(color.FgYellow).SprintFunc() + yellow := color.New(color.FgYellow) + if todo.IsPriority { + yellow.Add(color.Bold, color.Italic) + } fmt.Fprintf(f.Writer, " %s\t%s\t%s\t%s\t\n", - yellow(strconv.Itoa(todo.Id)), + yellow.SprintFunc()(strconv.Itoa(todo.Id)), f.formatCompleted(todo.Completed), - f.formatDue(todo.Due), - f.formatSubject(todo.Subject)) + f.formatDue(todo.Due, todo.IsPriority), + f.formatSubject(todo.Subject, todo.IsPriority)) } -func (f *Formatter) formatDue(due string) string { - blue := color.New(color.FgBlue).SprintFunc() - red := color.New(color.FgRed).SprintFunc() +func (f *Formatter) formatDue(due string, isPriority bool) string { + blue := color.New(color.FgBlue) + red := color.New(color.FgRed) + + if isPriority { + blue.Add(color.Bold, color.Italic) + red.Add(color.Bold, color.Italic) + } if due == "" { - return blue(" ") + return blue.SprintFunc()(" ") } dueTime, err := time.Parse("2006-01-02", due) @@ -68,13 +76,13 @@ func (f *Formatter) formatDue(due string) string { } if isToday(dueTime) { - return blue("today") + return blue.SprintFunc()("today") } else if isTomorrow(dueTime) { - return blue("tomorrow") + return blue.SprintFunc()("tomorrow") } else if isPastDue(dueTime) { - return red(dueTime.Format("Mon Jan 2")) + return red.SprintFunc()(dueTime.Format("Mon Jan 2")) } else { - return blue(dueTime.Format("Mon Jan 2")) + return blue.SprintFunc()(dueTime.Format("Mon Jan 2")) } } @@ -98,9 +106,17 @@ func isPastDue(t time.Time) bool { return time.Now().After(t) } -func (f *Formatter) formatSubject(subject string) string { - red := color.New(color.FgRed).SprintFunc() - magenta := color.New(color.FgMagenta).SprintFunc() +func (f *Formatter) formatSubject(subject string, isPriority bool) string { + + red := color.New(color.FgRed) + magenta := color.New(color.FgMagenta) + white := color.New(color.FgWhite) + + if isPriority { + red.Add(color.Bold, color.Italic) + magenta.Add(color.Bold, color.Italic) + white.Add(color.Bold, color.Italic) + } splitted := strings.Split(subject, " ") projectRegex, _ := regexp.Compile(`\+[\p{L}\d_]+`) @@ -110,11 +126,11 @@ func (f *Formatter) formatSubject(subject string) string { for _, word := range splitted { if projectRegex.MatchString(word) { - coloredWords = append(coloredWords, magenta(word)) + coloredWords = append(coloredWords, magenta.SprintFunc()(word)) } else if contextRegex.MatchString(word) { - coloredWords = append(coloredWords, red(word)) + coloredWords = append(coloredWords, red.SprintFunc()(word)) } else { - coloredWords = append(coloredWords, word) + coloredWords = append(coloredWords, white.SprintFunc()(word)) } } return strings.Join(coloredWords, " ") diff --git a/todolist/todo_item.go b/todolist/todo_item.go index 6b820b1..273df8d 100644 --- a/todolist/todo_item.go +++ b/todolist/todo_item.go @@ -3,17 +3,18 @@ package todolist import "time" type Todo struct { - Id int `json:"id"` - Subject string `json:"subject"` - Projects []string `json:"projects"` - Contexts []string `json:"contexts"` - Due string `json:"due"` - Completed bool `json:"completed"` - Archived bool `json:"archived"` + Id int `json:"id"` + Subject string `json:"subject"` + Projects []string `json:"projects"` + Contexts []string `json:"contexts"` + Due string `json:"due"` + Completed bool `json:"completed"` + Archived bool `json:"archived"` + IsPriority bool `json:"isPriority"` } func NewTodo() *Todo { - return &Todo{Completed: false, Archived: false} + return &Todo{Completed: false, Archived: false, IsPriority: false} } func (t Todo) Valid() bool { diff --git a/todolist/todo_list.go b/todolist/todo_list.go index d7e1f83..71484c6 100644 --- a/todolist/todo_list.go +++ b/todolist/todo_list.go @@ -63,6 +63,20 @@ func (t *TodoList) IndexOf(todoToFind *Todo) int { return -1 } +func (t *TodoList) Prioritize(id int) { + todo := t.FindById(id) + todo.IsPriority = true + t.Delete(id) + t.Data = append(t.Data, todo) +} + +func (t *TodoList) Unprioritize(id int) { + todo := t.FindById(id) + todo.IsPriority = false + t.Delete(id) + t.Data = append(t.Data, todo) +} + type ByDate []*Todo func (a ByDate) Len() int { return len(a) } diff --git a/todolist/todo_list_test.go b/todolist/todo_list_test.go index 8a40b14..bd0f926 100644 --- a/todolist/todo_list_test.go +++ b/todolist/todo_list_test.go @@ -77,3 +77,23 @@ func TestUncomplete(t *testing.T) { list.Uncomplete(2) assert.Equal(false, list.FindById(2).Completed) } + +func TestPrioritizeNotInTodosJson(t *testing.T) { + assert := assert.New(t) + store := &FileStore{FileLocation: "todos.json"} + list := &TodoList{} + todos, _ := store.Load() + list.Load(todos) + assert.Equal(false, list.FindById(2).IsPriority) +} + +func TestPrioritizeTodo(t *testing.T) { + assert := assert.New(t) + list := &TodoList{} + todo := &Todo{Archived: false, Completed: false, Subject: "testing", IsPriority: false} + list.Add(todo) + list.Prioritize(1) + assert.Equal(true, list.FindById(1).IsPriority) + list.Unprioritize(1) + assert.Equal(false, list.FindById(1).IsPriority) +} diff --git a/todolist/todos.json b/todolist/todos.json index 5e44228..bc147d1 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,"archived":true},{"id":2,"subject":" audit userify for 2FA","projects":["test1"],"contexts":["root","more"],"due":"","completed":true,"archived":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,"archived":true,"isPriority":false},{"id":2,"subject":" audit userify for 2FA","projects":["test1"],"contexts":["root","more"],"due":"","completed":true,"archived":false,"isPriority":false}]
\ No newline at end of file |
