Documentation
Define a new tag.
ATTRIBUTES should be an attribute-spec (see parse-attributes and
attribute-bind).
BODY is simply the body of the expander lambda.
Within the BODY the functions EMIT-CODE, EMIT-PRINC and EMIT-HTML can
be used to generate code. EMIT-CODE should be passed lisp code which
will be executed at runtime.
Source
(defmacro deftag (name attributes &body body)
"Define a new tag.
ATTRIBUTES should be an attribute-spec (see parse-attributes and
attribute-bind).
BODY is simply the body of the expander lambda.
Within the BODY the functions EMIT-CODE, EMIT-PRINC and EMIT-HTML can
be used to generate code. EMIT-CODE should be passed lisp code which
will be executed at runtime."
(with-unique-names (contents)
`(progn
(setf (gethash ',name *expanders*)
(lambda (,contents)
(handler-bind ((tag-related-error (lambda (c)
(setf (tag c) ,contents))))
(attribute-bind ,attributes ,contents
,@body))))
(defmacro ,name (&rest contents)
(let ((%yaclml-code% nil)
(%yaclml-indentation-depth% 0))
;; build tag's body
(funcall (gethash ',name *expanders*) contents)
(setf %yaclml-code% (nreverse %yaclml-code%))
;; now that we've generated the code we can fold the
;; strings in yaclml-code and princ them, leaving any other
;; forms as they are.
`(progn ,@(mapcar (lambda (form)
(if (stringp form)
`(write-string ,form *yaclml-stream*)
form))
(fold-strings %yaclml-code%))
(values)))))))Source Context