aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrant Ammons <gammons@gmail.com>2017-08-15 19:32:36 -0600
committerGitHub <noreply@github.com>2017-08-15 19:32:36 -0600
commit620a9f3aff090063f79285fb20437a62ce089a4e (patch)
tree50c57801c9f1edb7ad1b80aa314c5c340f97d9f3
parent9f62f82025e4dd7fa3a0dfc50bb94704209e608c (diff)
parentb1607ce3bfaf54936338d8639087dee52f7d7bc2 (diff)
Merge pull request #85 from stuartskelton/multiple_ids_for_actions
Allow for ranged ids in some commands
-rw-r--r--todolist/app.go99
-rw-r--r--todolist/app_test.go29
-rw-r--r--todolist/todo_list.go110
-rw-r--r--todolist/util.go7
-rw-r--r--todolist/util_test.go13
5 files changed, 187 insertions, 71 deletions
diff --git a/todolist/app.go b/todolist/app.go
index 367cc2f..f63c41b 100644
--- a/todolist/app.go
+++ b/todolist/app.go
@@ -38,65 +38,70 @@ func (a *App) AddTodo(input string) {
func (a *App) DeleteTodo(input string) {
a.Load()
- id, _ := a.getId(input)
- if id == -1 {
+ ids := a.getIds(input)
+ if len(ids) == 0 {
return
}
- a.TodoList.Delete(id)
+ a.TodoList.Delete(ids...)
a.Save()
- fmt.Println("Todo deleted.")
+ fmt.Printf("%s deleted.\n", pluralize(len(ids), "Todo", "Todos"))
}
func (a *App) CompleteTodo(input string) {
a.Load()
- id, _ := a.getId(input)
- if id == -1 {
+ ids := a.getIds(input)
+ if len(ids) == 0 {
return
}
- a.TodoList.Complete(id)
+ a.TodoList.Complete(ids...)
a.Save()
fmt.Println("Todo completed.")
}
func (a *App) UncompleteTodo(input string) {
a.Load()
- id, _ := a.getId(input)
- if id == -1 {
+ ids := a.getIds(input)
+ if len(ids) == 0 {
return
}
- a.TodoList.Uncomplete(id)
+ a.TodoList.Uncomplete(ids...)
a.Save()
fmt.Println("Todo uncompleted.")
}
func (a *App) ArchiveTodo(input string) {
a.Load()
- id, _ := a.getId(input)
- if id == -1 {
+ ids := a.getIds(input)
+ if len(ids) == 0 {
return
}
- a.TodoList.Archive(id)
+ a.TodoList.Archive(ids...)
a.Save()
fmt.Println("Todo archived.")
}
func (a *App) UnarchiveTodo(input string) {
a.Load()
- id, _ := a.getId(input)
- if id == -1 {
+ ids := a.getIds(input)
+ if len(ids) == 0 {
return
}
- a.TodoList.Unarchive(id)
+ a.TodoList.Unarchive(ids...)
a.Save()
fmt.Println("Todo unarchived.")
}
func (a *App) EditTodo(input string) {
a.Load()
- id, todo := a.getId(input)
+ id := a.getId(input)
if id == -1 {
return
}
+ todo := a.TodoList.FindById(id)
+ if todo == nil {
+ fmt.Println("No such id.")
+ return
+ }
parser := &Parser{}
if parser.ParseEditTodo(todo, input) {
@@ -107,7 +112,7 @@ func (a *App) EditTodo(input string) {
func (a *App) ExpandTodo(input string) {
a.Load()
- id, _ := a.getId(input)
+ id := a.getId(input)
parser := &Parser{}
if id == -1 {
return
@@ -154,43 +159,69 @@ func (a *App) ListTodos(input string) {
func (a *App) PrioritizeTodo(input string) {
a.Load()
- id, _ := a.getId(input)
- if id == -1 {
+ ids := a.getIds(input)
+ if len(ids) == 0 {
return
}
- a.TodoList.Prioritize(id)
+ a.TodoList.Prioritize(ids...)
a.Save()
fmt.Println("Todo prioritized.")
}
func (a *App) UnprioritizeTodo(input string) {
a.Load()
- id, _ := a.getId(input)
- if id == -1 {
+ ids := a.getIds(input)
+ if len(ids) == 0 {
return
}
- a.TodoList.Unprioritize(id)
+ a.TodoList.Unprioritize(ids...)
a.Save()
fmt.Println("Todo un-prioritized.")
}
-func (a *App) getId(input string) (int, *Todo) {
+func (a *App) getId(input string) int {
re, _ := regexp.Compile("\\d+")
if re.MatchString(input) {
id, _ := strconv.Atoi(re.FindString(input))
- todo := a.TodoList.FindById(id)
- if todo == nil {
- fmt.Println("No such id.")
- return -1, nil
+ return id
+ }
- }
- return id, todo
+ fmt.Println("Invalid id.")
+ return -1
+}
- } else {
- fmt.Println("Invalid id.")
- return -1, nil
+func (a *App) getIds(input string) (ids []int) {
+
+ idGroups := strings.Split(input, ",")
+ for _, idGroup := range idGroups {
+ if rangedIds, err := a.parseRangedIds(idGroup); len(rangedIds) > 0 || err != nil {
+ if err != nil {
+ fmt.Printf("Invalid id group: %s.\n", input)
+ continue
+ }
+ ids = append(ids, rangedIds...)
+ } else if id := a.getId(idGroup); id != -1 {
+ ids = append(ids, id)
+ } else {
+ fmt.Printf("Invalid id: %s.\n", idGroup)
+ }
+ }
+ return ids
+}
+func (a *App) parseRangedIds(input string) (ids []int, err error) {
+ rangeNumberRE, _ := regexp.Compile("(\\d+)-(\\d+)")
+ if matches := rangeNumberRE.FindStringSubmatch(input); len(matches) > 0 {
+ lowerID, _ := strconv.Atoi(matches[1])
+ upperID, _ := strconv.Atoi(matches[2])
+ if lowerID >= upperID {
+ return ids, fmt.Errorf("Invalid id group: %s.\n", input)
+ }
+ for id := lowerID; id <= upperID; id++ {
+ ids = append(ids, id)
+ }
}
+ return ids, err
}
func (a *App) getGroups(input string, todos []*Todo) *GroupedTodos {
diff --git a/todolist/app_test.go b/todolist/app_test.go
index f29a1b6..2fb7717 100644
--- a/todolist/app_test.go
+++ b/todolist/app_test.go
@@ -108,3 +108,32 @@ func TestListbyContext(t *testing.T) {
}
assert.Equal(true, hasACompletedTodo)
}
+
+func TestGetId(t *testing.T) {
+ assert := assert.New(t)
+ app := &App{TodoList: &TodoList{}, TodoStore: &MemoryStore{}}
+ // not a valid id
+ assert.Equal(-1, app.getId("p"))
+ // a single digit id
+ assert.Equal(6, app.getId("6"))
+ // a double digit id
+ assert.Equal(66, app.getId("66"))
+}
+
+func TestGetIds(t *testing.T) {
+ assert := assert.New(t)
+ app := &App{TodoList: &TodoList{}, TodoStore: &MemoryStore{}}
+ // no valid id here
+ assert.Equal(0, len(app.getIds("p")))
+ // one valid value here
+ assert.Equal([]int{6}, app.getIds("6"))
+ // lots of single post numbers
+ assert.Equal([]int{6, 10, 8, 4}, app.getIds("6,10,8,4"))
+ // a correct range
+ assert.Equal([]int{6, 7, 8}, app.getIds("6-8"))
+ // some incorrect ranges
+ assert.Equal(0, len(app.getIds("6-6")))
+ assert.Equal(0, len(app.getIds("8-6")))
+ // some compsite ranges
+ assert.Equal([]int{5, 6, 7, 8, 10, 11, 9}, app.getIds("5,6-8,10-11,9"))
+}
diff --git a/todolist/todo_list.go b/todolist/todo_list.go
index 4623a22..55c250d 100644
--- a/todolist/todo_list.go
+++ b/todolist/todo_list.go
@@ -15,57 +15,93 @@ func (t *TodoList) Add(todo *Todo) {
t.Data = append(t.Data, todo)
}
-func (t *TodoList) Delete(id int) {
- i := -1
- for index, todo := range t.Data {
- if todo.Id == id {
- i = index
+func (t *TodoList) Delete(ids ...int) {
+ for _, id := range ids {
+ todo := t.FindById(id)
+ if todo == nil {
+ continue
+ }
+ i := -1
+ for index, todo := range t.Data {
+ if todo.Id == id {
+ i = index
+ }
}
- }
- t.Data = append(t.Data[:i], t.Data[i+1:]...)
+ t.Data = append(t.Data[:i], t.Data[i+1:]...)
+ }
}
-func (t *TodoList) Complete(id int) {
- todo := t.FindById(id)
- todo.Complete()
- t.Delete(id)
- t.Data = append(t.Data, todo)
+func (t *TodoList) Complete(ids ...int) {
+ for _, id := range ids {
+ todo := t.FindById(id)
+ if todo == nil {
+ continue
+ }
+ todo.Complete()
+ t.Delete(id)
+ t.Data = append(t.Data, todo)
+ }
}
-func (t *TodoList) Uncomplete(id int) {
- todo := t.FindById(id)
- todo.Uncomplete()
- t.Delete(id)
- t.Data = append(t.Data, todo)
+func (t *TodoList) Uncomplete(ids ...int) {
+ for _, id := range ids {
+ todo := t.FindById(id)
+ if todo == nil {
+ continue
+ }
+ todo.Uncomplete()
+ t.Delete(id)
+ t.Data = append(t.Data, todo)
+ }
}
-func (t *TodoList) Archive(id int) {
- todo := t.FindById(id)
- todo.Archive()
- t.Delete(id)
- t.Data = append(t.Data, todo)
+func (t *TodoList) Archive(ids ...int) {
+ for _, id := range ids {
+ todo := t.FindById(id)
+ if todo == nil {
+ continue
+ }
+ todo.Archive()
+ t.Delete(id)
+ t.Data = append(t.Data, todo)
+ }
}
-func (t *TodoList) Unarchive(id int) {
- todo := t.FindById(id)
- todo.Unarchive()
- t.Delete(id)
- t.Data = append(t.Data, todo)
+func (t *TodoList) Unarchive(ids ...int) {
+ for _, id := range ids {
+ todo := t.FindById(id)
+ if todo == nil {
+ continue
+ }
+ todo.Unarchive()
+ t.Delete(id)
+ t.Data = append(t.Data, todo)
+ }
}
-func (t *TodoList) Prioritize(id int) {
- todo := t.FindById(id)
- todo.Prioritize()
- t.Delete(id)
- t.Data = append(t.Data, todo)
+func (t *TodoList) Prioritize(ids ...int) {
+ for _, id := range ids {
+ todo := t.FindById(id)
+ if todo == nil {
+ continue
+ }
+ todo.Prioritize()
+ t.Delete(id)
+ t.Data = append(t.Data, todo)
+ }
}
-func (t *TodoList) Unprioritize(id int) {
- todo := t.FindById(id)
- todo.Unprioritize()
- t.Delete(id)
- t.Data = append(t.Data, todo)
+func (t *TodoList) Unprioritize(ids ...int) {
+ for _, id := range ids {
+ todo := t.FindById(id)
+ if todo == nil {
+ continue
+ }
+ todo.Unprioritize()
+ t.Delete(id)
+ t.Data = append(t.Data, todo)
+ }
}
func (t *TodoList) IndexOf(todoToFind *Todo) int {
diff --git a/todolist/util.go b/todolist/util.go
index 34f9dd1..ff3dbba 100644
--- a/todolist/util.go
+++ b/todolist/util.go
@@ -52,3 +52,10 @@ func getNearestMonday(t time.Time) time.Time {
}
}
}
+
+func pluralize(count int, singular, plural string) string {
+ if count > 1 {
+ return plural
+ }
+ return singular
+}
diff --git a/todolist/util_test.go b/todolist/util_test.go
new file mode 100644
index 0000000..40ecb54
--- /dev/null
+++ b/todolist/util_test.go
@@ -0,0 +1,13 @@
+package todolist
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestPluralize(t *testing.T) {
+ assert := assert.New(t)
+ assert.Equal("todo", pluralize(1, "todo", "todos"))
+ assert.Equal("todos", pluralize(2, "todo", "todos"))
+}