diff options
| author | Paul Bütow <1224732+snonux@users.noreply.github.com> | 2025-06-20 20:43:12 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-20 20:43:12 +0300 |
| commit | c0dd74fb9b434a17332be11ad867839832d10b63 (patch) | |
| tree | 781f26f009ba5205c0ddb3ac3c31be3ebd5a95ea /internal/task/task.go | |
| parent | 438272b134ba537f68884c25f2a015a5218503dd (diff) | |
| parent | 363caa6301d67c97b29e83e168ed9c83f571355c (diff) | |
Merge pull request #31 from snonux/codex/sort-tasks-by-due-date,-priority,-tag,-and-id
Implement task sorting by due date and priority
Diffstat (limited to 'internal/task/task.go')
| -rw-r--r-- | internal/task/task.go | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/internal/task/task.go b/internal/task/task.go index f860b16..55e1328 100644 --- a/internal/task/task.go +++ b/internal/task/task.go @@ -8,8 +8,10 @@ import ( "io" "os" "os/exec" + "sort" "strconv" "strings" + "time" ) // Task represents a taskwarrior task as returned by `task export`. @@ -232,3 +234,68 @@ func EditCmd(id int) *exec.Cmd { func Edit(id int) error { return EditCmd(id).Run() } + +// SortTasks orders tasks by due date, priority, tag names and id. +// Tasks without a due date are placed after tasks with a due date. +func SortTasks(tasks []Task) { + joinTags := func(tags []string) string { + if len(tags) == 0 { + return "" + } + cpy := append([]string(nil), tags...) + sort.Strings(cpy) + return strings.Join(cpy, ",") + } + + priVal := func(p string) int { + switch p { + case "H": + return 3 + case "M": + return 2 + case "L": + return 1 + default: + return 0 + } + } + + parseDue := func(s string) (time.Time, bool) { + if s == "" { + return time.Time{}, false + } + t, err := time.Parse("20060102T150405Z", s) + if err != nil { + return time.Time{}, false + } + return t, true + } + + sort.Slice(tasks, func(i, j int) bool { + ti, tj := tasks[i], tasks[j] + + di, iok := parseDue(ti.Due) + dj, jok := parseDue(tj.Due) + if iok && !jok { + return true + } + if !iok && jok { + return false + } + if iok && jok && !di.Equal(dj) { + return di.Before(dj) + } + + pi, pj := priVal(ti.Priority), priVal(tj.Priority) + if pi != pj { + return pi > pj + } + + tgI, tgJ := joinTags(ti.Tags), joinTags(tj.Tags) + if tgI != tgJ { + return tgI < tgJ + } + + return ti.ID < tj.ID + }) +} |
