Re: easily embedding html into Lisp
From: Pascal Bourguignon (spam_at_mouse-potato.com)
Date: 09/15/04
- Next message: Michael Hönisch: "Evaluate string in Lisp"
- Previous message: Rob Warnock: "Re: troll's food (python vs lisp)"
- In reply to: Rob Warnock: "Re: easily embedding html into Lisp"
- Next in thread: Christophe Turle: "Re: easily embedding html into Lisp"
- Reply: Christophe Turle: "Re: easily embedding html into Lisp"
- Reply: Rob Warnock: "Re: easily embedding html into Lisp"
- Reply: Tim Bradshaw: "Re: easily embedding html into Lisp"
- Reply: Andreas Thiele: "Re: easily embedding html into Lisp"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: 15 Sep 2004 11:53:59 +0000
rpw3@rpw3.org (Rob Warnock) writes:
> Andreas Thiele <nospam6329@nospam.com> wrote:
> +---------------
> | I'd like to introduce a simple approach of embedding html into Lisp.
> +---------------
>
> You should look at <http://www.cliki.net/Lisp%20Markup%20Languages>,
> which lists several readily-available packages which already do
> this (or similar). I tend to use HTOUT, but CL-WHO is also nice.
> Also see <http://www.cliki.net/HTML-from-sexpr>.
>
> +---------------
> | Let's assume we already have three functions 'table 'tr and 'td.
> | Our html code to make a table then might look like
> | (table :cellpadding 0 :cellspacing 5
> | (tr (td "hello") (td "world")))
> | producing
> | <table cellpadding="0"
> | cellspacing="5"><tr><td>hello</td><td>world</td></tr></table>
> +---------------
>
> In HTOUT, that would be written this way.
>
> (with-html-output (s stream)
> ((:table :cellpadding 0 :cellspacing 5)
> (:tr (:td "hello") (:td "world"))))
> [...]
> +---------------
> | I assume html tags can be described liked
> | <tag-name attribute1=value1 ... > content </tag-name>
> +---------------
>
> HTOUT uses keywords for tags, so you don't need to define functions
> for all of them. Or, if the first element of a form is itself a list
> the CAR of which is a keyword, then the CAAR is taken as the tag and
> the CDAR is a property list of "attribute value..." (as shown in the
> example above).
>
> +---------------
> | Now let's go one step ahead. For each html tag there has to be such a
> | function definition.
> +---------------
>
> Packages such as HTOUT & CL-WHO don't require this, using symbols in
> the keyword package as tag markers instead. Any list whose CAR is not
> a keyword or whose CAR is not a list starting with a keyword is taken
> to be pure Lisp code, which is simply passed through to the compiler.
> Also, inside a WITH-HTML-OUTPUT, macrolets are automatically defined
> for several common operations, including going back into HTML mode
> from Lisp code [note the use of HTM in the following example].
> [...]
> (defun list-html-table (lists &key (stream *standard-output*))
> (let ((column-names (car lists))
> (rows (cdr lists)))
> (with-html-output (s stream)
> (:h3 (fmt "Results: ~d rows" (length rows)))
> (lfd)
> ((:table :border 1 :cellspacing 0 :cellpadding 1) ; make compact
> (:tr (lfd)
> (loop for name in column-names do
> (htm ((:th :nowrap) name) (lfd))))
> (loop for row in rows do
> (htm (:tr (lfd)
> (loop for v in row do
> (let ((vv (if (or (null v) (string-equal v ""))
> " "
> (escape-string v))))
> (htm ((:td :nowrap) vv) (lfd))))))))
> (lfd))))
> [...]
> +---------------
> | When talking about html I must mention Kevin Rosenberg's LML package
> | at http://lml.b9.com
> +---------------
>
> That one is also listed on the above-mentioned CLiki pages, as well as
> his LML2 (for generating XHTML documents).
>
> +---------------
> | I am interested in your criticism to my approach.
> +---------------
>
> It certainly works. I used something very similar to it [in Scheme]...
> before I found HTOUT. ;-}
My own variation is as follow.
I translated the DTD of HTML 4.01 as:
(DEFELEMENT A () "anchor")
(DEFELEMENT ABBR () "abbreviated form (e.g., WWW, HTTP, etc.)")
(DEFELEMENT ACRONYM ())
(DEFELEMENT ADDRESS () "information on author")
(DEFELEMENT APPLET (:DEPRECATED :LOOSE-DTD) "Java applet")
(DEFELEMENT AREA (:END-FORBIDDEN :EMPTY) "client-side image map area")
(DEFELEMENT B () "bold text style")
(DEFELEMENT BASE (:END-FORBIDDEN :EMPTY) "document base URI")
;; ...
(DEFATTRIBUTE ABBR
(TD TH)
(%TEXT) :IMPLIED
() "abbreviation for header cell"
);;ABBR
(DEFATTRIBUTE ACCEPT-CHARSET
(FORM)
(%CHARSETS) :IMPLIED
() "list of supported charsets"
);;ACCEPT-CHARSET
(DEFATTRIBUTE ACCEPT
(FORM INPUT)
(%CONTENTTYPES) :IMPLIED
() "list of MIME types for file upload"
);;ACCEPT
;; ...
Then I define DEFELEMENT and DEFATTRIBUTE as macros doing what I need
in various cases. I've got a package that define them to generate HTML
as Andreas (attribute validation is not implemented yet, DEFELEMENT
generates a macro named for the tag instead of a function as in
Andreas' solution. (There's only one shadow: MAP, between HTML4.01
tags and COMMON-LISP). The advantage of using macros for tags is that
you can embed a lisp body non functionally:
(table (:width "80%")
(dolist (row rows)
(when (odd (length row))
(tr ()
(dolist (item row)
(td () (p () (insert-pcdata "Item: ~A" item))))))))
In HTOUT it would be written almost the same.
Andreas would have to evaluate all arguments and build lists:
(table :cellpadding 0 :cellspacing 5
(mapcan (lambda (row)
(when (odd (length row))
(list (tr (mapcan (lambda (item)
(list (td item))) row))))) rows))
In another package, I defined DEFELEMENT and DEFATTRIBUTE otherwise to
generate an HTML parser. Since the knowledge of the tags and
attribute is embedded inside WITH-HTML-OUTPUT, I feel it's a solution
that's less declarative, ie. lower level than mine and less useful.
Also, since HTOUT binds locally an output stream, and doesn't take it
as argument to the non function keyword tags, I don't see how you
could split the description of a page over serveral functions. On the
other hand, for now I have to use a global context to generate HTML,
but this allow be to define methods to insert items on pages such as
headers, feets, forms, etc. This could be easily done with Andreas'
solution. Would HTM work outside of the lexical context of
WITH-HTML-OUTPUT?
-- __Pascal Bourguignon__ http://www.informatimago.com/ Our enemies are innovative and resourceful, and so are we. They never stop thinking about new ways to harm our country and our people, and neither do we.
- Next message: Michael Hönisch: "Evaluate string in Lisp"
- Previous message: Rob Warnock: "Re: troll's food (python vs lisp)"
- In reply to: Rob Warnock: "Re: easily embedding html into Lisp"
- Next in thread: Christophe Turle: "Re: easily embedding html into Lisp"
- Reply: Christophe Turle: "Re: easily embedding html into Lisp"
- Reply: Rob Warnock: "Re: easily embedding html into Lisp"
- Reply: Tim Bradshaw: "Re: easily embedding html into Lisp"
- Reply: Andreas Thiele: "Re: easily embedding html into Lisp"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|