From 8777bd39328415a0c8159e6fe013dc023c81176e Mon Sep 17 00:00:00 2001 From: Paolo Donadeo Date: Sat, 16 May 2026 22:24:06 +0200 Subject: [PATCH] refactor(remind): extract buffer primitives for remind rendering --- bin/remind.ml | 168 ++++++++++++++++++++++++-------------------------- 1 file changed, 81 insertions(+), 87 deletions(-) diff --git a/bin/remind.ml b/bin/remind.ml index f504310..afc51d3 100644 --- a/bin/remind.ml +++ b/bin/remind.ml @@ -42,98 +42,92 @@ let empty = exdate = []; } -let render_yearly month day summary = - let month_str = month_of_int month |> string_of_month in - spf "REM %s %d MSG %s\n" month_str day summary +(* ── buffer primitives ────────────────────────────────────────── *) -let render_weekly rem weekly = +let add_rem b = Buffer.add_string b "REM " +let add_info b uuid = Buffer.add_string b (spf "INFO \"UID: %s\" " uuid) +let add_date b date = Buffer.add_string b (Timedesc.Date.to_rfc3339 date) +let add_weekday b wd = Buffer.add_string b (spf "%s " (string_of_weekday wd)) + +let add_interval b w = + let n = Option.value ~default:1 w.interval in + Buffer.add_string b (spf "*%d " (n * 7)) + +let add_until b rem w = + match w.count_or_until with + | None -> () + | Some (`Until d) -> + let ts = timedesc_of_utc_or_timestamp_local d in + Buffer.add_string b (spf "UNTIL %s " (Timedesc.Date.to_rfc3339 (Timedesc.date ts))) + | Some (`Count count) -> + let wd = Timedesc.Date.weekday rem.date in + let wd_int = Timedesc.Utils.tm_int_of_weekday wd in + let sub = + match w.week_start with + | Some `Monday -> wd_int - 1 + | _ -> wd_int + in + let iv = Option.value ~default:1 w.interval in + let until = Timedesc.Date.add ~days:((count * 7 * iv) - sub) rem.date in + Buffer.add_string b (spf "UNTIL %s " (Timedesc.Date.to_rfc3339 until)) + +let add_at b = function + | Some t -> Buffer.add_string b (spf " AT %s" (string_of_time t)) + | None -> () + +let add_duration b = function + | Some d -> Buffer.add_string b (spf " DURATION %s" (string_of_span d)) + | None -> () + +let add_through b = function + | Some d -> Buffer.add_string b (spf " THROUGH %s" (Timedesc.Date.to_rfc3339 d)) + | None -> () + +let add_msg b summary = Buffer.add_string b (spf " MSG %s\n" summary) + +(* ── rendering ────────────────────────────────────────────────── *) + +let render_weekly rem w = let b = Buffer.create 256 in List.iter - begin fun weekday -> - Buffer.add_string b "REM "; - Buffer.add_string b (spf "INFO \"UID: %s\" " rem.original_uuid); - Buffer.add_string b (spf "%s " (string_of_weekday weekday)); - Buffer.add_string b (Timedesc.Date.to_rfc3339 rem.date); - Buffer.add_string b " "; - (match weekly.interval with - | Some interval -> Buffer.add_string b (spf "*%d " (interval * 7)) - | None -> Buffer.add_string b "*7 "); - - (match weekly.count_or_until with - | Some (`Count count) -> begin - (* We must compute the until date based on the count and the interval *) - let wd = Timedesc.Date.weekday rem.date in - let wd_int = Timedesc.Utils.tm_int_of_weekday wd in - let day_to_subtract = - match weekly.week_start with - | Some `Sunday -> wd_int - | Some `Monday -> wd_int - 1 - | None -> wd_int (* Default to Sunday if not specified *) - in - let interval = Option.value ~default:1 weekly.interval in - let until_date = Timedesc.Date.add ~days:((count * 7 * interval) - day_to_subtract) rem.date in - Buffer.add_string b "UNTIL "; - Buffer.add_string b (Timedesc.Date.to_rfc3339 until_date); - Buffer.add_string b " " - end - | Some (`Until until_date) -> begin - Buffer.add_string b "UNTIL "; - let ts = timedesc_of_utc_or_timestamp_local until_date in - Buffer.add_string b (Timedesc.Date.to_rfc3339 (Timedesc.date ts)); - Buffer.add_string b " " - end - | None -> ()); - - (match rem.time with - | Some time -> - Buffer.add_string b " AT "; - Buffer.add_string b (string_of_time time) - | None -> ()); - - (match rem.duration with - | Some duration -> - Buffer.add_string b " DURATION "; - Buffer.add_string b (string_of_span duration); - Buffer.add_string b "" - | None -> ()); - - Buffer.add_string b " MSG "; - Buffer.add_string b rem.summary; - Buffer.add_string b "\n" - end - weekly.byday; + (fun wd -> + add_rem b; + add_info b rem.original_uuid; + add_weekday b wd; + add_date b rem.date; + Buffer.add_char b ' '; + add_interval b w; + add_until b rem w; + add_at b rem.time; + add_duration b rem.duration; + add_msg b rem.summary) + w.byday; Buffer.contents b +let render_single rem = + let b = Buffer.create 256 in + add_rem b; + add_info b rem.original_uuid; + add_date b rem.date; + add_at b rem.time; + add_duration b rem.duration; + add_through b rem.end_date; + add_msg b rem.summary; + Buffer.contents b + +let render_yearly month day summary = + let b = Buffer.create 64 in + add_rem b; + Buffer.add_string b (spf "%s %d" (month_of_int month |> string_of_month) day); + add_msg b summary; + Buffer.contents b + +(* ── dispatcher ───────────────────────────────────────────────── *) + let string_of_rem rem = match rem.weekly with - | Some weekly -> render_weekly rem weekly - | None -> - begin match rem.yearly with + | Some w -> render_weekly rem w + | None -> ( + match rem.yearly with | Some (month, day) -> render_yearly month day rem.summary - | None -> begin - let b = Buffer.create 256 in - Buffer.add_string b "REM "; - Buffer.add_string b (spf "INFO \"UID: %s\" " rem.original_uuid); - Buffer.add_string b (Timedesc.Date.to_rfc3339 rem.date); - (match rem.time with - | Some time -> - Buffer.add_string b " AT "; - Buffer.add_string b (string_of_time time) - | None -> ()); - (match rem.duration with - | Some duration -> - Buffer.add_string b " DURATION "; - Buffer.add_string b (string_of_span duration); - Buffer.add_string b "" - | None -> ()); - (match rem.end_date with - | Some end_date -> - Buffer.add_string b " THROUGH "; - Buffer.add_string b (Timedesc.Date.to_rfc3339 end_date) - | None -> ()); - Buffer.add_string b " MSG "; - Buffer.add_string b rem.summary; - Buffer.add_string b "\n"; - Buffer.contents b - end - end + | None -> render_single rem)