feat(cli): add output control flags, sort order, and verbose mode

- Add `--verbose`/`-v` flag; gate all diagnostic stderr output behind it
- Add `--no-uuid`, `--no-source`, `--no-location`, `--no-description`,
  `--no-conference-url` flags to suppress individual INFO lines
- Add `--sort` option (`asc`, `desc`, `original`) replacing hardcoded
  descending sort
- Add `--source` option to override calendar name (single-file only)
- Introduce `Config` module with global `ref` flags set at startup from
  CLI args
- Add `Utils.warn` helper that writes to stderr only when
  `Config.verbose` is set
- Normalise all diagnostic messages to a consistent format (`Warning:
  ... (UID: ...)`)
- Remove `debug_print_of_recurrence_and_skip`; inline skip at each call
  site
- Fix `add_common_part` to always emit a trailing `\\\n    `
  continuation line
This commit is contained in:
2026-05-24 12:25:22 +02:00
parent e2f637895d
commit db2adbfbbb
7 changed files with 150 additions and 55 deletions

View File

@@ -164,10 +164,13 @@ let render_alarm (rem : rem) : alarm_rendering =
end
(* ── buffer primitives ────────────────────────────────────────── *)
let add_rem b = Buffer.add_string b "REM "
let add_uid b uuid = Buffer.add_string b (spf "\\\n INFO \"UID: %s\" " uuid)
let add_source b source = Buffer.add_string b (spf "\\\n INFO \"Calendar: %s\" " (String.uppercase_ascii source))
let add_uid b uuid = if not !Config.no_uuid then Buffer.add_string b (spf "\\\n INFO \"UID: %s\" " uuid)
let add_source b source =
if not !Config.no_source then
Buffer.add_string b (spf "\\\n INFO \"Calendar: %s\" " (String.uppercase_ascii source))
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))
@@ -275,26 +278,28 @@ let add_msg b ?(alarm = empty_alarm) ?(timed = false) summary =
Buffer.add_string b (spf " MSG %s\n" body)
let add_location b loc =
match loc with
| Some loc -> begin
let loc = String.trim loc in
Buffer.add_string b (spf "\\\n INFO \"Location: %s\" " (escape_msg loc))
end
| None -> ()
if not !Config.no_location then
match loc with
| Some loc ->
let loc = String.trim loc in
Buffer.add_string b (spf "\\\n INFO \"Location: %s\" " (escape_msg loc))
| None -> ()
let add_description b desc =
match desc with
| Some desc ->
let desc = String.trim desc in
Buffer.add_string b (spf "\\\n INFO \"Description: %s\" " (escape_msg desc))
| None -> ()
if not !Config.no_description then
match desc with
| Some desc ->
let desc = String.trim desc in
Buffer.add_string b (spf "\\\n INFO \"Description: %s\" " (escape_msg desc))
| None -> ()
let add_url b url =
match url with
| Some url ->
let url = String.trim url in
Buffer.add_string b (spf "\\\n INFO \"Url: %s\" " (escape_msg url))
| None -> ()
if not !Config.no_conference_url then
match url with
| Some url ->
let url = String.trim url in
Buffer.add_string b (spf "\\\n INFO \"Url: %s\" " (escape_msg url))
| None -> ()
let add_common_part b rem =
add_rem b;
@@ -302,7 +307,8 @@ let add_common_part b rem =
add_source b rem.source;
add_location b rem.location;
add_description b rem.description;
add_url b rem.conference_url
add_url b rem.conference_url;
Buffer.add_string b "\\\n "
let date_of_date_or_datetime (d : Icalendar.date_or_datetime) : Timedesc.Date.t =
match d with