Command-line and Emacs Calendar Client
1open Cmdliner
2open Caledonia_lib
3open Event_args
4
5let run ~summary ~start_date ~start_time ~end_date ~end_time ~location
6 ~description ~recur ~calendar_name ?timezone ?end_timezone ~fs calendar_dir
7 =
8 let ( let* ) = Result.bind in
9 let* start = parse_start ~start_date ~start_time ~timezone in
10 let* start =
11 match start with
12 | Some s -> Ok s
13 | None -> Error (`Msg "Start date required")
14 in
15 let* end_ =
16 (* if we have an endtime and no end date default to start date *)
17 let end_date =
18 match (end_date, end_time) with
19 | None, Some _ -> start_date
20 | _ -> end_date
21 in
22 (* if we have a start date and no end date default to start date *)
23 let end_date =
24 match (start_date, end_date) with
25 | Some _, None -> start_date
26 | _ -> end_date
27 in
28 let end_timezone =
29 (* if we specify and end date and time without a end timezone, default to the start timezone *)
30 match (end_date, end_time, end_timezone) with
31 | Some _, Some _, None -> timezone
32 | _ -> end_timezone
33 in
34 parse_end ~end_date ~end_time ~end_timezone
35 in
36 let* recurrence =
37 match recur with
38 | Some r ->
39 let* p = parse_recurrence r in
40 Ok (Some p)
41 | None -> Ok None
42 in
43 let calendar_name = calendar_name in
44 let* event =
45 Event.create ~fs
46 ~calendar_dir_path:(Calendar_dir.get_path calendar_dir)
47 ~summary ~start ?end_ ?location ?description ?recurrence calendar_name
48 in
49 let* events = Calendar_dir.get_events ~fs calendar_dir in
50 let* _ = Calendar_dir.add_event ~fs calendar_dir events event in
51 Printf.printf "Event created with ID: %s\n" (Event.get_id event);
52 Ok ()
53
54let cmd ~fs calendar_dir =
55 let run summary start_date start_time end_date end_time location description
56 recur calendar_name timezone end_timezone () =
57 match
58 run ~summary ~start_date ~start_time ~end_date ~end_time ~location
59 ~description ~recur ~calendar_name ?timezone ?end_timezone ~fs
60 calendar_dir
61 with
62 | Error (`Msg msg) ->
63 Printf.eprintf "Error: %s\n%!" msg;
64 1
65 | Ok () -> 0
66 in
67 let term =
68 Term.(
69 const run $ required_summary_arg $ start_date_arg $ start_time_arg
70 $ end_date_arg $ end_time_arg $ location_arg $ description_arg $ recur_arg
71 $ calendar_name_arg $ timezone_arg $ end_timezone_arg)
72 in
73 let doc = "Add a new calendar event" in
74 let man =
75 [
76 `S Manpage.s_description;
77 `P "Add a new event to your calendar.";
78 `P
79 "Specify the event summary (title) as the first argument, and use \
80 options to set other details.";
81 `S Manpage.s_examples;
82 `I
83 ( "Add a event for today:",
84 "caled add \"Meeting\" --date today --time 14:00" );
85 `I
86 ( "Add an event with a specific date and time:",
87 "caled add \"Dentist Appointment\" --date 2025-04-15 --time 10:30" );
88 `I
89 ( "Add an event with an end time:",
90 "caled add \"Conference\" --date 2025-05-20 --time 09:00 --end-date \
91 2025-05-22 --end-time 17:00" );
92 `I
93 ( "Add an event with location and description:",
94 "caled add \"Lunch with Bob\" --date 2025-04-02 --time 12:30 \
95 --location \"Pasta Restaurant\" --description \"Discuss project \
96 plans\"" );
97 `I
98 ( "Add an event to a specific calendar:",
99 "caled add \"Work Meeting\" --date 2025-04-03 --time 15:00 \
100 --calendar work" );
101 `S Manpage.s_options;
102 ]
103 @ date_format_manpage_entries @ recurrence_format_manpage_entries
104 @ [ `S Manpage.s_see_also ]
105 in
106 let exit_info =
107 [ Cmd.Exit.info ~doc:"on success." 0; Cmd.Exit.info ~doc:"on error." 1 ]
108 in
109 let info = Cmd.info "add" ~doc ~man ~exits:exit_info in
110 Cmd.v info term