Command-line and Emacs Calendar Client
1open Cmdliner
2open Caledonia_lib
3open Query_args
4
5let run ?from_str ?to_str ?calendar ?count ~format ~today ~tomorrow ~week ~month
6 ?timezone ~sort ~fs calendar_dir =
7 let ( let* ) = Result.bind in
8 let tz = Query_args.parse_timezone ~timezone in
9 let* from, to_ =
10 match
11 Date.convert_relative_date_formats ~tz ~today ~tomorrow ~week ~month ()
12 with
13 | Some (from, to_) ->
14 let* _ =
15 match (from_str, to_str) with
16 | None, None -> Ok ()
17 | _ ->
18 Error
19 (`Msg
20 "Can't specify --from / --to when using --today, --week, \
21 --month")
22 in
23 Ok (Some from, to_)
24 | None -> (
25 let* from =
26 match from_str with
27 | None -> Ok None
28 | Some s ->
29 let* d = Date.parse_date ~tz s `From in
30 Ok (Some d)
31 in
32 let* to_ =
33 match to_str with
34 | None -> Ok None
35 | Some s ->
36 let* d = Date.parse_date ~tz s `From in
37 Ok (Some d)
38 in
39 match (from, to_) with
40 | Some f, Some t -> Ok (Some f, Date.to_end_of_day t)
41 | Some f, None ->
42 let one_month_later = Date.add_months f 1 in
43 Ok (Some f, one_month_later)
44 | None, Some t ->
45 let today_date = !Date.get_today ~tz () in
46 Ok (Some today_date, Date.to_end_of_day t)
47 | None, None ->
48 let today_date = !Date.get_today ~tz () in
49 let one_month_later = Date.add_months today_date 1 in
50 Ok (Some today_date, one_month_later))
51 in
52 let filter =
53 match calendar with
54 | Some collection_id ->
55 Some (Query.in_collections [ Collection.Col collection_id ])
56 | None -> None
57 in
58 let comparator = Query_args.create_instance_comparator sort in
59 let* results =
60 Query.query ~fs calendar_dir ?filter ~from ~to_ ~comparator ?limit:count ()
61 in
62 if results = [] then print_endline "No events found."
63 else
64 print_endline
65 (Format.format_instances ~fs ~calendar_dir ~format ~tz results);
66 Ok ()
67
68let cmd ~fs calendar_dir =
69 let run from_str to_str calendar count format today tomorrow week month
70 timezone sort =
71 match
72 run ?from_str ?to_str ?calendar ?count ~format ~today ~tomorrow ~week
73 ~month ?timezone ~sort ~fs calendar_dir
74 with
75 | Error (`Msg msg) ->
76 Printf.eprintf "Error: %s\n%!" msg;
77 1
78 | Ok () -> 0
79 in
80 let term =
81 Term.(
82 const run $ from_arg $ to_arg $ calendar_arg $ count_arg $ format_arg
83 $ today_arg $ tomorrow_arg $ week_arg $ month_arg $ timezone_arg
84 $ sort_arg)
85 in
86 let doc = "List calendar events" in
87 let man =
88 [
89 `S Manpage.s_description;
90 `P "List calendar events within a specified date range.";
91 `P "By default, events from today to one month from today are shown.";
92 `P "You can use date flags to show events for a specific time period.";
93 `P "You can also filter events by calendar using the --calendar flag.";
94 `P "Use the --sort option to control the sorting of results.";
95 `S Manpage.s_options;
96 ]
97 @ date_format_manpage_entries
98 @ [
99 `S Manpage.s_examples;
100 `I ("List all events for today:", "caled list --today");
101 `I ("List all events for tomorrow:", "caled list --tomorrow");
102 `I ("List all events for the current week:", "caled list --week");
103 `I ("List all events for the current month:", "caled list --month");
104 `I
105 ( "List events within a specific date range:",
106 "caled list --from 2025-03-27 --to 2025-04-01" );
107 `I
108 ("List events from a specific calendar:", "caled list --calendar work");
109 `I ("List events in JSON format:", "caled list --format json");
110 `I ("Limit the number of events shown:", "caled list --count 5");
111 `I
112 ( "Sort by multiple fields (start time and summary):",
113 "caled list --sort start --sort summary" );
114 `I
115 ( "Sort by calendar name in descending order:",
116 "caled list --sort calendar:desc" );
117 ]
118 in
119 let exit_info =
120 [ Cmd.Exit.info ~doc:"on success." 0; Cmd.Exit.info ~doc:"on error." 1 ]
121 in
122 let info = Cmd.info "list" ~doc ~man ~exits:exit_info in
123 Cmd.v info term