I ported John Wiseman's lsp for use by hunchentoot.
You can check out the source from the contrib directory :
svn checkout svn://common-lisp.net/project/tbnl/svn
http://common-lisp.net/websvn/listing.php?repname=tbnl&path=%2Fcontrib%2...
Comments welcomed.
Cheers, -- Mac
The following are copied verbatim from the comment
(asdf:oos 'asdf:load-op :cl-ppcre) (asdf:oos 'asdf:load-op :hunchentoot-test) (hunchentoot:start-server :port 8080)
;; verify that hunchentoot is running ;; http://localhost:8080/hunchentoot/test/
(asdf:oos 'asdf:load-op :lsp)
(in-package :lsp)
;; set debug on so we can examine the generated code (set-lsp-debug t)
;; use cl-user package for all unqualified symbols (set-lsp-package :cl-user)
;; compile the test file (get-lsp-function (merge-pathnames "test.lsp" *this-dir*))
;; take a look at the generated code (show-lsp-form (merge-pathnames "test.lsp" *this-dir*))
;; print the output to REPL (do-lsp-request (merge-pathnames "test.lsp" *this-dir*))
;; install the dispatcher function (push (create-lsp-folder-dispatcher-and-handler ;; uri "/hunchentoot/lsp/" ;; directory *this-dir* ;; valid lsp page suffixes '("lsp" "lhtml" "lhtm" "asp") ;; default content-type for non lsp files "text/plain") hunchentoot:*dispatch-table*)
;; try it out (click refresh a few times to verify that it is _dynamic_) ;; http://localhost:8080/hunchentoot/lsp/test.lsp
;; take a look at the source code too ;; http://localhost:8080/hunchentoot/lsp/lsp.lisp
;; alternatively, you can also create separate handler for each lsp file (push (hunchentoot:create-prefix-dispatcher "/hunchentoot/lsp/test.lsp" (get-lsp-function (merge-pathnames "test.lsp" *this-dir*))) hunchentoot:*dispatch-table*)
;; finally, you can also reuse lsp function within a custom dispatch handler (hunchentoot:define-easy-handler (lsp-demo :uri "/hunchentoot/test/lsp-demo.html") () (do-lsp-request (merge-pathnames "test.lsp" *this-dir*)))
;; http://localhost:8080/hunchentoot/test/lsp-demo.html
LAQ:
* Why another template module?
There are indeed a lot of template libraries including CL-EMB, Edi's own HTML-TEMPLATE, etc. But these libraries are obstinate in that they require you to construct and pass the `environment' variable in order to generate the dynamic content.
Secondly, I found that the @if @else template extensions/add-ons are often too limited in expressive power. You are programming lisp in the backend, but all of a sudden you need to drop to a very dumb language when you need to deal with the template code, which is kind of frustrating.
John Wiseman's code is very close to what I need, but it is designed to work with Franz's allegoserver. So I port it to work with my preferred web server (hunchentoot) instead.
* So should I use this for all my dynamic content generation?
No. Absolutely not. If you take a look at the very simple test.lsp, it screams like spaghetti code!
In the ideal world, if the graphics designer can deliver properly formatted html in cl-who sexp, I'm all set. But that's not gonna happen.
So for pages that I have total control, I prefer to write it using sexp. However, there are times where the designer need to frequently update a messy html template and I cannot afford to sync up with it given the time constraint, using lsp is a good compromise.
* Any tips & tricks?
Lisp is very hard to write (and even harder to read) without a good editor (like emacs) to help indenting your code and provide structured editing.
So unlike other dumber languages (php, perl...), intermixed lisp code with content is extremely hard to maintain and read.
In this regard, I would recommend you to use Franz's if-star package ( http://www.franz.com/~jkf/ifstar.txt ) in your template file because it helps you to match the open and close parenthesis for if-then-else conditional expression.
Also, unlike other dumber languages where if you have a syntax error in the template file, the compiler can point you to the exact line where it occurs. With lsp, the line number is lost when we use the built-in lisp reader to read the form. However you can use `show-lsp-form' in the REPL to examine the code when you encounter an error.