Function: icalendar-define-property
icalendar-define-property is a macro defined in icalendar-macs.el.gz.
Signature
(icalendar-define-property SYMBOLIC-NAME PROPERTY-NAME DOC VALUE &key DEFAULT (UNRECOGNIZED default) (DEFAULT-TYPE (if (icalendar-value-type-symbol-p value) value 'icalendar-text)) OTHER-TYPES LIST-SEP CHILD-SPEC OTHER-VALIDATOR ((:name-face NAME-FACE) 'icalendar-property-name NONDEFAULT-NAME-FACE) ((:value-face VALUE-FACE) 'icalendar-property-value NONDEFAULT-VALUE-FACE) ((:warn-face WARN-FACE) 'icalendar-warning NONDEFAULT-WARN-FACE) EXTRA-FACES LINK)
Documentation
Define iCalendar property PROPERTY-NAME under SYMBOLIC-NAME.
PROPERTY-NAME should be the property 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 the
property's value. If it is a regular expression, it is assumed
that the values are strings of type icalendar-text which match
that regular expression.
An rx regular expression named SYMBOLIC-NAME is defined to
match the property:
Group 1 of this regex matches PROPERTY-NAME.
Group 2 matches VALUE.
Group 3, if matched, contains any property value which does
*not* match VALUE, and is incorrect according to the standard.
Group 4, if matched, contains the (unparsed) property parameters;
its boundaries can be used for parsing these.
This regex matches the entire string representing this property,
from the beginning of the content line to the end of its value.
Another regular expression named SYMBOLIC-NAME-value is also
defined to match just the value part, after the separating colon,
with groups 2 and 3 as above.
A function to match the complete property expression called
icalendar-match-PROPERTY-NAME-property is defined. This
function is used to provide syntax highlighting in
icalendar-mode.
See the functions icalendar-read-property-value,
icalendar-parse-property-value, icalendar-parse-property, and
icalendar-print-property-node to convert properties 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 property is not specified in a given component.
: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.
:default-type - a type symbol naming the default type of the
property's value. If the property's value differs from this
type, an icalendar-valuetypeparam parameter will be added to
the property's syntax node and printed when the node is
printed. Default is VALUE if VALUE is a value type symbol,
otherwise the type icalendar-text.
:other-types - a list of type symbols naming value types other
than :default-type. These represent alternative types for the
property's value. If parsing the property's value under its
default type fails, these types will be tried in turn, and only
if the property's value matches none of them will an error be
signaled.
:list-sep - if the property 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 each value will be read according to VALUE
and collected into a list when parsing. When printing, the
inverse happens: values are printed individually and 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.
:child-spec - a plist mapping the following keywords to lists
of type symbols:
:one - parameters that must appear exactly once
:one-or-more - parameters that must appear at least once and
may appear more than once
:zero-or-one - parameters that must appear at most once
:zero-or-more - parameters that may appear more than once
:allow-others - if non-nil, other parameters besides those listed in
the above are allowed to appear. (In this case, a
:zero-or-more clause is redundant.)
:other-validator - a function to perform any additional validation of
the component, beyond what icalendar-ast-node-valid-p checks.
This function should accept one argument, a syntax node. It
should return non-nil if the node is valid, or signal an
icalendar-validation-error if it is not. Its name does not
need to be quoted.
:name-face - a face symbol for highlighting the property name
(default: icalendar-property-name)
:value-face - a face symbol for highlighting valid property values
(default: icalendar-property-value)
:warn-face - a face symbol for highlighting invalid property values
(default: icalendar-warning)
:extra-faces - a list of the form 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 property
Source Code
;; Defined in /usr/src/emacs/lisp/calendar/icalendar-macs.el.gz
;; Define properties:
(cl-defmacro ical:define-property (symbolic-name property-name doc value
&key default
(unrecognized default)
(default-type
(if (ical:value-type-symbol-p value)
value
'ical:text))
other-types
list-sep
child-spec
other-validator
((:name-face name-face)
'ical:property-name nondefault-name-face)
((:value-face value-face)
'ical:property-value nondefault-value-face)
((:warn-face warn-face)
'ical:warning nondefault-warn-face)
extra-faces
link)
"Define iCalendar property PROPERTY-NAME under SYMBOLIC-NAME.
PROPERTY-NAME should be the property 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 the
property's value. If it is a regular expression, it is assumed
that the values are strings of type `icalendar-text' which match
that regular expression.
An `rx' regular expression named SYMBOLIC-NAME is defined to
match the property:
Group 1 of this regex matches PROPERTY-NAME.
Group 2 matches VALUE.
Group 3, if matched, contains any property value which does
*not* match VALUE, and is incorrect according to the standard.
Group 4, if matched, contains the (unparsed) property parameters;
its boundaries can be used for parsing these.
This regex matches the entire string representing this property,
from the beginning of the content line to the end of its value.
Another regular expression named `SYMBOLIC-NAME-value' is also
defined to match just the value part, after the separating colon,
with groups 2 and 3 as above.
A function to match the complete property expression called
`icalendar-match-PROPERTY-NAME-property' is defined. This
function is used to provide syntax highlighting in
`icalendar-mode'.
See the functions `icalendar-read-property-value',
`icalendar-parse-property-value', `icalendar-parse-property', and
`icalendar-print-property-node' to convert properties 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 property is not specified in a given component.
: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.
:default-type - a type symbol naming the default type of the
property's value. If the property's value differs from this
type, an `icalendar-valuetypeparam' parameter will be added to
the property's syntax node and printed when the node is
printed. Default is VALUE if VALUE is a value type symbol,
otherwise the type `icalendar-text'.
:other-types - a list of type symbols naming value types other
than :default-type. These represent alternative types for the
property's value. If parsing the property's value under its
default type fails, these types will be tried in turn, and only
if the property's value matches none of them will an error be
signaled.
:list-sep - if the property 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 each value will be read according to VALUE
and collected into a list when parsing. When printing, the
inverse happens: values are printed individually and 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'.
:child-spec - a plist mapping the following keywords to lists
of type symbols:
:one - parameters that must appear exactly once
:one-or-more - parameters that must appear at least once and
may appear more than once
:zero-or-one - parameters that must appear at most once
:zero-or-more - parameters that may appear more than once
:allow-others - if non-nil, other parameters besides those listed in
the above are allowed to appear. (In this case, a
:zero-or-more clause is redundant.)
:other-validator - a function to perform any additional validation of
the component, beyond what `icalendar-ast-node-valid-p' checks.
This function should accept one argument, a syntax node. It
should return non-nil if the node is valid, or signal an
`icalendar-validation-error' if it is not. Its name does not
need to be quoted.
:name-face - a face symbol for highlighting the property name
(default: `icalendar-property-name')
:value-face - a face symbol for highlighting valid property values
(default: `icalendar-property-value')
:warn-face - a face symbol for highlighting invalid property values
(default: `icalendar-warning')
:extra-faces - a list of the form 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 property"
(declare (doc-string 2))
(let* (;; Value RX:
(full-value-rx-name
(intern (concat (symbol-name symbolic-name) "-property-value")))
(values-rx (when list-sep
`(seq ,value (zero-or-more ,list-sep ,value))))
;; Related functions:
(property-dname (if property-name
(downcase property-name)
(string-trim (symbol-name symbolic-name)
"icalendar-" "-property")))
(matcher-name
(intern (concat "icalendar-match-" property-dname "-property")))
(type-predicate-name
(intern (concat "icalendar-" property-dname "-property-p")))
;; Faces:
(has-faces (or nondefault-name-face nondefault-value-face
nondefault-warn-face extra-faces))
;; Documentation:
(header "It names a property type defined by `icalendar-define-property'.")
(val-list (if list-sep (concat "VAL1" list-sep "VAL2" list-sep "...")
"VAL"))
(default-doc (if default (format "The default value is: \"%s\"\n" default)
""))
(s (if list-sep "s" "")) ; to make plurals
(val-doc (concat "VAL" s " "
"must be " (unless list-sep "a ")
(format "value%s of one of the following types:\n" s)
(string-join
(cons
(format "`%s' (default)" default-type)
(mapcar (lambda (type) (format "`%s'" type))
other-types))
"\n")
default-doc))
(name-doc (if property-name "" "NAME must match rx `icalendar-name'"))
(syntax-doc (format "Syntax: %s[;PARAM...]:%s\n%s\n%s\n"
(or property-name "NAME") val-list name-doc val-doc))
(child-doc
(concat
"The following parameters are required or allowed\n"
"as children in syntax nodes of this type:\n\n"
(ical:format-child-spec child-spec)
(when (plist-get child-spec :allow-others)
"\nOther parameters of any type are also allowed.\n")))
(full-doc (concat header "\n\n" doc "\n\n" syntax-doc "\n\n" child-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-property t
'ical:matcher (function ,matcher-name)
'ical:default-value ,default
'ical:default-type (quote ,default-type)
'ical:other-types (quote ,other-types)
'ical:list-sep ,list-sep
'ical:substitute-value ,unrecognized
'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:child-spec (quote ,child-spec)
'ical:other-validator (function ,other-validator)
'ical:type-documentation ,full-doc
'ical:link ,link)))
;; Value regex which matches:
;; Group 2: correct values of the property, and
;; Group 3: incorrect values up to end-of-line (for syntax warnings)
(rx-define ,full-value-rx-name
(or (group-n 2 ,(or values-rx value))
(group-n 3 (zero-or-more not-newline))))
;; Full property regex which matches:
;; Group 1: the property name,
;; Group 2: correct values of the property, and
;; Group 3: incorrect values up to end-of-line (for syntax warnings)
(rx-define ,symbolic-name
(seq line-start
(group-n 1 ,(or property-name 'ical:name))
(group-n 4 (zero-or-more ical:other-param-safe))
":"
,full-value-rx-name
line-end))
;; Matcher:
(defun ,matcher-name (limit)
,(concat (format "Matcher for `%s' property.\n" symbolic-name)
"(Defined by icalendar-define-property.)")
(re-search-forward (rx ,symbolic-name) limit t))
;; CL-type to represent syntax nodes for this property:
(defun ,type-predicate-name (node)
,(format "Return non-nil if NODE represents a %s property." property-name)
(and (ical:ast-node-p node)
(eq (ical:ast-node-type node) (quote ,symbolic-name))))
(cl-deftype ,symbolic-name () '(satisfies ,type-predicate-name))
;; Associate the print name with the type symbol for
;; `icalendar-parse-property', `icalendar-print-property-node', etc.:
(when ,property-name
(push (cons ,property-name (quote ,symbolic-name)) ical:property-types))
;; Generate an 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)))))