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