added Complete() and Reopen() to Task.
This commit is contained in:
parent
caa944bb71
commit
48dacccdf1
48
example_test.go
Normal file
48
example_test.go
Normal file
@ -0,0 +1,48 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package todotxt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
func ExampleLoadFromFilename() {
|
||||
if tasklist, err := LoadFromFilename("todo.txt"); err != nil {
|
||||
log.Fatal(err)
|
||||
} else {
|
||||
fmt.Print(tasklist) // String representation of TaskList works as expected.
|
||||
}
|
||||
|
||||
// Output:
|
||||
// (A) Call Mom @Phone +Family
|
||||
// (A) Schedule annual checkup +Health
|
||||
// (B) Outline chapter 5 @Computer +Novel
|
||||
// (C) Add cover sheets @Office +TPSReports
|
||||
// Plan backyard herb garden @Home
|
||||
// Pick up milk @GroceryStore
|
||||
// Research self-publishing services @Computer +Novel
|
||||
// x Download Todo.txt mobile app @Phone
|
||||
}
|
||||
|
||||
func ExampleTaskList_LoadFromFilename() {
|
||||
var tasklist TaskList
|
||||
|
||||
// This will overwrite whatever was in the tasklist before.
|
||||
// Irrelevant here since the list is still empty.
|
||||
if err := tasklist.LoadFromFilename("todo.txt"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(tasklist[0].Todo) // Text part of first task (Call Mom)
|
||||
fmt.Println(tasklist[2].Contexts) // Slice of contexts from third task ([Computer])
|
||||
fmt.Println(tasklist[3].Priority) // Priority of fourth task (C)
|
||||
fmt.Println(tasklist[7].Completed) // Completed flag of eigth task (true)
|
||||
// Output:
|
||||
// Call Mom
|
||||
// [Computer]
|
||||
// C
|
||||
// true
|
||||
}
|
24
sort.go
24
sort.go
@ -35,7 +35,7 @@ func (tasklist *TaskList) Sort(sortFlag int) error {
|
||||
case SORT_DUE_DATE_ASC, SORT_DUE_DATE_DESC:
|
||||
tasklist.sortByDueDate(sortFlag)
|
||||
default:
|
||||
return errors.New("Unrecognized sort option")
|
||||
return errors.New("unrecognized sort option")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -68,19 +68,17 @@ func (tasklist *TaskList) sortBy(by func(t1, t2 *Task) bool) *TaskList {
|
||||
|
||||
func (tasklist *TaskList) sortByPriority(order int) *TaskList {
|
||||
tasklist.sortBy(func(t1, t2 *Task) bool {
|
||||
if order == SORT_PRIORITY_DESC { // DESC
|
||||
if t1.HasPriority() && t2.HasPriority() {
|
||||
return t1.Priority > t2.Priority
|
||||
} else {
|
||||
return !t1.HasPriority()
|
||||
}
|
||||
} else { // ASC
|
||||
if order == SORT_PRIORITY_ASC { // ASC
|
||||
if t1.HasPriority() && t2.HasPriority() {
|
||||
return t1.Priority < t2.Priority
|
||||
} else {
|
||||
}
|
||||
return t1.HasPriority()
|
||||
}
|
||||
// DESC
|
||||
if t1.HasPriority() && t2.HasPriority() {
|
||||
return t1.Priority > t2.Priority
|
||||
}
|
||||
return !t1.HasPriority()
|
||||
})
|
||||
return tasklist
|
||||
}
|
||||
@ -89,17 +87,15 @@ func sortByDate(asc bool, hasDate1, hasDate2 bool, date1, date2 time.Time) bool
|
||||
if asc { // ASC
|
||||
if hasDate1 && hasDate2 {
|
||||
return date1.Before(date2)
|
||||
} else {
|
||||
}
|
||||
return hasDate2
|
||||
}
|
||||
} else { // DESC
|
||||
// DESC
|
||||
if hasDate1 && hasDate2 {
|
||||
return date1.After(date2)
|
||||
} else {
|
||||
}
|
||||
return !hasDate2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (tasklist *TaskList) sortByCreatedDate(order int) *TaskList {
|
||||
tasklist.sortBy(func(t1, t2 *Task) bool {
|
||||
|
42
sort_test.go
42
sort_test.go
@ -14,7 +14,9 @@ func TestTaskSortByPriority(t *testing.T) {
|
||||
|
||||
testTasklist = testTasklist[taskId : taskId+6]
|
||||
|
||||
testTasklist.Sort(SORT_PRIORITY_ASC)
|
||||
if err := testTasklist.Sort(SORT_PRIORITY_ASC); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testExpected = "(A) 2012-01-30 Call Mom @Call @Phone +Family"
|
||||
testGot = testTasklist[0].Task()
|
||||
@ -52,7 +54,9 @@ func TestTaskSortByPriority(t *testing.T) {
|
||||
t.Errorf("Expected Task[6] after Sort() to be [%s], but got [%s]", testExpected, testGot)
|
||||
}
|
||||
|
||||
testTasklist.Sort(SORT_PRIORITY_DESC)
|
||||
if err := testTasklist.Sort(SORT_PRIORITY_DESC); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testExpected = "x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05"
|
||||
testGot = testTasklist[0].Task()
|
||||
@ -97,7 +101,9 @@ func TestTaskSortByCreatedDate(t *testing.T) {
|
||||
|
||||
testTasklist = testTasklist[taskId : taskId+5]
|
||||
|
||||
testTasklist.Sort(SORT_CREATED_DATE_ASC)
|
||||
if err := testTasklist.Sort(SORT_CREATED_DATE_ASC); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testExpected = "x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05"
|
||||
testGot = testTasklist[0].Task()
|
||||
@ -129,7 +135,9 @@ func TestTaskSortByCreatedDate(t *testing.T) {
|
||||
t.Errorf("Expected Task[5] after Sort() to be [%s], but got [%s]", testExpected, testGot)
|
||||
}
|
||||
|
||||
testTasklist.Sort(SORT_CREATED_DATE_DESC)
|
||||
if err := testTasklist.Sort(SORT_CREATED_DATE_DESC); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testExpected = "x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12"
|
||||
testGot = testTasklist[0].Task()
|
||||
@ -168,7 +176,9 @@ func TestTaskSortByCompletedDate(t *testing.T) {
|
||||
|
||||
testTasklist = testTasklist[taskId : taskId+6]
|
||||
|
||||
testTasklist.Sort(SORT_COMPLETED_DATE_ASC)
|
||||
if err := testTasklist.Sort(SORT_COMPLETED_DATE_ASC); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testExpected = "x Download Todo.txt mobile app @Phone"
|
||||
testGot = testTasklist[0].Task()
|
||||
@ -206,7 +216,9 @@ func TestTaskSortByCompletedDate(t *testing.T) {
|
||||
t.Errorf("Expected Task[6] after Sort() to be [%s], but got [%s]", testExpected, testGot)
|
||||
}
|
||||
|
||||
testTasklist.Sort(SORT_COMPLETED_DATE_DESC)
|
||||
if err := testTasklist.Sort(SORT_COMPLETED_DATE_DESC); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testExpected = "x 2014-01-04 2014-01-01 Create some more golang library test cases @Go +go-todotxt"
|
||||
testGot = testTasklist[0].Task()
|
||||
@ -251,7 +263,9 @@ func TestTaskSortByDueDate(t *testing.T) {
|
||||
|
||||
testTasklist = testTasklist[taskId : taskId+4]
|
||||
|
||||
testTasklist.Sort(SORT_DUE_DATE_ASC)
|
||||
if err := testTasklist.Sort(SORT_DUE_DATE_ASC); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testExpected = "x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt"
|
||||
testGot = testTasklist[0].Task()
|
||||
@ -277,7 +291,9 @@ func TestTaskSortByDueDate(t *testing.T) {
|
||||
t.Errorf("Expected Task[4] after Sort() to be [%s], but got [%s]", testExpected, testGot)
|
||||
}
|
||||
|
||||
testTasklist.Sort(SORT_DUE_DATE_DESC)
|
||||
if err := testTasklist.Sort(SORT_DUE_DATE_DESC); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testExpected = "(B) 2013-12-01 Outline chapter 5 @Computer +Novel Level:5 private:false due:2014-02-17"
|
||||
testGot = testTasklist[0].Task()
|
||||
@ -303,3 +319,13 @@ func TestTaskSortByDueDate(t *testing.T) {
|
||||
t.Errorf("Expected Task[4] after Sort() to be [%s], but got [%s]", testExpected, testGot)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskSortError(t *testing.T) {
|
||||
testTasklist.LoadFromFilename(testInputSort)
|
||||
|
||||
if err := testTasklist.Sort(123); err == nil {
|
||||
t.Errorf("Expected Sort() to fail because of unrecognized sort option, but it didn't!")
|
||||
} else if err.Error() != "unrecognized sort option" {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
28
task.go
28
task.go
@ -67,7 +67,7 @@ func (task Task) String() string {
|
||||
if len(task.AdditionalTags) > 0 {
|
||||
// Sort map alphabetically by keys
|
||||
keys := make([]string, 0, len(task.AdditionalTags))
|
||||
for key, _ := range task.AdditionalTags {
|
||||
for key := range task.AdditionalTags {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
@ -106,7 +106,25 @@ func (task *Task) HasDueDate() bool {
|
||||
|
||||
// HasCompletedDate returns true if the task has a completed date.
|
||||
func (task *Task) HasCompletedDate() bool {
|
||||
return !task.CompletedDate.IsZero()
|
||||
return !task.CompletedDate.IsZero() && task.Completed
|
||||
}
|
||||
|
||||
// Complete sets Task.Completed to 'true' if the task was not already completed.
|
||||
// Also sets Task.CompletedDate to time.Now()
|
||||
func (task *Task) Complete() {
|
||||
if !task.Completed {
|
||||
task.Completed = true
|
||||
task.CompletedDate = time.Now()
|
||||
}
|
||||
}
|
||||
|
||||
// Reopen sets Task.Completed to 'false' if the task was completed.
|
||||
// Also resets Task.CompletedDate.
|
||||
func (task *Task) Reopen() {
|
||||
if task.Completed {
|
||||
task.Completed = false
|
||||
task.CompletedDate = time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC) // time.IsZero() value
|
||||
}
|
||||
}
|
||||
|
||||
// IsOverdue returns true if due date is in the past.
|
||||
@ -116,9 +134,8 @@ func (task *Task) HasCompletedDate() bool {
|
||||
func (task *Task) IsOverdue() bool {
|
||||
if task.HasDueDate() {
|
||||
return task.DueDate.Before(time.Now())
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Due returns the duration passed since due date, or until due date from now.
|
||||
@ -129,7 +146,6 @@ func (task *Task) IsOverdue() bool {
|
||||
func (task *Task) Due() time.Duration {
|
||||
if task.IsOverdue() {
|
||||
return time.Now().Sub(task.DueDate)
|
||||
} else {
|
||||
}
|
||||
return task.DueDate.Sub(time.Now())
|
||||
}
|
||||
}
|
||||
|
145
task_test.go
145
task_test.go
@ -263,21 +263,21 @@ func TestTaskCompleted(t *testing.T) {
|
||||
testExpected = true
|
||||
testGot = testTasklist[taskId-1].Completed
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] not to be completed, but got '%v'", taskId, testGot)
|
||||
t.Errorf("Expected Task[%d] to be completed, but got '%v'", taskId, testGot)
|
||||
}
|
||||
taskId++
|
||||
|
||||
testExpected = true
|
||||
testGot = testTasklist[taskId-1].Completed
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] not to be completed, but got '%v'", taskId, testGot)
|
||||
t.Errorf("Expected Task[%d] to be completed, but got '%v'", taskId, testGot)
|
||||
}
|
||||
taskId++
|
||||
|
||||
testExpected = true
|
||||
testGot = testTasklist[taskId-1].Completed
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] not to be completed, but got '%v'", taskId, testGot)
|
||||
t.Errorf("Expected Task[%d] to be completed, but got '%v'", taskId, testGot)
|
||||
}
|
||||
taskId++
|
||||
|
||||
@ -379,6 +379,145 @@ func TestTaskIsOverdue(t *testing.T) {
|
||||
t.Errorf("Expected Task[%d] to be due since 72 hours, but got '%v'", taskId, testGot)
|
||||
}
|
||||
taskId++
|
||||
|
||||
testGot = testTasklist[taskId-1].IsOverdue()
|
||||
if testGot.(bool) {
|
||||
t.Errorf("Expected Task[%d] not to be overdue, but got '%v'", taskId, testGot)
|
||||
}
|
||||
taskId++
|
||||
}
|
||||
|
||||
func TestTaskComplete(t *testing.T) {
|
||||
testTasklist.LoadFromFilename(testInputTask)
|
||||
taskId := 44
|
||||
|
||||
// first 4 tasks should all match the same tests
|
||||
for i := 0; i < 4; i++ {
|
||||
testExpected = false
|
||||
testGot = testTasklist[taskId-1].Completed
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] not to be completed, but got '%v'", taskId, testGot)
|
||||
}
|
||||
testGot = testTasklist[taskId-1].HasCompletedDate()
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] not to have a completed date, but got '%v'", taskId, testGot)
|
||||
}
|
||||
testTasklist[taskId-1].Complete()
|
||||
testExpected = true
|
||||
testGot = testTasklist[taskId-1].Completed
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to be completed, but got '%v'", taskId, testGot)
|
||||
}
|
||||
testGot = testTasklist[taskId-1].HasCompletedDate()
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to have a completed date, but got '%v'", taskId, testGot)
|
||||
}
|
||||
testExpected = time.Now().Format(DateLayout)
|
||||
testGot = testTasklist[taskId-1].CompletedDate.Format(DateLayout)
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to have a completed date of '%v', but got '%v'", taskId, testExpected, testGot)
|
||||
}
|
||||
taskId++
|
||||
}
|
||||
|
||||
testExpected = true
|
||||
testGot = testTasklist[taskId-1].Completed
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to be completed, but got '%v'", taskId, testGot)
|
||||
}
|
||||
testGot = testTasklist[taskId-1].HasCompletedDate()
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to have a completed date, but got '%v'", taskId, testGot)
|
||||
}
|
||||
testTasklist[taskId-1].Complete()
|
||||
testGot = testTasklist[taskId-1].Completed // should be unchanged
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to be completed, but got '%v'", taskId, testGot)
|
||||
}
|
||||
testGot = testTasklist[taskId-1].HasCompletedDate() // should be unchanged
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to have a completed date, but got '%v'", taskId, testGot)
|
||||
}
|
||||
testExpected = "2012-01-01" // should be unchanged
|
||||
testGot = testTasklist[taskId-1].CompletedDate.Format(DateLayout)
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to have a completed date of '%v', but got '%v'", taskId, testExpected, testGot)
|
||||
}
|
||||
taskId++
|
||||
}
|
||||
|
||||
func TestTaskReopen(t *testing.T) {
|
||||
testTasklist.LoadFromFilename(testInputTask)
|
||||
taskId := 49
|
||||
|
||||
// the first 2 tasks should match the same tests
|
||||
for i := 0; i < 2; i++ {
|
||||
testExpected = true
|
||||
testGot = testTasklist[taskId-1].Completed
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to be completed, but got '%v'", taskId, testGot)
|
||||
}
|
||||
testExpected = false
|
||||
testGot = testTasklist[taskId-1].HasCompletedDate()
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to have a completed date, but got '%v'", taskId, testGot)
|
||||
}
|
||||
testTasklist[taskId-1].Reopen()
|
||||
testExpected = false
|
||||
testGot = testTasklist[taskId-1].Completed
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to not be completed, but got '%v'", taskId, testGot)
|
||||
}
|
||||
testGot = testTasklist[taskId-1].HasCompletedDate()
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to not have a completed date, but got '%v'", taskId, testGot)
|
||||
}
|
||||
taskId++
|
||||
}
|
||||
|
||||
// the next 3 tasks should all match the same tests
|
||||
for i := 0; i < 3; i++ {
|
||||
testExpected = true
|
||||
testGot = testTasklist[taskId-1].Completed
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to be completed, but got '%v'", taskId, testGot)
|
||||
}
|
||||
testGot = testTasklist[taskId-1].HasCompletedDate()
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to have a completed date, but got '%v'", taskId, testGot)
|
||||
}
|
||||
testTasklist[taskId-1].Reopen()
|
||||
testExpected = false
|
||||
testGot = testTasklist[taskId-1].Completed
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to not be completed, but got '%v'", taskId, testGot)
|
||||
}
|
||||
testGot = testTasklist[taskId-1].HasCompletedDate()
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to not have a completed date, but got '%v'", taskId, testGot)
|
||||
}
|
||||
taskId++
|
||||
}
|
||||
|
||||
testExpected = false
|
||||
testGot = testTasklist[taskId-1].Completed
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to be completed, but got '%v'", taskId, testGot)
|
||||
}
|
||||
testGot = testTasklist[taskId-1].HasCompletedDate()
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to have a completed date, but got '%v'", taskId, testGot)
|
||||
}
|
||||
testTasklist[taskId-1].Reopen()
|
||||
testGot = testTasklist[taskId-1].Completed // should be unchanged
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to be completed, but got '%v'", taskId, testGot)
|
||||
}
|
||||
testGot = testTasklist[taskId-1].HasCompletedDate() // should be unchanged
|
||||
if testGot != testExpected {
|
||||
t.Errorf("Expected Task[%d] to have a completed date, but got '%v'", taskId, testGot)
|
||||
}
|
||||
taskId++
|
||||
}
|
||||
|
||||
func compareSlices(list1 []string, list2 []string) bool {
|
||||
|
17
testdata/task_todo.txt
vendored
17
testdata/task_todo.txt
vendored
@ -59,3 +59,20 @@ x 2014-01-03 2014-01-01 Create some more golang library test cases @Go +go-todot
|
||||
x 2014-01-04 (B) 2013-12-30 Create golang library @Go +go-todotxt due:2014-01-02
|
||||
(B) 2013-12-01 private:false Outline chapter 5 +Novel @Computer due:2017-07-17 Level:5
|
||||
Research self-publishing services +Novel +Novel +Novel due:2014-01-01
|
||||
x 2014-01-03 2014-01-01 Create some more golang library test cases @Go +go-todotxt
|
||||
|
||||
# Complete test cases
|
||||
Create golang library @Go +go-todotxt due:2014-01-05
|
||||
(A) @Phone Call Mom @Call +Family
|
||||
2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05
|
||||
(B) 2013-12-30 Create golang library test cases @Go +go-todotxt
|
||||
x 2012-01-01 More Go!
|
||||
|
||||
# Reopen test cases
|
||||
x Download Todo.txt mobile app @Phone
|
||||
x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12
|
||||
x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05
|
||||
x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt
|
||||
x 2014-01-03 2014-01-01 Create some more golang library test cases @Go +go-todotxt
|
||||
(B) 2013-12-30 Create golang library test cases @Go +go-todotxt
|
||||
|
||||
|
6
testdata/tasklist_completedDate_error.txt
vendored
Normal file
6
testdata/tasklist_completedDate_error.txt
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12
|
||||
x Download Todo.txt mobile app @Phone
|
||||
x 2014-01-03 Create golang library @Go +go-todotxt due:2014-01-05
|
||||
x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12
|
||||
x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt
|
||||
x 2014-25-04 2014-01-01 Create some more golang library test cases @Go +go-todotxt
|
5
testdata/tasklist_createdDate_error.txt
vendored
Normal file
5
testdata/tasklist_createdDate_error.txt
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
2013-02-22 Pick up milk @GroceryStore
|
||||
x Download Todo.txt mobile app @Phone
|
||||
(B) 2013-13-01 private:false Outline chapter 5 +Novel @Computer Level:5 due:2014-02-17
|
||||
x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt
|
||||
x 2014-01-03 2014-01-01 Create some more golang library test cases @Go +go-todotxt
|
5
testdata/tasklist_dueDate_error.txt
vendored
Normal file
5
testdata/tasklist_dueDate_error.txt
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
B) 2013-12-01 private:false Outline chapter 5 +Novel @Computer Level:5 due:2014-02-17
|
||||
x 2014-01-02 (B) 2013-12-30 Create golang library test cases @Go +go-todotxt
|
||||
x 2014-01-03 2014-01-01 Create some more golang library test cases @Go +go-todotxt
|
||||
(B) 2013-12-01 private:false Outline chapter 5 +Novel @Computer Level:5 due:2014-02-32
|
||||
x (C) 2014-01-01 Create golang library documentation @Go +go-todotxt due:2014-01-12
|
2
testdata/tasklist_scanner_error.txt
vendored
Normal file
2
testdata/tasklist_scanner_error.txt
vendored
Normal file
File diff suppressed because one or more lines are too long
37
todotxt.go
37
todotxt.go
@ -23,12 +23,13 @@ import (
|
||||
// It is usually loaded from a whole todo.txt file.
|
||||
type TaskList []Task
|
||||
|
||||
// IgnoreComments can be set to 'false', in order to revert to more standard todo.txt behaviour.
|
||||
// IgnoreComments can be set to 'false', in order to revert to a more standard todo.txt behaviour.
|
||||
// The todo.txt format does not define comments.
|
||||
var (
|
||||
// Used for formatting time.Time into todo.txt date format and vice-versa.
|
||||
// DateLayout is used for formatting time.Time into todo.txt date format and vice-versa.
|
||||
DateLayout = "2006-01-02"
|
||||
// Ignores comments (Lines/Text starting with "#").
|
||||
// IgnoreComments is used to switch ignoring of comments (lines starting with "#").
|
||||
// If this is set to 'false', then lines starting with "#" will be parsed as tasks.
|
||||
IgnoreComments = true
|
||||
|
||||
// unexported vars
|
||||
@ -74,10 +75,10 @@ func (tasklist *TaskList) LoadFromFile(file *os.File) error {
|
||||
task.Completed = true
|
||||
// Check for completed date
|
||||
if completedDateRx.MatchString(task.Original) {
|
||||
if date, err := time.Parse(DateLayout, completedDateRx.FindStringSubmatch(task.Original)[1]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if date, err := time.Parse(DateLayout, completedDateRx.FindStringSubmatch(task.Original)[1]); err == nil {
|
||||
task.CompletedDate = date
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,11 +95,11 @@ func (tasklist *TaskList) LoadFromFile(file *os.File) error {
|
||||
|
||||
// Check for created date
|
||||
if createdDateRx.MatchString(task.Original) {
|
||||
if date, err := time.Parse(DateLayout, createdDateRx.FindStringSubmatch(task.Original)[2]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if date, err := time.Parse(DateLayout, createdDateRx.FindStringSubmatch(task.Original)[2]); err == nil {
|
||||
task.CreatedDate = date
|
||||
task.Todo = createdDateRx.ReplaceAllString(task.Todo, "") // Remove from Todo text
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,10 +138,10 @@ func (tasklist *TaskList) LoadFromFile(file *os.File) error {
|
||||
for _, match := range matches {
|
||||
key, value := match[2], match[3]
|
||||
if key == "due" { // due date is a known addon tag, it has its own struct field
|
||||
if date, err := time.Parse(DateLayout, value); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if date, err := time.Parse(DateLayout, value); err == nil {
|
||||
task.DueDate = date
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
} else if key != "" && value != "" {
|
||||
tags[key] = value
|
||||
@ -195,8 +196,10 @@ func (tasklist *TaskList) WriteToFilename(filename string) error {
|
||||
// Using *os.File instead of a filename allows to also use os.Stdin.
|
||||
func LoadFromFile(file *os.File) (TaskList, error) {
|
||||
tasklist := TaskList{}
|
||||
err := tasklist.LoadFromFile(file)
|
||||
return tasklist, err
|
||||
if err := tasklist.LoadFromFile(file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tasklist, nil
|
||||
}
|
||||
|
||||
// WriteToFile writes a TaskList to *os.File.
|
||||
@ -209,8 +212,10 @@ func WriteToFile(tasklist *TaskList, file *os.File) error {
|
||||
// LoadFromFilename loads and returns a TaskList from a file (most likely called "todo.txt").
|
||||
func LoadFromFilename(filename string) (TaskList, error) {
|
||||
tasklist := TaskList{}
|
||||
err := tasklist.LoadFromFilename(filename)
|
||||
return tasklist, err
|
||||
if err := tasklist.LoadFromFilename(filename); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tasklist, nil
|
||||
}
|
||||
|
||||
// WriteToFilename writes a TaskList to the specified file (most likely called "todo.txt").
|
||||
|
@ -12,6 +12,10 @@ import (
|
||||
|
||||
var (
|
||||
testInputTasklist = "testdata/tasklist_todo.txt"
|
||||
testInputTasklistCreatedDateError = "testdata/tasklist_createdDate_error.txt"
|
||||
testInputTasklistDueDateError = "testdata/tasklist_dueDate_error.txt"
|
||||
testInputTasklistCompletedDateError = "testdata/tasklist_completedDate_error.txt"
|
||||
testInputTasklistScannerError = "testdata/tasklist_scanner_error.txt"
|
||||
testOutput = "testdata/ouput_todo.txt"
|
||||
testExpectedOutput = "testdata/expected_todo.txt"
|
||||
testTasklist TaskList
|
||||
@ -39,6 +43,10 @@ func TestLoadFromFile(t *testing.T) {
|
||||
t.Errorf("Expected TaskList to be [%s], but got [%s]", testExpected, testGot)
|
||||
}
|
||||
}
|
||||
|
||||
if testTasklist, err := LoadFromFile(nil); testTasklist != nil || err == nil {
|
||||
t.Errorf("Expected LoadFromFile to fail, but got TaskList back: [%s]", testTasklist)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadFromFilename(t *testing.T) {
|
||||
@ -55,6 +63,10 @@ func TestLoadFromFilename(t *testing.T) {
|
||||
t.Errorf("Expected TaskList to be [%s], but got [%s]", testExpected, testGot)
|
||||
}
|
||||
}
|
||||
|
||||
if testTasklist, err := LoadFromFilename("some_file_that_does_not_exists.txt"); testTasklist != nil || err == nil {
|
||||
t.Errorf("Expected LoadFromFilename to fail, but got TaskList back: [%s]", testTasklist)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteFile(t *testing.T) {
|
||||
@ -192,7 +204,9 @@ func TestTaskListWriteFilename(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTaskListCount(t *testing.T) {
|
||||
testTasklist.LoadFromFilename(testInputTasklist)
|
||||
if err := testTasklist.LoadFromFilename(testInputTasklist); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testExpected := 63
|
||||
testGot := len(testTasklist)
|
||||
@ -200,3 +214,30 @@ func TestTaskListCount(t *testing.T) {
|
||||
t.Errorf("Expected TaskList to contain %d tasks, but got %d", testExpected, testGot)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskListReadErrors(t *testing.T) {
|
||||
if testTasklist, err := LoadFromFilename(testInputTasklistCreatedDateError); testTasklist != nil || err == nil {
|
||||
t.Errorf("Expected LoadFromFilename to fail because of invalid created date, but got TaskList back: [%s]", testTasklist)
|
||||
} else if err.Error() != `parsing time "2013-13-01": month out of range` {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if testTasklist, err := LoadFromFilename(testInputTasklistDueDateError); testTasklist != nil || err == nil {
|
||||
t.Errorf("Expected LoadFromFilename to fail because of invalid due date, but got TaskList back: [%s]", testTasklist)
|
||||
} else if err.Error() != `parsing time "2014-02-32": day out of range` {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if testTasklist, err := LoadFromFilename(testInputTasklistCompletedDateError); testTasklist != nil || err == nil {
|
||||
t.Errorf("Expected LoadFromFilename to fail because of invalid completed date, but got TaskList back: [%s]", testTasklist)
|
||||
} else if err.Error() != `parsing time "2014-25-04": month out of range` {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// really silly test
|
||||
if testTasklist, err := LoadFromFilename(testInputTasklistScannerError); testTasklist != nil || err == nil {
|
||||
t.Errorf("Expected LoadFromFilename to fail because of invalid file, but got TaskList back: [%s]", testTasklist)
|
||||
} else if err.Error() != `bufio.Scanner: token too long` {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user