At Shared Logic, we use Google’s Closure Tools and Common Lisp to write and deploy rich web applications. In this article I demonstrate our approach by writing the Hello, World! described in Google’s Getting Started with the Closure Library.
First, I create a project directory and download the Closure Library:
mkdir -p ~/src/mjf/grok-google-closure-lisp/closure cd ~/src/mjf/grok-google-closure-lisp/closure svn checkout http://closure-library.googlecode.com/svn/trunk/ \ closure-library
mkdir -p ~/src/mjf/grok-google-closure-lisp/www/js cd ~/src/mjf/grok-google-closure-lisp/www/js ln -s ../../closure/closure-library/closure/goog .
CL-USER> (ql:quickload "quickproject") ... => ("quickproject") CL-USER> (quickproject:make-project "~/src/mjf/grok-google-closure-lisp/" :depends-on '(hunchentoot cl-who parenscript)) => "grok-google-closure-lisp" CL-USER> (ql:quickload "grok-google-closure-lisp") ... => ("grok-google-closure-lisp") CL-USER> (in-package #:grok-google-closure-lisp) => #<PACKAGE "GROK-GOOGLE-CLOSURE-LISP">
;;;; grok-google-closure-lisp.lisp (in-package #:grok-google-closure-lisp) ;;; "grok-google-closure-lisp" goes here. Hacks and glory await! (setf hunchentoot:*catch-errors-p* nil) ; T for production (setf hunchentoot:*show-lisp-errors-p* t) (setf hunchentoot:*show-lisp-backtraces-p* t) (defparameter *project-pathname* (merge-pathnames "src/mjf/grok-google-closure-lisp/" (user-homedir-pathname))) (defparameter *http-port* 4242) (defvar *my-acceptor* nil) (defun start () (unless *my-acceptor* (push (hunchentoot:create-folder-dispatcher-and-handler "/js/" (merge-pathnames "www/js/" *project-pathname*)) hunchentoot:*dispatch-table*) (setf *my-acceptor* (hunchentoot:start (make-instance 'hunchentoot:easy-acceptor :port *http-port*))))) (defun stop () (when *my-acceptor* (hunchentoot:stop *my-acceptor*) (setf hunchentoot:*dispatch-table* (last hunchentoot:*dispatch-table*)) (setf *my-acceptor* nil)))
Fourth, I create and edit a hello.lisp file to define Hunchentoot easy handlers corresponding to the hello.js and hello.html from the Google example. I modify the script URLs according to our convention:
Fifth, I add hello.lisp to the components list of the system definition in grok-google-closure-lisp.asd, reload the project, and start the Hunchentoot acceptor:
GROK-GOOGLE-CLOSURE-LISP> (ql:quickload "grok-google-closure-lisp") ... => ("grok-google-closure-lisp") GROK-GOOGLE-CLOSURE-LISP> (start)
Finally, I can browse the application URL http://localhost:4242/hello.
Yes, the Parenscript definition is a few lines longer than hello.js, and, yes, I could shorten it with Lisp macros. However, I have a better plan.
As Google does with it’s compiler, I will trade some terseness now for much greater gain later using Lisp’s magic in creating embedded domain specific languages. More to come.