We have a PS program split across a dozen or so Lisp files and a
"compiler" (really just a build script in the form of a CL function)
that processes each file by binding *PARENSCRIPT-STREAM*, reading in
PS forms from the top level of the file, and calling PS* on them to
create a .js file. Then a second script assembles the component .js
files into a big one, which is the entire client program. That thing
is given a SHA1 hash as part of its name so it can be browser-cached
forever.

This setup has proven pretty good. It's simple. It works somewhat like
ASDF so it feels natural in a CL environment. It only recompiles
individual js files when they change, so the round trip from editing
PS code to refreshing the page in the browser is reasonably fast.

Another advantage is for debugging. When browsers, even bad ones,
report an error, they provide the line number at which the error
occurred. Because the big .js file is named with a SHA1 hash, it's
very quick to go back to Emacs, open the precise version of the
program that's producing the error (ido-mode makes this particularly
quick as one only needs to type in 4 or 5 characters) and M-g M-g to
the offending line number. This is so much easier than having to open
the script in some horrible dinky client-side tool (even the
not-so-bad ones like Firebug) and scroll around.

As I said, pretty simple. Before this we had a more complicated
approach that didn't work nearly as well.

Daniel


On Sat, Jan 8, 2011 at 2:44 PM, Jon Rosebaugh <chairos@gmail.com> wrote:
As I said in the subject, I'm working on a JS-only (no server-side
code) HTML5 webapp in Parenscript with jQuery. I have extensive JS
experience, but I'm really new to Common Lisp.

I wanted a setup where I could edit a Parenscript file, hit save, then
hit refresh in my browser and immediately see the new code, just as if
I were working in Javascript. I built a little server using
Hunchentoot and cl-who that runs ps-compile-file on my parenscript
source file as needed. This works fairly well, but maybe is not the
best way to accomplish this.

However, there's a problem; I wanted to use parenscript functions
without the namespace, so I defined a package in serve.lisp that uses
parenscript, then put (in-package :innkeeper) at the top of my
parenscript file. This doesn't work properly in the 2.2 release of
Parenscript (which is what Quicklisp provides). It _does_ work in the
git repo version (as of commit
0e01e555f404a7dcb8befb7587288c38abf526c2), but it's annoying to not be
able to use Quicklisp for everything.

Once I have a release version I'll want to come up with some lisp
program that compiles the parenscript to javascript, minifies it, and
sticks it in an also-minified html file from cl-who, so the whole
thing is compiled down to a single file. I'd appreciate any
best-practice tips on that too.

Just in case my description was unclear, here's what I think are the
relevant bits. If needed, I can provide the entire files off-list.

; relevant bits of serve.lisp
(defpackage "INNKEEPER"
 (:use "COMMON-LISP" "HUNCHENTOOT" "CL-WHO" "PARENSCRIPT")
 (:export :start-innserver :stop-innserver))

(in-package :innkeeper)

(define-easy-handler (jsgen :uri "/innkeeper.js") ()
 (setf (content-type*) "application/javascript")
 (ps-compile-file "/Users/jon/code/innkeeper/innkeeper.lisp"))

; beginning (and a few representative lines) of innkeeper.lisp

(in-package :innkeeper)

(defmacro immediate (&body body)
 `((lambda () ,@body)))

(var *inn*
    (create
            setup (lambda () ((@ ($ "#top-tabs") tabs)))))

(j-query #'(@ *inn* setup))

_______________________________________________
parenscript-devel mailing list
parenscript-devel@common-lisp.net
http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel