diff --git a/KisaniCal/Views/TodayView.swift b/KisaniCal/Views/TodayView.swift index 897183d..ffbf462 100644 --- a/KisaniCal/Views/TodayView.swift +++ b/KisaniCal/Views/TodayView.swift @@ -764,7 +764,7 @@ struct NLTaskParser { // ── Day keywords ─────────────────────────────────────────────────── let dayTable: [(String, Int)] = [ ("\\btoday\\b", 0), - ("\\btomorrow\\b", 1), + ("\\btom+[ao]r+ow\\b", 1), ("\\bmon(day)?\\b", daysUntil(2)), ("\\btue(sday)?\\b", daysUntil(3)), ("\\bwed(nesday)?\\b", daysUntil(4)), @@ -773,11 +773,20 @@ struct NLTaskParser { ("\\bsat(urday)?\\b", daysUntil(7)), ("\\bsun(day)?\\b", daysUntil(1)), ] - for (pat, offset) in dayTable { - if let r = match(pat, in: lower) { - let d = cal.date(byAdding: .day, value: offset, to: Date()) ?? Date() - comps = cal.dateComponents([.year, .month, .day], from: d) - rawRanges.append(r); foundDay = true; break + // ── Relative offsets ("in N days", "next week") ─────────────────── + if let (r, offset) = parseRelativeOffset(in: lower) { + let d = cal.date(byAdding: .day, value: offset, to: Date()) ?? Date() + comps = cal.dateComponents([.year, .month, .day], from: d) + rawRanges.append(r); foundDay = true + } + + if !foundDay { + for (pat, offset) in dayTable { + if let r = match(pat, in: lower) { + let d = cal.date(byAdding: .day, value: offset, to: Date()) ?? Date() + comps = cal.dateComponents([.year, .month, .day], from: d) + rawRanges.append(r); foundDay = true; break + } } } @@ -814,6 +823,22 @@ struct NLTaskParser { .replacingOccurrences(of: " ", with: " ") } + private static func parseRelativeOffset(in text: String) -> (NSRange, Int)? { + let wordNums = ["a": 1, "an": 1, "one": 1, "two": 2, "three": 3, "four": 4, + "five": 5, "six": 6, "seven": 7, "eight": 8, "nine": 9, "ten": 10] + if let r = match("\\bnext\\s+week\\b", in: text) { return (r, 7) } + for (unit, mult) in [("days?", 1), ("weeks?", 7)] { + let pat = "\\bin\\s+(\\d+|a|an|one|two|three|four|five|six|seven|eight|nine|ten)\\s+\(unit)\\b" + guard let rx = try? NSRegularExpression(pattern: pat), + let m = rx.firstMatch(in: text, range: NSRange(text.startIndex..., in: text)), + m.numberOfRanges >= 2, + let nr = Range(m.range(at: 1), in: text) else { continue } + let ns = String(text[nr]) + return (m.range, (Int(ns) ?? wordNums[ns] ?? 1) * mult) + } + return nil + } + private static func daysUntil(_ target: Int) -> Int { let today = Calendar.current.component(.weekday, from: Date()) let d = target - today