Hi,
While using CL-WHO recently, I ran into a small problem wherein some
tagnames/attributes could be determined only at runtime. Not knowing any
easy way to do this "out of the box" in CL-WHO, I wrote this small macro
(inspired by XML-EMITTER:WITH-TAG) -
(defmacro with-html-tag ((name &optional attributes) &body body)
(let ((body-fn (gensym)))
`(flet ((,body-fn () ,@body))
(call-with-html-tag ,name ,attributes #',body-fn))))
(defun call-with-html-tag (name attributes body-fn)
(let ((tag-name (typecase name
(symbol (string-downcase name))
(t name))))
(format t "<~A" tag-name)
(when attributes
(format t "~{~A~}" (cl-who:convert-attributes attributes)))
(format t ">")
(funcall body-fn)
(format t "</~A>" tag-name)))
Note that it writes only to *standard-output*.
Usage
-----
(defvar *x* :blockquote) => *X*
(with-output-to-string (*standard-output*)
(cl-who:with-html-output (*standard-output*)
(:body
(with-html-tag (*x*)
(cl-who:htm (:p "foo bar"))))))
=>
"<body><blockquote><p>foo bar</p></blockquote></body>"
(with-output-to-string (*standard-output*)
(cl-who:with-html-output (*standard-output*)
(:body
(with-html-tag (*x* '(("id" . "foo123")))
(cl-who:htm (:p "foo bar"))))))
=>
"<body><blockquote id='foo123'><p>foo bar</p></blockquote></body>"
I think this will be a useful addition to CL-WHO (although this
particular implementation can be improved a bit). Or did I miss out on
some other way that CL-WHO can easily handle this?
Chaitanya