[cl-who-devel] Macroexpansion of with-html-output body?

Below is the message I've sent today to Edi Weitz on this topic. Unfortunately, I've missed the existence of this mailing-list, that's why I didn't consult the archives. Today I have quickly pierced the discussion and, as far as I've seen, the solution, I propose, hadn't being mentioned. So, I suggest an implementation strategy for the macroexpansion inside with-html-output and provide a patch against the current version (0.11.1)... I tried to use CL-WHO a couple of times in the past and always stumbled over the fact, that it's possible to do something like that (example from the site): (with-html-output (*http-stream*) (:table :border 0 :cellpadding 4 (loop for i below 25 by 5 do (htm (:tr :align "right" (loop for j from i below (+ i 5) do (htm (:td :bgcolor (if (oddp j) "pink" "green") (fmt "~@R" (1+ j)))))))))) ...but not something like this (i.e. make a macro, to compress some of the pseudo-html tree): (with-html-output (*http-stream*) (:table :border 0 :cellpadding 4 (loop for i below 25 by 5 do (htm (:tr :align "right" (loop for j from i below (+ i 5) do (htm (embed-td j)))))))) (defmacro embed-td (j) `(:td :bgcolor (if (oddp ,j) "pink" "green") (fmt "~@R" (1+ ,j)))) Thus to write such a macro for with-htm-output you should do it in two steps (at least, this is the only way I have discovered): The original form should be like the following (with STR): (with-html-output (*http-stream*) (:table :border 0 :cellpadding 4 (loop for i below 25 by 5 do (htm (:tr :align "right" (loop for j from i below (+ i 5) do (STR (embed-td j)))))))) ...and the macro should itself use w-h-o-to-string: (defmacro embed-td (j) (let ((str (gensym))) `(with-html-output-to-string (,str) (:td :bgcolor (if (oddp ,j) "pink" "green") (fmt "~@R" (1+ ,j)))))) I think it's quite a common case in the usage of the w-h-o macro to want such macros (at least for me it always comes up). So I suggest to add another keyword to a list of STR, ESC and HTM -- EMB -- specially for such cases, which will mean "macroexpand-1 the enclosed form". With it the above code may be expressed like: (with-html-output (*http-stream*) (:table :border 0 :cellpadding 4 (loop for i below 25 by 5 do (htm (:tr :align "right" (loop for j from i below (+ i 5) do (htm (emb (embed-td j))))))))) (defmacro embed-td (j) `(:td :bgcolor (if (oddp ,j) "pink" "green") (fmt "~@R" (1+ ,j)))) or like this: (with-html-output (*http-stream*) (:table :border 0 :cellpadding 4 (loop for i below 25 by 5 do (htm (:tr :align "right" (emb (embed-tr i))))))) (defmacro embed-tr (i) (let ((j (gensym))) `(loop for ,j from ,i below (+ ,i 5) do (htm (:td :bgcolor (if (oddp ,j) "pink" "green") (fmt "~@R" (1+ ,j)))))) I think, sometimes such flexibility is necessary. Although, I'm not absolutely sure, that the solution, I've hacked, is flawless... The patch is attached. I tried to follow the guidelines for patches with this one. The only thing, that I didn't do, is provide examples of the usage of EMB keyword in the doc (only a brief reference). I think, that the examples in the letter might suit, but I'm not sure. Best regards, Vsevolod Dyomkin
participants (1)
-
Vsevolod