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 ~collection ?timezone ?end_timezone ~fs calendar_dir =
7 let ( let* ) = Result.bind in
8 let* start = parse_start ~start_date ~start_time ~timezone in
9 let* start =
10 match start with
11 | Some s -> Ok s
12 | None -> Error (`Msg "Start date required")
13 in
14 let* end_ = parse_end ~end_date ~end_time ~timezone ~end_timezone in
15 let* recurrence =
16 match recur with
17 | Some r ->
18 let* p = Recur.parse_recurrence r in
19 Ok (Some p)
20 | None -> Ok None
21 in
22 let collection = Collection.Col collection in
23 let event =
24 Event.create ~summary ~start ?end_ ?location ?description ?recurrence
25 collection
26 in
27 let* _ = Calendar_dir.add_event ~fs calendar_dir event in
28 Printf.printf "Event created with ID: %s\n" (Event.get_id event);
29 Ok ()
30
31let cmd ~fs calendar_dir =
32 let run summary start_date start_time end_date end_time location description
33 recur collection timezone end_timezone =
34 match
35 run ~summary ~start_date ~start_time ~end_date ~end_time ~location
36 ~description ~recur ~collection ?timezone ?end_timezone ~fs calendar_dir
37 with
38 | Error (`Msg msg) ->
39 Printf.eprintf "Error: %s\n%!" msg;
40 1
41 | Ok () -> 0
42 in
43 let term =
44 Term.(
45 const run $ required_summary_arg $ start_date_arg $ start_time_arg
46 $ end_date_arg $ end_time_arg $ location_arg $ description_arg $ recur_arg
47 $ collection_arg $ timezone_arg $ end_time_arg)
48 in
49 let doc = "Add a new calendar event" in
50 let man =
51 [
52 `S Manpage.s_description;
53 `P "Add a new event to your calendar.";
54 `P
55 "Specify the event summary (title) as the first argument, and use \
56 options to set other details.";
57 `S Manpage.s_options;
58 ]
59 @ date_format_manpage_entries
60 @ [
61 `S Manpage.s_examples;
62 `I ("Add a event for today:", "caled add \"Meeting\" -d today -t 14:00");
63 `I
64 ( "Add an event with a specific date and time:",
65 "caled add \"Dentist Appointment\" -d 2025-04-15 -t 10:30" );
66 `I
67 ( "Add an event with an end time:",
68 "caled add \"Conference\" -d 2025-05-20 -t 09:00 -e 2025-05-22 -T \
69 17:00" );
70 `I
71 ( "Add an event with location and description:",
72 "caled add \"Lunch with Bob\" -d 2025-04-02 -t 12:30 -l \"Pasta \
73 Restaurant\" -D \"Discuss project plans\"" );
74 `I
75 ( "Add an event to a specific calendar:",
76 "caled add \"Work Meeting\" -d 2025-04-03 -t 15:00 --calendar work"
77 );
78 `S "RECURRENCE";
79 `P
80 "Recurrence rule in iCalendar RFC5545 format. The FREQ part is \
81 required.";
82 `I ("FREQ=<frequency>", "DAILY, WEEKLY, MONTHLY, or YEARLY (required)");
83 `I
84 ( "COUNT=<number>",
85 "Limit to this many occurrences (optional, cannot be used with \
86 UNTIL)" );
87 `I
88 ( "UNTIL=<date>",
89 "Repeat until this date (optional, cannot be used with COUNT)" );
90 `I
91 ( "INTERVAL=<number>",
92 "Interval between occurrences, e.g., 2 for every other (optional)"
93 );
94 `I
95 ( "BYDAY=<dayspec>",
96 "Specific days, e.g., MO,WE,FR or 1MO (first Monday) (optional)" );
97 `I
98 ( "BYMONTHDAY=<daynum>",
99 "Day of month, e.g., 1,15 or -1 (last day) (optional)" );
100 `I
101 ( "BYMONTH=<monthnum>",
102 "Month number, e.g., 1,6,12 for Jan,Jun,Dec (optional)" );
103 `P "Examples:";
104 `I ("FREQ=DAILY;COUNT=5", "Daily for 5 occurrences");
105 `I ("FREQ=WEEKLY;INTERVAL=2", "Every other week indefinitely");
106 `I ("FREQ=WEEKLY;BYDAY=MO,WE,FR", "Every Monday, Wednesday, Friday");
107 `I ("FREQ=MONTHLY;BYDAY=1MO", "First Monday of every month");
108 `I
109 ( "FREQ=YEARLY;BYMONTH=1;BYMONTHDAY=1",
110 "Every January 1st (New Year's Day)" );
111 `I ("FREQ=MONTHLY;BYMONTHDAY=-1", "Last day of every month");
112 ]
113 in
114 let info = Cmd.info "add" ~doc ~man in
115 Cmd.v info term