Function: icalendar-index-insert

icalendar-index-insert is a byte-compiled function defined in icalendar-parser.el.gz.

Signature

(icalendar-index-insert INDEX COMPONENT)

Documentation

Insert COMPONENT into INDEX.

Source Code

;; Defined in /usr/src/emacs/lisp/calendar/icalendar-parser.el.gz
(defun ical:index-insert (index component)
  "Insert COMPONENT into INDEX."
  (require 'icalendar-recur) ; avoid circular imports
  (require 'icalendar-utils) ;
  (declare-function icr:recurrences-to-count "icalendar-recur")
  (declare-function ical:date/time-to-local "icalendar-utils")
  (declare-function ical:date/time-to-date "icalendar-utils")
  (declare-function ical:dates-until "icalendar-utils")

  (ical:with-component component
    ((ical:dtstart :first dtstart-node :value dtstart)
     (ical:dtend :first dtend-node :value dtend)
     (ical:due :value due)
     (ical:duration :value duration)
     (ical:rrule :value rrule)
     (ical:rdate :all rdate-nodes)
     (ical:exdate :all exdate-nodes)
     (ical:uid :value uid))
    (let ((date-index (plist-get index :bydate))
          (uid-index (plist-get index :byuid))
          (tzid-index (plist-get index :bytzid))
          (recurring (plist-get index :recurring))
          (rdates
           (mapcar #'ical:ast-node-value
                   (apply #'append (mapcar #'ical:ast-node-value rdate-nodes))))
          (exdates
           (mapcar #'ical:ast-node-value
                   (apply #'append (mapcar #'ical:ast-node-value exdate-nodes))))
          dates)
      ;; Everything with a UID goes into the uid-index:
      (when uid
        (puthash uid component uid-index))
      ;; For all top-level components, we gather a list of dates on which
      ;; they recur for date-index, or put them in the recurring list:
      (when dtstart
        (cond
         ;; If the component has an RRULE that specifies a fixed number
         ;; of recurrences, compute them now and index them for each date
         ;; in each recurrence:
         ((and rrule (ical:rrule-count rrule))
          (let* ((tz (gethash (ical:with-param-of dtstart-node 'ical:tzidparam)
                              tzid-index))
                 (recs (cons dtstart (icr:recurrences-to-count component tz))))
            (dolist (rec recs)
              (let ((end-time
                     (when duration (ical:date/time-add-duration rec duration))))
                (setq dates
                      (append dates
                              (if end-time (ical:dates-until rec end-time t)
                                (list (ical:date/time-to-date
                                       (ical:date/time-to-local rec))))))))))
         ;; Same with RDATEs when there's no RRULE:
         ((and rdates (not rrule))
          (dolist (rec (cons dtstart rdates))
            (unless (or (cl-typep rec 'ical:period) (member rec exdates))
              (let ((end-time
                     (when duration
                       (ical:date/time-add-duration rec duration))))
                (setq dates
                      (append dates
                              (if end-time (ical:dates-until rec end-time t)
                                (list (ical:date/time-to-date
                                       (ical:date/time-to-local rec))))))))
            (when (cl-typep rec 'ical:period)
              (let* ((start (ical:period-start rec))
                     (end (or (ical:period-end rec)
                              (ical:date/time-add-duration
                               start (ical:period-dur-value rec)))))
                (setq dates (append dates (ical:dates-until start end t)))))))
         ;; A non-recurring event also gets an index entry for each date
         ;; until its end time:
         ((not rrule)
          (let ((end-time
                 (or dtend due
                     (when duration
                       (ical:date/time-add-duration dtstart duration)))))
            (setq dates (if end-time (ical:dates-until dtstart end-time t)
                          (list
                           (ical:date/time-to-date
                            (ical:date/time-to-local dtstart)))))))
         ;; Otherwise, we put off the computation of recurrences until queried:
         (t (push component recurring)))

        (dolist (date (seq-uniq dates))
          (let ((others (gethash date date-index)))
            ;; TODO: wonder if we should normalize, and instead store UIDs
            ;; in the date index, then look them up by UID when queried.
            (puthash date (cons component others) date-index))))

      ;; Return the updated index:
      (setq index (plist-put index :byuid uid-index))
      (setq index (plist-put index :bytzid tzid-index))
      (setq index (plist-put index :bydate date-index))
      (setq index (plist-put index :recurring recurring))
      index)))