Function: icalendar-define-param

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

Signature

(icalendar-define-param SYMBOLIC-NAME PARAM-NAME DOC VALUE &key QUOTED LIST-SEP DEFAULT (UNRECOGNIZED default) ((:name-face NAME-FACE) 'icalendar-parameter-name NONDEFAULT-NAME-FACE) ((:value-face VALUE-FACE) 'icalendar-parameter-value NONDEFAULT-VALUE-FACE) ((:warn-face WARN-FACE) 'icalendar-warning NONDEFAULT-WARN-FACE) EXTRA-FACES LINK)

Documentation

Define iCalendar parameter PARAM-NAME under the symbol SYMBOLIC-NAME.

PARAM-NAME should be the parameter name as it should appear in iCalendar data.

VALUE should either be a symbol for a value type defined with icalendar-define-type, or an rx regular expression. If it is a type symbol, the regex, reader and printer functions associated with that type will be used when parsing and serializing values. If it is a regular expression, it is assumed that the values of this parameter are strings which match that regular expression.

An rx regular expression named SYMBOLIC-NAME which matches the parameter is defined:
  Group 1 of this regex matches PARAM-NAME
    (or any valid parameter name, if PARAM-NAME is nil).
  Group 2 matches VALUE, which specifies a correct value
    for this parameter according to RFC5545.
  Group 3, if matched, contains any parameter value which does
    *not* match VALUE, and is incorrect according to the standard.

This regex matches the entire string representing this parameter, from ";" to the end of its value. Another regular expression named SYMBOLIC-NAME-value is also defined to match just the value part, after ";PARAM-NAME=", with groups 2 and 3 as above.

A function to match the complete parameter expression called icalendar-match-PARAM-NAME-param is defined
(or icalendar-match-OTHER-param-value if PARAM-NAME is nil,
where OTHER is derived from SYMBOLIC-NAME by removing any prefix icalendar- and suffix param). This function is used to provide syntax highlighting in icalendar-mode.

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

The following keyword arguments are accepted:

:default - a (string representing the) default value, if the
  parameter is not specified on a given property.

:unrecognized - a (string representing the) value which must be
  substituted for values that are not recognized but syntactically
  correct according to RFC5545. Unrecognized values must be in match
  group 5 of the regex determined by VALUE. An unrecognized value will
  be preserved in the syntax tree metadata and printed instead of this
  value when the node is printed. Defaults to any value specified for
  :default.

:quoted - non-nil if values of this parameter must always be surrounded
  by (double-)quotation marks when printed, according to RFC5545.

:list-sep - if the parameter accepts a list of values, this should be a
  string which separates the values (typically ","). If :list-sep is
  non-nil, the value string will first be split on the separator, then
  if :quoted is non-nil, the individual values will be unquoted, then
  each value will be read according to VALUE and collected into a list
  when parsing. When printing, the inverse happens: values are quoted
  if :quoted is non-nil, then joined with :list-sep. Passing this
  argument marks SYMBOLIC-NAME as a type that accepts a list of values
  for icalendar-expects-list-of-values-p.

:name-face - a face symbol for highlighting the property name
  (default: icalendar-parameter-name)

:value-face - a face symbol for highlighting valid property values
  (default: icalendar-parameter-value)

:warn-face - a face symbol for highlighting invalid property values
  (default: icalendar-warning)

:extra-faces - a list of the form accepted for HIGHLIGHT in
  font-lock-keywords. In particular,
    ((GROUPNUM FACENAME [OVERRIDE [LAXMATCH]]) ...)
  can be used to apply different faces to different
  match subgroups.

:link - a string containing a URL for documentation of this parameter.
  The URL will be provided in the documentation shown by
  describe-symbol for SYMBOLIC-NAME.

Source Code

;; Defined in /usr/src/emacs/lisp/calendar/icalendar-macs.el.gz
;; Define parameters:
(cl-defmacro ical:define-param (symbolic-name param-name doc value
                                &key quoted
                                     list-sep
                                     default
                                     (unrecognized default)
                                     ((:name-face name-face)
                                      'ical:parameter-name nondefault-name-face)
                                     ((:value-face value-face)
                                      'ical:parameter-value nondefault-value-face)
                                     ((:warn-face warn-face)
                                      'ical:warning nondefault-warn-face)
                                     extra-faces
                                     link)
  "Define iCalendar parameter PARAM-NAME under the symbol SYMBOLIC-NAME.
PARAM-NAME should be the parameter name as it should appear in
iCalendar data.

VALUE should either be a symbol for a value type defined with
`icalendar-define-type', or an `rx' regular expression.  If it is
a type symbol, the regex, reader and printer functions associated
with that type will be used when parsing and serializing values.
If it is a regular expression, it is assumed that the values of
this parameter are strings which match that regular expression.

An `rx' regular expression named SYMBOLIC-NAME which matches the
parameter is defined:
  Group 1 of this regex matches PARAM-NAME
    (or any valid parameter name, if PARAM-NAME is nil).
  Group 2 matches VALUE, which specifies a correct value
    for this parameter according to RFC5545.
  Group 3, if matched, contains any parameter value which does
    *not* match VALUE, and is incorrect according to the standard.

This regex matches the entire string representing this parameter,
from \";\" to the end of its value.  Another regular expression
named `SYMBOLIC-NAME-value' is also defined to match just the
value part, after \";PARAM-NAME=\", with groups 2 and 3 as above.

A function to match the complete parameter expression called
`icalendar-match-PARAM-NAME-param' is defined
\(or `icalendar-match-OTHER-param-value' if PARAM-NAME is nil,
where OTHER is derived from SYMBOLIC-NAME by removing any prefix
`icalendar-' and suffix `param').  This function is used
to provide syntax highlighting in `icalendar-mode'.

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

The following keyword arguments are accepted:

:default - a (string representing the) default value, if the
  parameter is not specified on a given property.

:unrecognized - a (string representing the) value which must be
  substituted for values that are not recognized but syntactically
  correct according to RFC5545.  Unrecognized values must be in match
  group 5 of the regex determined by VALUE.  An unrecognized value will
  be preserved in the syntax tree metadata and printed instead of this
  value when the node is printed.  Defaults to any value specified for
  :default.

:quoted - non-nil if values of this parameter must always be surrounded
  by (double-)quotation marks when printed, according to RFC5545.

:list-sep - if the parameter accepts a list of values, this should be a
  string which separates the values (typically \",\").  If :list-sep is
  non-nil, the value string will first be split on the separator, then
  if :quoted is non-nil, the individual values will be unquoted, then
  each value will be read according to VALUE and collected into a list
  when parsing.  When printing, the inverse happens: values are quoted
  if :quoted is non-nil, then joined with :list-sep.  Passing this
  argument marks SYMBOLIC-NAME as a type that accepts a list of values
  for `icalendar-expects-list-of-values-p'.

:name-face - a face symbol for highlighting the property name
  (default: `icalendar-parameter-name')

:value-face - a face symbol for highlighting valid property values
  (default: `icalendar-parameter-value')

:warn-face - a face symbol for highlighting invalid property values
  (default: `icalendar-warning')

:extra-faces - a list of the form accepted for HIGHLIGHT in
  `font-lock-keywords'.  In particular,
    ((GROUPNUM FACENAME [OVERRIDE [LAXMATCH]]) ...)
  can be used to apply different faces to different
  match subgroups.

:link - a string containing a URL for documentation of this parameter.
  The URL will be provided in the documentation shown by
  `describe-symbol' for SYMBOLIC-NAME."
  (declare (doc-string 2))
  (let* (;; Related function names:
         (param-dname (if param-name
                          (downcase param-name)
                        (string-trim (symbol-name symbolic-name)
                                     "icalendar-" "param")))
         (matcher-name (intern (concat "icalendar-match-" param-dname "-param")))
         (type-predicate-name
          (intern (concat "icalendar-" param-dname "-param-p")))
         ;; Value regexes:
         (qvalue-rx (if quoted `(seq ?\" ,value ?\") value))
         (values-rx (when list-sep
                     `(seq ,qvalue-rx (zero-or-more ,list-sep ,qvalue-rx))))
         (full-value-rx-name
          (intern (concat (symbol-name symbolic-name) "-value")))
         ;; Faces:
         (has-faces (or nondefault-name-face nondefault-value-face
                        nondefault-warn-face extra-faces))
         ;; Documentation:
         (header "It names a parameter type defined by `icalendar-define-param'.")
         (val-list (if list-sep (concat "VAL1" list-sep "VAL2" list-sep "...")
                     "VAL"))
         (s (if list-sep "s" "")) ; to make plurals
         (val-doc (concat "VAL" s " "
                          "must be " (unless list-sep "a ") (when quoted "quoted ")
                          (if (ical:value-type-symbol-p value)
                              (format "`%s' value%s" (symbol-name value) s)
                            (format "string%s matching rx `%S'" s value))))
         (syntax-doc (format "Syntax: %s=%s\n%s"
                             (or param-name "(NAME)") val-list val-doc))
         (full-doc (concat header "\n\n" doc "\n\n" syntax-doc)))

    `(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-param t
                    'ical:matcher (function ,matcher-name)
                    'ical:default-value ,default
                    'ical:is-quoted ,quoted
                    'ical:list-sep ,list-sep
                    'ical:substitute-value ,unrecognized
                    'ical:matcher (function ,matcher-name)
                    'ical:value-type
                    (when (ical:value-type-symbol-p (quote ,value))
                      (quote ,value))
                    'ical:value-rx (quote ,value)
                    'ical:values-rx (quote ,values-rx)
                    'ical:full-value-rx (quote ,full-value-rx-name)
                    'ical:type-documentation ,full-doc
                    'ical:link ,link)))

       ;; Regex which matches just the value of the parameter:
       ;; Group 2: correct values of the parameter, and
       ;; Group 3: incorrect values up to the next parameter
       (rx-define ,full-value-rx-name
         (or (group-n 2 ,(or values-rx qvalue-rx))
             (group-n 3 ical:param-value)))

       ;; Regex which matches the full parameter:
       ;; Group 1: the parameter name,
       ;; Group 2: correct values of the parameter, and
       ;; Group 3: incorrect values up to the next parameter
       (rx-define ,symbolic-name
         (seq ";"
              ;; if the parameter name has no printed form, the best we
              ;; can do is match ical:param-name:
              (group-n 1 ,(or param-name 'ical:param-name))
              "="
              ,full-value-rx-name))

       ;; CL-type to represent syntax nodes for this parameter:
       (defun ,type-predicate-name (node)
         ,(format "Return non-nil if NODE represents a %s parameter." param-name)
         (and (ical:ast-node-p node)
              (eq (ical:ast-node-type node) (quote ,symbolic-name))))

       (cl-deftype ,symbolic-name () '(satisfies ,type-predicate-name))

       ;; Matcher for the full param string, for syntax highlighting:
       (defun ,matcher-name (limit)
         ,(concat (format "Matcher for %s parameter.\n" param-name)
                  "(Defined by `icalendar-define-param'.)")
         (re-search-forward (rx ,symbolic-name) limit t))

       ;; Entry for font-lock-keywords in icalendar-mode:
       (when ,has-faces
         ;; Avoid circular load of icalendar-mode.el in
         ;; icalendar-parser.el (which does not use the *-face
         ;; keywords), while still allowing external code to add to
         ;; font-lock-keywords dynamically:
         (require 'icalendar-mode)
         (push (quote (,matcher-name
                       (1 (quote ,name-face) t t)
                       (2 (quote ,value-face) t t)
                       (3 (quote ,warn-face) t t)
                       ,@extra-faces))
               ical:font-lock-keywords))

       ;; Associate the print name with the type symbol for
       ;; `ical:parse-params' and `ical:print-param':
       (when ,param-name
         (push (cons ,param-name (quote ,symbolic-name)) ical:param-types)))))