Something went wrong. Try again.
Command-line and Emacs Calendar Client
Something went wrong. Try again.
OCaml
at timezone-cli
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201type component_type = CEvent | CTodo | CJournal [@@deriving sexp]
type t = | Event of Event.t | Todo of Todo.t | Journal of Journal.t
let sexp_of_t = function | Event e -> Event.sexp_of_t e | Todo t -> Todo.sexp_of_t t | Journal j -> Journal.sexp_of_t j
let component_type = function | Event _ -> CEvent | Todo _ -> CTodo | Journal _ -> CJournal
let of_event e = Event elet of_todo t = Todo tlet of_journal j = Journal j
let to_event = function Event e -> Some e | _ -> Nonelet to_todo = function Todo t -> Some t | _ -> Nonelet to_journal = function Journal j -> Some j | _ -> None
let get_id = function | Event e -> Event.get_id e | Todo t -> Todo.get_id t | Journal j -> Journal.get_id j
let get_summary = function | Event e -> Event.get_summary e | Todo t -> Todo.get_summary t | Journal j -> Journal.get_summary j
let get_description = function | Event e -> Event.get_description e | Todo t -> Todo.get_description t | Journal j -> Journal.get_description j
let get_categories = function | Event e -> Event.get_categories e | Todo t -> Todo.get_categories t | Journal j -> Journal.get_categories j
let get_calendar_name = function | Event e -> Event.get_calendar_name e | Todo t -> Todo.get_calendar_name t | Journal j -> Journal.get_calendar_name j
let get_file = function | Event e -> Event.get_file e | Todo t -> Todo.get_file t | Journal j -> Journal.get_file j
let get_alarms = function | Event e -> Event.get_alarms e | Todo t -> Todo.get_alarms t | Journal _ -> []
let get_start = function | Event e -> Some (Event.get_start e) | Todo t -> Todo.get_start t | Journal j -> Journal.get_start j
let to_ical_component = function | Event e -> `Event (Event.to_ical_event e) | Todo t -> `Todo (Todo.to_ical_todo t, Todo.get_alarms t) | Journal j -> `Journal (Journal.to_ical_journal j)
let to_ical_calendar = function | Event e -> Event.to_ical_calendar e | Todo t -> Todo.to_ical_calendar t | Journal j -> Journal.to_ical_calendar j
let components_of_icalendar calendar_name ~file calendar = let events = Event.events_of_icalendar calendar_name ~file calendar |> List.map of_event in let todos = Todo.todos_of_icalendar calendar_name ~file calendar |> List.map of_todo in let journals = Journal.journals_of_icalendar calendar_name ~file calendar |> List.map of_journal in events @ todos @ journals
(* Comparators *)type comparator = t -> t -> int
let by_start a b = match (get_start a, get_start b) with | None, None -> 0 | None, Some _ -> 1 | Some _, None -> -1 | Some ta, Some tb -> Ptime.compare ta tb
let by_summary a b = match (get_summary a, get_summary b) with | None, None -> 0 | None, Some _ -> 1 | Some _, None -> -1 | Some sa, Some sb -> String.compare sa sb
let by_calendar_name a b = String.compare (get_calendar_name a) (get_calendar_name b)
let by_type a b = match (component_type a, component_type b) with | CEvent, CEvent | CTodo, CTodo | CJournal, CJournal -> 0 | CEvent, _ -> -1 | _, CEvent -> 1 | CTodo, CJournal -> -1 | CJournal, CTodo -> 1
let descending comp a b = -comp a blet chain comp1 comp2 a b = match comp1 a b with 0 -> comp2 a b | n -> n
(* Filters *)type filter = t -> bool
let is_type typ comp = component_type comp = typ
let summary_contains pattern comp = match get_summary comp with | Some s -> Re.execp (Re.compile (Re.str pattern |> Re.no_case)) s | None -> false
let description_contains pattern comp = match get_description comp with | Some d -> Re.execp (Re.compile (Re.str pattern |> Re.no_case)) d | None -> false
let in_calendars calendars comp = List.mem (get_calendar_name comp) calendars
let has_categories cats comp = let comp_cats = get_categories comp in List.exists (fun cat -> List.mem cat comp_cats) cats
let and_filter filters comp = List.for_all (fun f -> f comp) filters
let or_filter filters comp = List.exists (fun f -> f comp) filters
let not_filter f comp = not (f comp)
(* Formatting *)type format = [ `Text | `Entries | `Json | `Csv | `Ics | `Sexp ]
let format_component ?(format = `Text) ?tz comp = let tz_val = match tz with Some tz -> tz | None -> Date.local_timezone () in match comp with | Event e -> Event.format_event ~format ~tz:tz_val e | Todo t -> Todo.format_todo ~format ~tz:tz_val t | Journal j -> Journal.format_journal ~format ~tz:tz_val j
let format_components ?(format = `Text) ?tz ?get_color comps = let events = List.filter_map to_event comps in let todos = List.filter_map to_todo comps in let journals = List.filter_map to_journal comps in let tz_val = match tz with Some tz -> tz | None -> Date.local_timezone () in let event_str = Event.format_events ~format ~tz:tz_val ?get_color events in let todo_str = Todo.format_todos ~format ~tz:tz_val ?get_color todos in let journal_str = Journal.format_journals ~format ~tz:tz_val ?get_color journals in match format with | `Json -> Printf.sprintf "{\"events\":%s,\"todos\":%s,\"journals\":%s}" event_str todo_str journal_str | `Sexp -> Printf.sprintf "(:events %s :todos %s :journals %s)" event_str todo_str journal_str | _ -> let parts = [event_str; todo_str; journal_str] in let non_empty = List.filter (fun s -> s <> "") parts in String.concat "\n" non_empty
type alarm_fire = { fire_time : Ptime.t; component : t; alarm : Icalendar.alarm;}
let query_alarm_fires ~from ~to_ components = let event_fires = List.filter_map to_event components |> List.concat_map (Event.compute_alarm_fires ~from ~to_) |> List.map (fun (af : Event.alarm_fire) -> { fire_time = af.fire_time; component = Event af.event; alarm = af.alarm }) in let todo_fires = List.filter_map to_todo components |> List.concat_map (Todo.compute_alarm_fires ~from ~to_) |> List.map (fun (af : Todo.alarm_fire) -> { fire_time = af.fire_time; component = Todo af.todo; alarm = af.alarm }) in let all = event_fires @ todo_fires in List.sort (fun a b -> Ptime.compare a.fire_time b.fire_time) all