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