From 389c1c3d25d0a84516ed576f64febf01b6225826 Mon Sep 17 00:00:00 2001 From: Paolo Donadeo Date: Tue, 25 Nov 2025 17:15:28 +0100 Subject: [PATCH] feat(parser): add ToRemind method to Task for Remind-compatible string output Implements Task.ToRemind(), which generates a Remind-formatted string including due date, metadata, projects, contexts, completion status, and priority. --- internal/parser/parser.go | 69 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/internal/parser/parser.go b/internal/parser/parser.go index 4b15373..b6eba21 100644 --- a/internal/parser/parser.go +++ b/internal/parser/parser.go @@ -25,6 +25,75 @@ type Task struct { Metadata map[string]string `json:"metadata"` } +func (t Task) ToRemind() string { + var sb strings.Builder + sb.WriteString("REM TODO ") + if t.DueDate == nil { + return "" + } + sb.WriteString(t.DueDate.Format("2006-01-02")) + + sb.WriteString(" ++5 INFO \"Calendar: TODO.TX\" ") + + if len(t.Metadata) > 0 { + for k, v := range t.Metadata { + if k == "due" { + continue + } + // k must have the first letter uppercase for Remind + k = strings.ToUpper(k[:1]) + k[1:] + sb.WriteString(fmt.Sprintf("INFO \"%s: %s\" ", k, v)) + } + } + + if len(t.Projects) > 0 { + for _, p := range t.Projects { + sb.WriteString(fmt.Sprintf("INFO \"List: %s\" ", p)) + } + } + + if len(t.Contexts) > 0 { + for _, c := range t.Contexts { + sb.WriteString(fmt.Sprintf("INFO \"Tag: %s\" ", c)) + } + } + + if t.Completed { + sb.WriteString(fmt.Sprintf("COMPLETE-THROUGH %s ", t.DueDate.Format("2006-01-02"))) + } + + if t.Priority != nil { + sb.WriteString(fmt.Sprintf("PRIORITY %d ", t.PriorityAsRemind())) + } + + sb.WriteString("MSG") + + if len(t.Projects) > 0 { + sb.WriteString(" %:") + } + + sb.WriteString(fmt.Sprintf(" %s", t.Description)) + + if t.Completed { + sb.WriteString("%:") + } else { + sb.WriteString(" (%b)") + } + + if len(t.Metadata) > 0 { + for k := range t.Metadata { + if k == "due" { + continue + } + // uppercase first letter for Remind + k = strings.ToUpper(k[:1]) + k[1:] + sb.WriteString(fmt.Sprintf("%%_%s: %%<%s>", k, k)) + } + } + + return sb.String() +} + // PriorityAsRemind returns an integer representing the priority for sorting. // A = 9999 (highest), Z = 0 (lowest), absent = 5000. func (t Task) PriorityAsRemind() int {