Function: icalendar-make-component
icalendar-make-component is a macro defined in icalendar-ast.el.gz.
Signature
(icalendar-make-component TYPE &rest TEMPLATES)
Documentation
Construct an iCalendar component node of TYPE from TEMPLATES.
TYPE should be an iCalendar type symbol satisfying
icalendar-component-type-symbol-p; it should not be quoted.
Each expression in TEMPLATES should represent a child node of the
component; see icalendar-make-node-from-templates for the format of
such TEMPLATES. A template can also have the form (@ L), where L
evaluates to a list of child nodes to be added to the component.
Any value in TEMPLATES that evaluates to nil will be removed before the component node is constructed.
If TYPE is icalendar-vevent, icalendar-vtodo, icalendar-vjournal,
or icalendar-vfreebusy, the properties icalendar-dtstamp and
icalendar-uid will be automatically provided, if they are absent in
TEMPLATES. Likewise, if TYPE is icalendar-vcalendar, the properties
icalendar-prodid, icalendar-version, and icalendar-calscale will
be automatically provided if absent.
For example,
(icalendar-make-component icalendar-vevent
(icalendar-summary "Party")
(icalendar-location "Robot House")
(@ list-of-other-properties))
will return an icalendar-vevent node containing the provided
properties as well as icalendar-dtstamp and icalendar-uid
properties.
The resulting syntax node is checked for validity by
icalendar-ast-node-valid-p before it is returned.
Source Code
;; Defined in /usr/src/emacs/lisp/calendar/icalendar-ast.el.gz
(defmacro ical:make-component (type &rest templates)
"Construct an iCalendar component node of TYPE from TEMPLATES.
TYPE should be an iCalendar type symbol satisfying
`icalendar-component-type-symbol-p'; it should not be quoted.
Each expression in TEMPLATES should represent a child node of the
component; see `icalendar-make-node-from-templates' for the format of
such TEMPLATES. A template can also have the form (@ L), where L
evaluates to a list of child nodes to be added to the component.
Any value in TEMPLATES that evaluates to nil will be removed before the
component node is constructed.
If TYPE is `icalendar-vevent', `icalendar-vtodo', `icalendar-vjournal',
or `icalendar-vfreebusy', the properties `icalendar-dtstamp' and
`icalendar-uid' will be automatically provided, if they are absent in
TEMPLATES. Likewise, if TYPE is `icalendar-vcalendar', the properties
`icalendar-prodid', `icalendar-version', and `icalendar-calscale' will
be automatically provided if absent.
For example,
(icalendar-make-component icalendar-vevent
(icalendar-summary \"Party\")
(icalendar-location \"Robot House\")
(@ list-of-other-properties))
will return an `icalendar-vevent' node containing the provided
properties as well as `icalendar-dtstamp' and `icalendar-uid'
properties.
The resulting syntax node is checked for validity by
`icalendar-ast-node-valid-p' before it is returned."
(declare (debug (symbolp &rest form))
(indent 1))
;; TODO: support `ical:other-component', maybe like
;; (ical:other-component (:x-name "X-NAME") templates ...)
(unless (ical:component-type-symbol-p type)
(error "Not an iCalendar component type: %s" type))
;; Add templates for required properties automatically if we can:
(when (memq type '(ical:vevent ical:vtodo ical:vjournal ical:vfreebusy))
(unless (assq 'ical:dtstamp templates)
(push
'(icalendar-make-property icalendar-dtstamp
(let ((stamp (decode-time nil t)))
;; Ensure we return UTC, not just :zone 0:
(setf (decoded-time-zone stamp) t)
stamp))
templates))
(unless (assq 'ical:uid templates)
(push `(ical:uid ,(ical:make-uid templates))
templates)))
(when (eq type 'ical:vcalendar)
(unless (assq 'ical:prodid templates)
(push `(ical:prodid ,ical:vcalendar-prodid)
templates))
(unless (assq 'ical:version templates)
(push `(ical:version ,ical:vcalendar-version)
templates))
(unless (assq 'ical:calscale templates)
(push '(ical:calscale "GREGORIAN")
templates)))
(when (null templates)
(error "At least one template is required"))
(let (children lists-of-children)
(dolist (c templates)
(cond ((and (listp c) (ical:type-symbol-p (car c)))
;; c is a template for a child node, so it should be
;; recursively expanded:
(push (cons 'ical:make-node-from-templates c)
children))
((and (listp c) (eq '@ (car c)))
;; c is a template (@ L) where L evaluates to a list of children:
(push (cadr c) lists-of-children))
(t
;; otherwise, just pass c through as is; this allows
;; interleaving templates with other expressions that
;; evaluate to syntax nodes:
(push c children))))
(setq children (nreverse children)
lists-of-children (nreverse lists-of-children))
(when (or children lists-of-children)
`(ical:ast-node-valid-p
(ical:make-ast-node
(quote ,type)
nil
(seq-filter #'identity
(append (list ,@children) ,@lists-of-children)))))))