97 lines
2.3 KiB
Go
97 lines
2.3 KiB
Go
|
/* 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 (
|
||
|
"bufio"
|
||
|
"os"
|
||
|
"regexp"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type Task struct {
|
||
|
Task string // Raw text
|
||
|
Todo string // Only actual todo part of text
|
||
|
Priority string
|
||
|
Projects []string
|
||
|
Contexts []string
|
||
|
CreatedDate time.Time
|
||
|
DueDate time.Time
|
||
|
CompletedDate time.Time
|
||
|
Completed bool
|
||
|
}
|
||
|
|
||
|
type TaskList []Task
|
||
|
|
||
|
var (
|
||
|
priorityRx = regexp.MustCompile(`^\(([A-Z])\)\s+`) // Match priority value: '(A) ...'
|
||
|
createdDateRx = regexp.MustCompile(`^(\([A-Z]\)|)\s*([\d]{4}-[\d]{2}-[\d]{2})\s+`) // Match date value: '(A) 2012-12-12 ...' or '2012-12-12 ...'
|
||
|
)
|
||
|
|
||
|
// Return raw task text for String()
|
||
|
func (task *Task) String() string {
|
||
|
return task.Task
|
||
|
}
|
||
|
|
||
|
func (task *Task) HasPriority() bool {
|
||
|
return task.Priority != ""
|
||
|
}
|
||
|
|
||
|
func (task *Task) HasCreatedDate() bool {
|
||
|
return !task.CreatedDate.IsZero()
|
||
|
}
|
||
|
|
||
|
func (task *Task) HasDueDate() bool {
|
||
|
return !task.DueDate.IsZero()
|
||
|
}
|
||
|
|
||
|
func (task *Task) HasCompletedDate() bool {
|
||
|
return !task.CompletedDate.IsZero()
|
||
|
}
|
||
|
|
||
|
// Loading from *os.File allows to also use os.Stdin instead of just actual files
|
||
|
func (tasklist *TaskList) LoadFromFile(file *os.File) error {
|
||
|
*tasklist = []Task{} // Reset tasklist
|
||
|
|
||
|
scanner := bufio.NewScanner(file)
|
||
|
for scanner.Scan() {
|
||
|
task := Task{}
|
||
|
task.Task = scanner.Text()
|
||
|
|
||
|
// Check for priority
|
||
|
if priorityRx.MatchString(task.Task) {
|
||
|
task.Priority = priorityRx.FindStringSubmatch(task.Task)[1] // First match is priority value
|
||
|
}
|
||
|
|
||
|
// Check for created date
|
||
|
if createdDateRx.MatchString(task.Task) {
|
||
|
// Second match is created date value
|
||
|
if date, err := time.Parse("2006-01-02", createdDateRx.FindStringSubmatch(task.Task)[2]); err != nil {
|
||
|
return err
|
||
|
} else {
|
||
|
task.CreatedDate = date
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*tasklist = append(*tasklist, task)
|
||
|
}
|
||
|
if err := scanner.Err(); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Convenience method, since most of the time tasks will be loaded from an actual file, called "todo.txt" most likely ;)
|
||
|
func (tasklist *TaskList) LoadFromFilename(filename string) error {
|
||
|
file, err := os.Open(filename)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
defer file.Close()
|
||
|
|
||
|
return tasklist.LoadFromFile(file)
|
||
|
}
|