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:
37
bin/main.ml
37
bin/main.ml
@@ -14,16 +14,32 @@ let read_file filename =
|
||||
close_in ic;
|
||||
Bytes.unsafe_to_string s
|
||||
|
||||
let ical2rem tz_opt ical_files =
|
||||
Utils.init_target_tz tz_opt;
|
||||
let ical2rem (args : CommandLine.cli_args) ical_files =
|
||||
(* Validate --source with multiple files *)
|
||||
(match args.source with
|
||||
| Some _ when List.length ical_files > 1 ->
|
||||
Printf.eprintf "Error: --source can only be used with a single input file.\n";
|
||||
exit 1
|
||||
| _ -> ());
|
||||
Config.verbose := args.verbose;
|
||||
Config.no_uuid := args.no_uuid;
|
||||
Config.no_source := args.no_source;
|
||||
Config.no_location := args.no_location;
|
||||
Config.no_description := args.no_description;
|
||||
Config.no_conference_url := args.no_conference_url;
|
||||
Utils.init_target_tz args.tz;
|
||||
let good_rems =
|
||||
ListLabels.fold_left ~init:[] ical_files ~f:(fun good_rems_acc filename ->
|
||||
try
|
||||
let file_content = read_file filename in
|
||||
let basename = Filename.remove_extension (Filename.basename filename) in
|
||||
let basename =
|
||||
match args.source with
|
||||
| Some name -> name
|
||||
| None -> Filename.remove_extension (Filename.basename filename)
|
||||
in
|
||||
match Icalendar.parse file_content with
|
||||
| Error e ->
|
||||
if e <> ": not enough input" then prerr_endline ("Error parsing iCalendar file: " ^ e);
|
||||
if e <> ": not enough input" then Utils.warn "Error: could not parse %s: %s\n" filename e;
|
||||
good_rems_acc
|
||||
| Ok (_, components) -> begin
|
||||
let events_map : Icalendar.event list Map.t =
|
||||
@@ -44,21 +60,26 @@ let ical2rem tz_opt ical_files =
|
||||
match rem_or_error with
|
||||
| Ok rem -> rem :: good_rems
|
||||
| Error (EventPredicates.Invalid_date s) ->
|
||||
Printf.eprintf "UID: %s Invalid date: %s\n" uid s;
|
||||
Utils.warn "Warning: invalid date: %s (UID: %s)\n" s uid;
|
||||
good_rems
|
||||
| Error Skip ->
|
||||
Printf.eprintf "UID: %s Skipped\n" uid;
|
||||
Utils.warn "Warning: event skipped (UID: %s)\n" uid;
|
||||
good_rems)
|
||||
in
|
||||
let good_rems = List.rev good_rems in
|
||||
good_rems @ good_rems_acc
|
||||
end
|
||||
with e ->
|
||||
prerr_endline ("Error reading file " ^ filename ^ ": " ^ Printexc.to_string e);
|
||||
Utils.warn "Error: could not read file %s: %s\n" filename (Printexc.to_string e);
|
||||
good_rems_acc)
|
||||
in
|
||||
|
||||
let good_rems = List.sort (fun a b -> Timedesc.Date.compare b.Remind.date a.Remind.date) good_rems in
|
||||
let good_rems =
|
||||
match args.sort with
|
||||
| CommandLine.Desc -> List.sort (fun a b -> Timedesc.Date.compare b.Remind.date a.Remind.date) good_rems
|
||||
| CommandLine.Asc -> List.sort (fun a b -> Timedesc.Date.compare a.Remind.date b.Remind.date) good_rems
|
||||
| CommandLine.Original -> good_rems
|
||||
in
|
||||
try ListLabels.iter good_rems ~f:(fun rem -> Printf.printf "%s" (Remind.string_of_rem rem))
|
||||
with e ->
|
||||
Printf.eprintf "Error processing reminders: %s\n" (Printexc.to_string e);
|
||||
|
||||
Reference in New Issue
Block a user