diff options
| author | Paul Bütow <1224732+snonux@users.noreply.github.com> | 2025-06-20 09:43:23 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-20 09:43:23 +0300 |
| commit | 4c4e186b14b91163beb8316aff6eeda86f9dc171 (patch) | |
| tree | 512a6b9f8017f8cf0cc24158acc154034c121225 /internal/task | |
| parent | 13ec0a6ec615b4c7e7ddc461a7a6a623109826f9 (diff) | |
| parent | 13f7678a9fd092ac20eec10e4d2196f5bd1ae107 (diff) | |
Merge pull request #11 from snonux/codex/enhance-taskwarrior-ui-and-functionality
Add cell navigation, editor hotkey, stats and filter
Diffstat (limited to 'internal/task')
| -rw-r--r-- | internal/task/stats.go | 40 | ||||
| -rw-r--r-- | internal/task/stats_test.go | 28 | ||||
| -rw-r--r-- | internal/task/task.go | 8 |
3 files changed, 74 insertions, 2 deletions
diff --git a/internal/task/stats.go b/internal/task/stats.go new file mode 100644 index 0000000..c516249 --- /dev/null +++ b/internal/task/stats.go @@ -0,0 +1,40 @@ +package task + +import "time" + +// TotalTasks returns the number of tasks provided. +func TotalTasks(tasks []Task) int { + return len(tasks) +} + +// InProgressTasks returns the number of tasks that have been started and are not completed. +func InProgressTasks(tasks []Task) int { + count := 0 + for _, t := range tasks { + if t.Status == "completed" { + continue + } + if t.Start != "" { + count++ + } + } + return count +} + +// DueTasks returns the number of tasks with a due date that is not in the future. +func DueTasks(tasks []Task, now time.Time) int { + count := 0 + for _, t := range tasks { + if t.Status == "completed" || t.Due == "" { + continue + } + ts, err := time.Parse("20060102T150405Z", t.Due) + if err != nil { + continue + } + if !ts.After(now) { + count++ + } + } + return count +} diff --git a/internal/task/stats_test.go b/internal/task/stats_test.go new file mode 100644 index 0000000..fddbd69 --- /dev/null +++ b/internal/task/stats_test.go @@ -0,0 +1,28 @@ +package task + +import ( + "testing" + "time" +) + +func TestStats(t *testing.T) { + now := time.Now() + tasks := []Task{ + {Description: "t1"}, + {Description: "t2", Start: "20240101T000000Z"}, + {Description: "t3", Due: now.Add(-time.Hour).Format("20060102T150405Z")}, + {Description: "t4", Start: "20240101T000000Z", Due: now.Add(-time.Hour).Format("20060102T150405Z")}, + } + + if TotalTasks(tasks) != 4 { + t.Errorf("total tasks wrong: %d", TotalTasks(tasks)) + } + + if InProgressTasks(tasks) != 2 { + t.Errorf("in progress wrong: %d", InProgressTasks(tasks)) + } + + if DueTasks(tasks, now) != 2 { + t.Errorf("due tasks wrong: %d", DueTasks(tasks, now)) + } +} diff --git a/internal/task/task.go b/internal/task/task.go index 4c33fdb..f7a3f73 100644 --- a/internal/task/task.go +++ b/internal/task/task.go @@ -46,8 +46,12 @@ func Add(description string, tags []string) error { // Export retrieves all tasks using `task export rc.json.array=off` and parses // the JSON output into a slice of Task structs. -func Export() ([]Task, error) { - cmd := exec.Command("task", "export", "rc.json.array=off") +// Export retrieves tasks using `task <filter> export rc.json.array=off` and parses +// the JSON output into a slice of Task structs. Optional filter arguments are +// passed directly to the `task` command before `export`. +func Export(filters ...string) ([]Task, error) { + args := append(filters, "export", "rc.json.array=off") + cmd := exec.Command("task", args...) out, err := cmd.Output() if err != nil { return nil, err |
