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