Function: icalendar-define-type

icalendar-define-type is a macro defined in icalendar-macs.el.gz.

Signature

(icalendar-define-type SYMBOLIC-NAME PRINT-NAME DOC SPECIFIER MATCHER &key LINK (READER #'identity) (PRINTER #'identity))

Documentation

Define an iCalendar value type named SYMBOLIC-NAME.

PRINT-NAME should be the string used to represent this type in the value of an icalendar-valuetypeparam property parameter, or nil if this is not a type that should be specified there. DOC should be a documentation string for the type. SPECIFIER should be a type specifier in the sense of cl-deftype. MATCHER should be an RX definition body (see rx-define; argument lists are not supported).

Before the type is defined with cl-deftype, a function will be defined named icalendar-match-PRINT-NAME-value
(or icalendar-match-OTHER-value, if PRINT-NAME is nil, where
OTHER is derived from SYMBOLIC-NAME by removing any prefix
"icalendar-" and suffix "value"). This function takes a
string argument and matches it against MATCHER. This function may thus occur in SPECIFIER (e.g. in a (satisfies ...) clause).

See the functions icalendar-read-value-node, icalendar-parse-value-node, and icalendar-print-value-node to convert values defined with this macro to and from their text representation in iCalendar format.

The following keyword arguments are accepted:

:reader - a function to read data of this type. It will be passed
  a string matching MATCHER and should return an Elisp data structure.
  Its name does not need to be quoted. (default: identity)

:printer - a function to convert an Elisp data structure of this
  type to a string. Its name does not need to be quoted.
  (default: identity)

:link - a string containing a URL for further documentation of this type

Source Code

;; Defined in /usr/src/emacs/lisp/calendar/icalendar-macs.el.gz
;; Define value types:
(cl-defmacro ical:define-type (symbolic-name print-name doc specifier matcher
                               &key link
                                    (reader #'identity)
                                    (printer #'identity))
  "Define an iCalendar value type named SYMBOLIC-NAME.

PRINT-NAME should be the string used to represent this type in
the value of an `icalendar-valuetypeparam' property parameter, or
nil if this is not a type that should be specified there.  DOC
should be a documentation string for the type.  SPECIFIER should
be a type specifier in the sense of `cl-deftype'.  MATCHER should
be an RX definition body (see `rx-define'; argument lists are not
supported).

Before the type is defined with `cl-deftype', a function will be
defined named `icalendar-match-PRINT-NAME-value'
\(or `icalendar-match-OTHER-value', if PRINT-NAME is nil, where
OTHER is derived from SYMBOLIC-NAME by removing any prefix
\"icalendar-\" and suffix \"value\").  This function takes a
string argument and matches it against MATCHER.  This function may
thus occur in SPECIFIER (e.g. in a (satisfies ...) clause).

See the functions `icalendar-read-value-node',
`icalendar-parse-value-node', and `icalendar-print-value-node' to
convert values defined with this macro to and from their text
representation in iCalendar format.

The following keyword arguments are accepted:

:reader - a function to read data of this type.  It will be passed
  a string matching MATCHER and should return an Elisp data structure.
  Its name does not need to be quoted.  (default: identity)

:printer - a function to convert an Elisp data structure of this
  type to a string.  Its name does not need to be quoted.
  (default: identity)

:link - a string containing a URL for further documentation of this type"
  (declare (doc-string 2))
  (let* (;; Related functions:
         (type-dname (if print-name
                         (downcase print-name)
                       (string-trim
                        (symbol-name symbolic-name)
                        "icalendar-" "value")))
         (matcher-name (intern (concat "icalendar-match-" type-dname "-value")))
         ;; Documentation:
         (header "It names a value type defined by `icalendar-define-type'.")
         (matcher-doc (format
"Strings representing values of this type can be matched with
`%s'.\n" matcher-name))
         (reader-doc (format "They can be read with `%s'\n" reader))
         (printer-doc (format "and printed with `%s'." printer))
         (full-doc (concat header "\n\n" doc "\n\n"
                           matcher-doc reader-doc printer-doc "\n\n"
"A syntax node of this type can be read with
`icalendar-read-value-node' or parsed with `icalendar-parse-value-node',
and printed with `icalendar-print-value-node'.")))

    `(progn
       ;; Type metadata needs to be available at both compile time and
       ;; run time.  In particular, `ical:value-type-symbol-p' needs to
       ;; work at compile time.
       (eval-and-compile
         (setplist (quote ,symbolic-name)
                   (list
                    'ical:is-type t
                    'ical:is-value t
                    'ical:matcher (function ,matcher-name)
                    'ical:value-rx (quote ,symbolic-name)
                    'ical:value-reader (function ,reader)
                    'ical:value-printer (function ,printer)
                    'ical:type-documentation ,full-doc
                    'ical:link ,link)))

       (rx-define ,symbolic-name
         ,matcher)

       (defun ,matcher-name (s)
         ,(format "Match string S against rx `%s'." symbolic-name)
         (string-match (rx ,symbolic-name) s))

       (cl-deftype ,symbolic-name () ,specifier)

       ;; Store the association between the print name and the type
       ;; symbol in ical:value-types.  The check against print name
       ;; here allows us to also define value types that aren't
       ;; "really" types according to the standard, like
       ;; `ical:geo-coordinates'.  Only types that have a
       ;; print-name can be specified in a VALUE parameter.
       (when ,print-name
         (push (cons ,print-name (quote ,symbolic-name)) ical:value-types)))))