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

Victor Kryukov victor.kryukov at gmail.com
Sun Feb 10 06:44:33 UTC 2008


Jeff Cunningham <jeffrey at cunningham.net> writes:

> Edi Weitz wrote:
>> On Sat, 2 Feb 2008 15:18:09 -0600, "Eli Naeher" <enaeher at gmail.com> wrote:
>>
>>   
>>> It seems like it would be nice to expand any macros detected while
>>> walking the tree of the w-h-o body. This would allow users to define
>>> their own pseudo-tags a little more flexibly than is possible with
>>> convert-tag-to-string-list. In particular, it would allow the user
>>> to create a tag which modifies its body (as a tree) even when that
>>> body contains the expansion of another user-defined tag. I don't
>>> believe this is currently possible, as this hypothetical outer tag
>>> would have access only to the HTML strings returned by the
>>> convert-tag-to-string-list specialized on the inner tag and not to
>>> the relevant s-expressions.
>>>
>>
>> Modifying CL-WHO's internals to allow this is on my todo list, but
>> there are a lot more things on this list, so the chances of me doing
>> this myself in the near future are not very big.  So, if someone wants
>> to do this, I'm all for it.  Please read this first, though:
>>
>>   http://weitz.de/patches.html
>>
>> In the case of CL-WHO I'd think that backwards compatibility would be
>> pretty important.
>>
>> Edi.
>>   
> I also like the idea.
> And as I have tens of thousands of lines of cl-who code in operation,
> I emphatically vote for backwards compatibility.

Below is my attempt to implement macroexpansion capability in
with-html-output body. Before sending it formally as a patch I want to
get your feedback on the implementation and also ask for some testing.

The idea is simple: we define new special variable *MACRO-TO-EXPAND*
which stores names of all the macros that should be expanded before
with-html-output comes into play. Notice that specail forms 'htm',
'esc', 'str' and 'fmt' are no exception here, and may be defined as
similar macros. That simplifies code of TREE-TO-TEMPLATE,
TREE-TO-COMMANDS-AUX and TREE-TO-COMMANDS significantly.

Below[1] is an example of how we're using this functionality.
def-syntax-macro is a syntactic sugar that defines a normal macro and
also adds its name to *MACRO-TO-EXPAND*

(defpackage :cl-who-example
  (:use :cl :cl-who))

(in-package :cl-who-example)

(cl-who::def-syntax-macro html-list (&body body)
  `(:ul
    ,@(loop
	 for elem in body
	 collect `(:li ,elem))))

(with-html-output-to-string (s)
  (:html
   (:title "Title"))
  (:body
   (:h1 "H1 header")
   (:p "A small list"
       (html-list
	"First"
	"Second"
	(:a :href "/link" "Third")))))

=> "<html><title>Title</title></html><body><h1>H1 header</h1><p>A small list<ul><li>First</li><li>Second</li><li><a href='/link'>Third</a></li></ul></p></body>"

To test new functionality, simply load the code in who1.lisp[2] after you
load CL-WHO - that will allow you to keep the original CL-WHO intact.

I'm also attaching very simple test to check that we haven't braken
things at least for the three examples advertised on CL-WHO web page.

Please let me know your feedback,

Victor.

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: who1.lisp
URL: <https://mailman.common-lisp.net/pipermail/cl-who-devel/attachments/20080210/7e485435/attachment.ksh>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: cl-who-example.lisp
URL: <https://mailman.common-lisp.net/pipermail/cl-who-devel/attachments/20080210/7e485435/attachment-0001.ksh>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: cl-who-test.lisp
URL: <https://mailman.common-lisp.net/pipermail/cl-who-devel/attachments/20080210/7e485435/attachment-0002.ksh>
-------------- next part --------------
;;; -*- mode: lisp; -*-

(with-html-output-to-string (http-stream)
    (loop for (link . title) in '(("http://zappa.com/" . "Frank Zappa")
				  ("http://marcusmiller.com/" . "Marcus Miller")
				  ("http://www.milesdavis.com/" . "Miles Davis"))
       do (htm (:a :href link
		   (:b (str title)))
	       :br)))

"<a href='http://zappa.com/'><b>Frank Zappa</b></a><br /><a href='http://marcusmiller.com/'><b>Marcus Miller</b></a><br /><a href='http://www.milesdavis.com/'><b>Miles Davis</b></a><br />"

(with-html-output-to-string (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))))))))))

"<table border='0' cellpadding='4'><tr align='right'><td bgcolor='green'>I</td><td bgcolor='pink'>II</td><td bgcolor='green'>III</td><td bgcolor='pink'>IV</td><td bgcolor='green'>V</td></tr><tr align='right'><td bgcolor='pink'>VI</td><td bgcolor='green'>VII</td><td bgcolor='pink'>VIII</td><td bgcolor='green'>IX</td><td bgcolor='pink'>X</td></tr><tr align='right'><td bgcolor='green'>XI</td><td bgcolor='pink'>XII</td><td bgcolor='green'>XIII</td><td bgcolor='pink'>XIV</td><td bgcolor='green'>XV</td></tr><tr align='right'><td bgcolor='pink'>XVI</td><td bgcolor='green'>XVII</td><td bgcolor='pink'>XVIII</td><td bgcolor='green'>XIX</td><td bgcolor='pink'>XX</td></tr><tr align='right'><td bgcolor='green'>XXI</td><td bgcolor='pink'>XXII</td><td bgcolor='green'>XXIII</td><td bgcolor='pink'>XXIV</td><td bgcolor='green'>XXV</td></tr></table>"

(with-html-output-to-string (http-stream)
  (:h4 "Look at the character entities generated by this example")
   (loop for i from 0
         for string in '("F?te" "S?rensen" "na?ve" "H?hner" "Stra?e")
         do (htm
             (:p :style (conc "background-color:" (case (mod i 3)
                                                    ((0) "red")
                                                    ((1) "orange")
                                                    ((2) "blue")))
              (htm (esc string))))))

"<h4>Look at the character entities generated by this example</h4><p style='background-color:red'>F&#xEA;te</p><p style='background-color:orange'>S&#xF8;rensen</p><p style='background-color:blue'>na&#xEF;ve</p><p style='background-color:red'>H&#xFC;hner</p><p style='background-color:orange'>Stra&#xDF;e</p>"

(with-html-output-to-string (str)
  (:html (:title "test")))

"<html><title>test</title></html>"
-------------- next part --------------


--

[1] http://paste.lisp.org/display/55662

[2] http://paste.lisp.org/display/55663


More information about the Cl-who-devel mailing list