aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/ref/general.texi8
-rw-r--r--doc/ref/general/data-formats.texi25
-rw-r--r--doc/ref/general/data-stores.texi36
-rw-r--r--doc/ref/general/lens.texi47
-rw-r--r--doc/ref/general/sxml.texi100
-rw-r--r--doc/ref/general/util-object.texi86
-rw-r--r--doc/ref/general/util-path.texi8
-rw-r--r--doc/ref/general/util-type.texi62
-rw-r--r--doc/ref/general/util.texi16
-rw-r--r--doc/ref/general/webdav.texi301
-rw-r--r--doc/ref/vcomponent.texi41
11 files changed, 727 insertions, 3 deletions
diff --git a/doc/ref/general.texi b/doc/ref/general.texi
index d33975ed..b97dece0 100644
--- a/doc/ref/general.texi
+++ b/doc/ref/general.texi
@@ -21,3 +21,11 @@ of these should be generally useful in any project.
@include general/crypto.texi
@include general/graph.texi
@include general/options.texi
+
+
+@include general/util-type.texi
+@include general/util-object.texi
+@include general/lens.texi
+@include general/data-formats.texi
+@include general/data-stores.texi
+@include general/webdav.texi
diff --git a/doc/ref/general/data-formats.texi b/doc/ref/general/data-formats.texi
new file mode 100644
index 00000000..037d3ae7
--- /dev/null
+++ b/doc/ref/general/data-formats.texi
@@ -0,0 +1,25 @@
+@node Data Formats
+@section Data Formats
+A data format is some way that an individual event may get serialized
+to disk. The default is iCalendar (TODO reference RFC 5545), but
+others might be available (TODO footnote and reference xcal).
+
+Each available format should be included as
+@code{(vcomponent formats @var{format-name})}.
+Which module corresponds to what file type is currently defined out of band.
+
+Each module should expose the following procedures.
+
+@defun serialize component port
+Write a serialized representation of @var{component} to @var{port}.
+@end defun
+
+@defun deserialize port
+Read a serialized representation of a component from @var{port}, and
+return the deserialized instance of this object.
+@end defun
+
+@subsection iCalendar
+RFC 5545
+
+@subsection xCal
diff --git a/doc/ref/general/data-stores.texi b/doc/ref/general/data-stores.texi
new file mode 100644
index 00000000..ec3962da
--- /dev/null
+++ b/doc/ref/general/data-stores.texi
@@ -0,0 +1,36 @@
+@node Data Stores
+@section Data Stores
+Data stores are persistant stores for events, such as databases or the
+file system. Each data store can support any number of data formats,
+but which is an implementation detail of that format and shouldn't be
+needed information from the high level view.
+@footnote{It is however important for interoperability with other programs}.
+
+@c (make <calendar-store> #:path ``hello'')
+
+@defun path store
+@end defun
+
+@deftp {GOOPS method} get-calendar this
+Returns a vcomponent object of type @code{VCALENDAR}. Should contain
+all @code{VEVENT} components of this calendar.
+@end deftp
+
+@deftp {GOOPS method} get-by-uid this uid
+Return the event object with UID equal to the string @var{uid}.
+@end deftp
+
+@deftp {GOOPS method} queue-save this event
+Queue a save event of @var{event} to the store.
+@end deftp
+
+@deftp {GOOPS method} flush this
+Force write of all queued actions.
+@end deftp
+
+@subsection VDir
+[VDIR]: http://vdirsyncer.pimutils.org/en/latest/vdir.html
+
+@subsection File
+
+@subsection SQLite
diff --git a/doc/ref/general/lens.texi b/doc/ref/general/lens.texi
new file mode 100644
index 00000000..eeddd6ca
--- /dev/null
+++ b/doc/ref/general/lens.texi
@@ -0,0 +1,47 @@
+@node Lenses
+@section Lenses
+
+Provided by the module @code{(hnh util lens)}
+
+@defun modify object lens f args ...
+@end defun
+
+@defmac modify* object lens
+@defmacx modify* object lens rest ...
+@end defmac
+
+@defmac set object lenses ... value
+@end defmac
+
+@defmac get object lenses ...
+@end defmac
+
+
+@defun make-lens getter setter
+@end defun
+
+@defmac build-lens getter setter
+Where any of getter or setter can either be a single symbol, or a list.
+@end defmac
+
+@deftp {Scheme Lens} identity-lens
+@end deftp
+
+@defun compose-lenses lenses ...
+@defunx lens-compose lenses ...
+Lenses composes left to right, so earlier lenses in @var{lenses} are
+applied earlier.
+@end defun
+
+@deftp {Scheme Lens} ref idx
+Focuses the element at index @var{idx} in a list.
+@end deftp
+
+@deftp {Scheme Lens} car*
+@deftp {Scheme Lens} cdr*
+Focuses the first or second element of a pair.
+@end deftp
+
+@defun each object lens proc
+@end defun
+
diff --git a/doc/ref/general/sxml.texi b/doc/ref/general/sxml.texi
new file mode 100644
index 00000000..dd635b4c
--- /dev/null
+++ b/doc/ref/general/sxml.texi
@@ -0,0 +1,100 @@
+@node sxml namespaced
+@section Namespaced SXML
+
+Namespaces is a variant to ``regular'' SXML. Difference being that
+instead of representing XML-tags as symbols, they are instead actual
+objects.
+
+For example
+@example
+`(a (b "Content"))
+@end example
+
+Would be represented as
+@example
+`(,(xml 'a)
+ (,(xml 'b)
+ "Content"))
+@end example
+
+@defun namespaced-sxml->sxml tree [namespace-prefixes='()]
+Takes a tree of namespaced-sxml, and optionally an assoc list from
+namespace symbols, to prefered prefix.
+
+Returns a sxml tree, with xmlns:<prefix>=namespace attributes
+@end defun
+
+@defun namespaced-sxml->xml tree [namespaces='()] [port='(current-output-port)]
+Serializes the namespaced sxml tree to port. @var{namespaces} should
+be an association list from namespace symbols, to prefered prefixes.
+@end defun
+
+@defun namespaced-sxml->sxml/namespaces tree [namespace-prefixes='()]
+Returns two values:
+@itemize
+@item An SXML tree (which doesn't have namespace attributes)
+@item an association list from namespace symbols, to used prefixes.
+@end itemize
+@end defun
+
+@c xml->namespcaed-sxml and sxml->namespaced-sxml don't share
+@c implementation, despite doing almost the same thing. This is since
+@c xml->namespaced-sxml directly uses the ssax parser, giving us great
+@c controll, while sxml->namespaced-sxml attempt to look at symbols.
+
+@defun xml->namespaced-sxml port-or-string
+Reads xml from port, and return a namespaced SXML tree.
+@end defun
+
+@defun sxml->namespaced-sxml tree namespaces
+Converts a ``regular'' SXML tree into a namespaced sxml tree.
+@var{namespaces} must be an association list which maps each prefix
+used in @var{tree} onto a full XML namespace.
+
+The key @code{#f} can be used to map non-namespaced elements into a
+namespace.
+@end defun
+
+@defun xml tag
+@defunx xml ns tag [attrs]
+@anchor{xml-tag}
+ A single XML element, suitable to go as the car of a list to
+ create a full object.
+
+ @var{xml} is a shorthand to @code{make-xml-element}, which
+ either takes just a tag (for non-namespaced elements), or a
+ namespace, a tag, and a list of attributes.
+
+ @itemize
+ @item @var{tag} should be a symbol.
+ @item @var{ns} should be a symbol.
+ @item @var{attrs} should be a hash table.
+ @end itemize
+
+ @defun make-xml-element tagname namespace attributes
+ @end defun
+
+ @defun xml-element? x
+ @end defun
+
+ @defun xml-element-tagname el
+ @end defun
+
+ @defun xml-element-namespace el
+ @end defun
+
+ @defun xml-element-attributes el
+ @end defun
+@end defun
+
+
+@defun make-pi-element tag body
+ @defun pi-element? x
+ @end defun
+
+ @defun pi-tag pi
+ @end defun
+
+ @defun pi-body pi
+ @end defun
+@end defun
diff --git a/doc/ref/general/util-object.texi b/doc/ref/general/util-object.texi
new file mode 100644
index 00000000..ceac2f2a
--- /dev/null
+++ b/doc/ref/general/util-object.texi
@@ -0,0 +1,86 @@
+@node define-type
+@section Yet Another Object System
+
+@defmac define-type (name type-parameters ...) fields ...
+Introduce a new type.
+
+Each field is either a symbol, or a list where the first element is a
+symbol, and the remaining elements are alternating keywords and
+values, as per @ref{Field Parameters}. All fields are optional by
+default, but can be made non-optional through its type parameter.
+
+The example below creates a new type called @var{type}, with a custom
+printer which always displays the string ``TYPE''. It has two fields,
+@var{x}, which must be an integer, and @var{y}, which can have any
+type, but gets the value ``Hello'' in none is given.
+@example
+(define-type (type #:printer (lambda (r p) (display "TYPE" p)))
+ (x #:type integer?)
+ (y #:default "Hello"))
+@end example
+@end defmac
+
+@subsection Type Parameters
+
+@deffn {Type Parameter} constructor (λ (primitive-constructor type-validator))
+Use a custom constructor for the type. The given procedure is called
+with two values:
+@itemize
+@item the types primitive (and usually hidden) constructor,
+which takes as many arguments as there are fields, in the order given
+in define-type, and
+@item the type validator procedure, which also takes all arguments,
+but instead either returns an undefined value if everything is fine,
+or throws @code{'wrong-type-arg} otherwise.
+@end itemize
+The procedure should then return a new procedure, which will be bound
+as the constructor for the type. Note that default values are current
+disregarded with custom constructors.
+
+A custom constructor for the type above might look like
+@example
+(lambda (primitive-constructor type-check)
+ (lambda* (#:key x y)
+ (type-check x y)
+ (primitive-constructor x y)))
+@end example
+@end deffn
+
+@deffn {Type Parameter} printer (λ (record port))
+Use a custom printer for the type.
+@end deffn
+
+@subsection Field Parameters
+@anchor{Field Parameters}
+
+@deffn {Field Parameter} default value
+Value the field should get if not given.
+@end deffn
+
+@deffn {Field Parameter} type type-clause
+A type predicate that the field must obey. See @ref{type-clause} for details.
+@end deffn
+
+@subsection Introduced Bindings
+
+Define type introduces a number procedures. (@var{<name>} should be
+replaced with whatever was given as @var{name} to define-type.
+
+@defun @var{<name>} [kv-args ...]
+Type constructor. Takes key-value arguments. Where the keys are the
+names of the fields.
+@end defun
+
+@defun @var{<name>}? x
+Type predicate.
+@end defun
+
+And for each field @var{<field>}:
+
+@defun @var{<field>} object [value]
+Accessor for the given filed.
+Returns the current value if called with only an object, and returns a
+new object with @var{field} set to @var{value} if called with two values.
+
+The updating version checks the type if #:type was given on creation.
+@end defun
diff --git a/doc/ref/general/util-path.texi b/doc/ref/general/util-path.texi
index 9c1da19b..ba78a828 100644
--- a/doc/ref/general/util-path.texi
+++ b/doc/ref/general/util-path.texi
@@ -41,7 +41,13 @@ The first component will be @code{""} if path is absolute.
@defun filename-extension filename
-Returns the extension of the filename, or the empty string if none exists.
+Returns the extension of the filename without a leading period, or the
+empty string if none exists.
+
+@example
+(filename-extension "file.tar.gz")
+⇒ "gz"
+@end example
@end defun
@defun realpath path
diff --git a/doc/ref/general/util-type.texi b/doc/ref/general/util-type.texi
new file mode 100644
index 00000000..104b00b3
--- /dev/null
+++ b/doc/ref/general/util-type.texi
@@ -0,0 +1,62 @@
+@node Type utilities
+@section Type utilities
+
+Provided by the module @code{(hnh util type)}
+
+@subsection Type Clauses
+@anchor{type-clause}
+@cindex type-clause
+
+Type clauses are an effective way of writing compound predicates
+without explicitly mentioning the variable at all steps.
+
+The simplest type predicate is a single symbol, which is directly
+called on the object:
+@example
+predicate? ⇒ (predicate? x)
+@end example
+
+Otherwise, if the predicate is a list then the variable is spliced
+into the argument list in the first position:
+@example
+(proc args ...) ⇒ (proc x args ...)
+@end example
+
+The two primitives @code{and} and @code{or} are also available, which
+both take an arbitrary number of predicates, and calls them in order,
+with Scheme's usual short-circuiting rules.
+@footnote{@code{and} and @code{or} doesn't have to be primitives, but
+we would otherwise have one hell of a namespace conflict}
+
+@defmac list-of variable type-clause
+Checks if @var{variable} is a list, and that every element satisfies type-clause.
+@end defmac
+
+@defmac pair-of variable car-type-clause cdr-type-clause
+Check if @var{variable} is a cons-pair, and that the car satisfies
+@var{car-type-clause}, and that the cdr satisfies @var{cdr-type-clause}.
+@end defmac
+
+@subsection Deffinitions
+
+@defmac build-validator-body variable type-clause
+``Entry point'' of type clauses. Inserts variable into the
+type-clause, returning something ready to be passed along the eval (or
+rather, spliced into another macro).
+
+Also used if new ``primitives'' are to be added, such as list-of.
+@end defmac
+
+@defmac typecheck variable type-clause [procedure-name=(current-procedure-name)]
+Checks @var{variable} against @var{type-clause}, and raises
+@code{'wrong-type-argument} if it fails. @var{procedure-name} is used
+as the calling procedure for @code{scm-error}.
+
+Useful at the start of procedures.
+@end defmac
+
+
+@defmac current-procedure-name
+Returns the current procedure name as a symbol, or @code{#f} if not found.
+@end defmac
+
diff --git a/doc/ref/general/util.texi b/doc/ref/general/util.texi
index a85ff661..1d6a4e7a 100644
--- a/doc/ref/general/util.texi
+++ b/doc/ref/general/util.texi
@@ -127,6 +127,11 @@ See @var{find-extreme}
@end lisp
@end defun
+@defun init+last list
+Returns two values: everything except the last element of @var{list},
+and the last element of @var{list}.
+@end defun
+
@defun take-to lst n
Equivalent to @var{take}, but return everything (instead of crash) if
n > (length lst).
@@ -235,7 +240,9 @@ list, whose indices matches the order of the inputs
@end defun
@defun string-flatten tree
-@c TODO document me
+Given an arbitary tree, do a pre-order traversal, appending all strings.
+
+Non-strings are converted to strings, and also appended.
@end defun
@defun intersperse item list
@@ -243,7 +250,7 @@ Inserts @var{item} between each element in @var{list}.
@end defun
-@defun insert-ordered item collection [<=<]
+@defun insert-ordered item collection [<]
Inserts @var{item} into @var{collection}, such that collection
remainins sorted if it was sorted beforehand.
@end defun
@@ -334,6 +341,11 @@ A variable can also be removed from the environment, by setting its
value to @code{#f}.
@end defmac
+@defmac with-locale1 category locale thunk
+Run @var{thunk} with the locale @var{category} temporarily set to
+@var{locale}.
+@end defmac
+
@defmac catch* thunk (symbol proc) ...
Macro allowing multiple exception types to be caught. Each (symbol
proc) pair expands to a regular @code{catch}, with the leftmost being
diff --git a/doc/ref/general/webdav.texi b/doc/ref/general/webdav.texi
new file mode 100644
index 00000000..a495c945
--- /dev/null
+++ b/doc/ref/general/webdav.texi
@@ -0,0 +1,301 @@
+@node WebDAV
+@section WebDAV
+
+For a complete view of WebDAV, please see @cite{RFC4918 (HTTP
+Extensions for Web Distributed Authoring and Versioning (WebDAV))},
+but in short, and specifc for this implementation.
+
+A DAV tree consists of resources, which are analogous to files and
+directories. A resource is referenced by its href.
+
+Each resources is either a collection and have children, or have
+content. Parts of this implementation allows a collection to also have
+contents, while other does not. The standard doesn't seem to mind
+either way.
+
+Each resource also has a set of properties, modelling metadata and
+extra data about the resource.
+
+@emph{href}'s are internally represented as lists of strings, where the
+root element ``/'' is an empty list, and all other cases are mapped
+like:
+@example
+"/a/b" ⇒ '("a" "b")
+@end example
+
+@emph{resources} are GOOPS objects, which the base class
+@code{<resource>}.
+
+The user (of the library) is assumed to designate one resource
+instance as the root of the resource tree. All other resources are
+then added as (grand-)children to that resource. Each resource has a
+field @var{name}, which is the normative name used when searching by
+name in the tree@footnote{This means that one resource can't easily
+exist at multiple points in the tree}.
+
+@emph{properties} are split into live and dead properties, where live
+properties have extra handling by the server, while dead properties
+are simply carried along after the end-user put them on a resource.
+
+Live properties are handled through GOOPS methods.
+
+Dead properties are (by default) stored directly inside each resource.
+
+@node WebDAV Properties
+@subsection Properties
+
+@itemize
+@item @code{(calp webdav property)}
+@item @code{(calp webdav propfind)}
+@end itemize
+
+@subsubsection Default Live Properties
+
+@deftp {GOOPS method} creationdate
+@end deftp
+
+@deftp {GOOPS method} displayname
+@end deftp
+
+@deftp {GOOPS method} getcontentlanguage
+@end deftp
+
+@deftp {GOOPS method} getcontentlength
+@end deftp
+
+@deftp {GOOPS method} getcontenttype
+@end deftp
+
+@deftp {GOOPS method} getetag
+@end deftp
+
+@deftp {GOOPS method} getlastmodified
+@end deftp
+
+@deftp {GOOPS method} lockdiscovery
+@end deftp
+
+@deftp {GOOPS method} resourcetype
+@end deftp
+
+@deftp {GOOPS method} supportedlock
+@end deftp
+
+
+@node WebDAV Resources
+@subsection Resources
+
+@deftp {GOOPS class} <resource>
+Base type for all WebDAV resources.
+
+The base class shouldn't be directly instanciated.
+
+ @defun resource? x
+ Is the given object a <resource>, or decendant?
+ @end defun
+@end deftp
+
+@deftp {GOOPS method} name resource
+The name of a resource is the local part of a href.
+@end deftp
+
+@deftp {GOOPS method} children resource
+All direct children of a resource, as a list.
+@end deftp
+
+@defun add-child! parent child [#:overwrite?] [#:collection?=(is-collection? child)]
+Adds a resource as a child of another resource.
+
+Before adding the resource to the parents child set,
+@code{(setup-new-resource! child parent)} is called. If
+@var{collection?} is true, then
+@code{(setup-new-collection! child parent)} is also called.
+
+If @var{overwrite?} is present, then the parent will be checked for a
+child which already has that name, and take action accordingly.
+It will return one of: @code{'replaced} if a resource already existed
+with that name, but it has been replaced, @code{'collision}, if the
+old one was kept, and @code{'created} if the new resource was added
+without collisions.
+
+If @var{overwrite?} is absent then the method always returns @var{'created}.
+@end defun
+
+@defun add-resource! resource name content
+Creates a new resource with the given name, and make it a child of
+@var{self}. Setting its initial content to @var{content}.
+
+Calls @code{add-resource!}, so the same book-keeping procedures are called.
+@c TODO Document throw
+@c TODO Document return
+@end defun
+
+@defun add-collection! resource name
+Similar to @code{add-resource!} but the created resource is instead a collection.
+@end defun
+
+@deftp {GOOPS method} setup-new-resource! (self <resource>) (parent <resource>)
+Book-keeping procedure called by @code{add-resource!} on @emph{all}
+added resources.
+
+Base implementation in a no-op.
+@end deftp
+
+@deftp {GOOPS method} setup-new-collection! (self <resource>) (parent <resource>)
+Book-keeping procedure called by @code{add-resource!} if
+@var{collection?} is true.
+
+Base implementation is a no-op.
+@end deftp
+
+@deftp {GOOPS method} is-collection? resource
+Is the given resource a collection.
+
+The base implementation simply checks if the resource has any children.
+@end deftp
+
+@deftp {GOOPS method} content resource
+@deftpx {GOOPS method} set-content! resource content
+Get and set the content of a given resource. @var{content}s type can
+be anything that the given resource type accepts. Overrides of this
+procedure should preferably save its contents properly.
+@end deftp
+
+@c
+
+@defun get-property resource xml-tag
+@defunx get-live-property resource xml-tag
+@defunx get-dead-property resource xml-tag
+@end defun
+
+
+@defun set-property resource xml-el
+@defunx set-property! resource xml-el
+@defunx set-dead-property resource xml-el
+@defunx set-dead-property! resource xml-el
+@defunx set-live-property resource xml-el
+@defunx set-live-property! resource xml-el
+@end defun
+
+
+@defun remove-property resource xml-tag
+@defunx remove-property! resource xml-tag
+@defunx remove-dead-property resource xml-tag
+@defunx remove-dead-property! resource xml-tag
+@defunx remove-live-property resource xml-tag
+@defunx remove-live-property! resource xml-tag
+@end defun
+
+@c
+
+@deftp {GOOPS method} copy-resource (resource <resource>) include-children? [name]
+Create a new resource which looks as similar as possible to the given
+resource. The new resource will have the same (GOOPS) class as the
+source, displayname, contentlanguage and all dead properties are
+transfered, other live properties are currently not explicitly
+transfered (but probably still transfered implicitly).
+
+The new resources name is @var{name} if given, and the name of the
+original resource otherwise.
+
+If @var{include-children?} is true then a deep copy is performed,
+otherwise no children are copied, and the resulting resource will be a
+leaf node.
+
+Content is copied verbatim.
+
+@b{NOTE} currently no helper method is called, which means that extra
+resources held by the resource object can't be copied.
+For example, FILE can't create a copy (but it also shouldn't do that
+here, but rathen when the element is ``mounted'' into the tree).
+@end deftp
+
+@c
+
+@defun lookup-resource root-resource path
+@end defun
+
+
+@defun all-resources-under resource [prefix='()]
+Returns the given resource, and all its children in a flat list.
+
+Currently depth first, but that might change.
+The root resource is however guaranteed to be first.
+@end defun
+
+@c
+
+@c TODO
+ make-live-property
+ live-property?
+ property-getter
+
+ property-setter-generator
+ property-remover-generator
+
+ prepare-update-properties
+
+ live-properties
+ dead-properties
+
+ webdav-properties
+
+
+@node WebDAV Resource Types
+@subsection Resource Types
+
+@subsubsection @code{(calp webdav resource base)}
+
+Implementation of @code{(calp webdav resource)}. Exists to possibly
+avoid dependency loops.
+
+@subsubsection @code{(calp webdav resource calendar)}
+@subsubsection @code{(calp webdav resource file)}
+
+Resources backed by the file system.
+
+@defun file-resource? x
+@end defun
+
+@deftp {GOOPS method} children <file-resource>
+@end deftp
+
+@deftp {GOOPS method} is-collection? <file-resource>
+@end deftp
+
+@deftp {GOOPS method} creationdate <file-resource>
+Retrived directly from the file through @command{stat -c %W $@{filename@}}.
+@end deftp
+
+@deftp {GOOPS method} content <file-resource>
+@deftpx {GOOPS method} set-content! <file-resource> data
+Directly interfaced with the file.
+
+Data can't be retrieved for collections, and will always be
+returned as a bytevector for non-collections.
+
+Data can be set either as a string or a bytevector. When a string is
+used Guile's current encoding will be used.
+@end deftp
+
+@subsubsection @code{(calp webdav resource virtual)}
+
+@node WebDAV Utilities
+@subsection Utilities
+@defun xml-element-hash-key xml-tag
+Given an xml tag object @ref{xml-tag}, return a suitable key for
+@code{hash-ref} and family.
+
+These key objects should preferably not be carried around for
+long. Prefer to keep the @emph{real} xml-tag object, and only call
+this while directly referencing the hash table.
+@end defun
+
+@defun href->string href
+HREF's are represented as lists of strings. The root resource (``/'')
+is the empty list.
+@end defun
+
+@defun string->href string
+Return a href list back into a string. A leading slash will always be added.
+@end defun
diff --git a/doc/ref/vcomponent.texi b/doc/ref/vcomponent.texi
index dac47348..d0e032b3 100644
--- a/doc/ref/vcomponent.texi
+++ b/doc/ref/vcomponent.texi
@@ -113,6 +113,8 @@ Curried version of @var{prop}.
@end deftp
@defun copy-vcomponent vcomponent
+Creates a shallow copy of @var{vcomponent}. If the source object has a
+parent, then than parent adopts the new event also.
@end defun
@@ -122,3 +124,42 @@ Does symbol start with ``X-''?
@defun internal-field? symb [prefix="-"]
@end defun
+
+@node VComponent Create
+@section (vcomponent create)
+
+Procedures for declarativly creating components (instead of the
+primitive procedural API).
+
+@defun vcomponent type [key: prop] ... children
+Creates a new vcomponent of @var{type}. Each kv-pair should contain a
+keyword @var{key}, and a value which is either a direct value, or the
+return value of @code{with-parameters} or
+@code{as-list}. @var{children} should be a list of other vcomponent's.
+@end defun
+
+@defun vcalendar
+@defunx vevent
+@defunx vtimezone
+@defunx standard
+@defunx daylight
+Calls @code{vcomponent}, with type set to the procedure name (but
+up-cased).
+@end defun
+
+@defun with-parameters [key: param] ... value
+Allows setting parameters for a property as created by @code{vcomponent}.
+
+@var{value} follows the same rules as in @code{vcomponent}. Multiple
+@var{key}, @var{value} pairs can be given, where each key must be a keyword.
+@end defun
+
+@defun as-list lst
+Allows setting list values when using @code{vcomponent}.
+
+Without this a list value would be stored as a single value, while
+with this a list of values is instead stored (as, for example, in EXDATE).
+
+A list of list types could be hard-coded, but even then this procedure
+is needed since custom types might need it.
+@end defun