This is an overview to my attempts at getting Clojure with Emacs. Inspired by this post, I set out to learn three things simultaneously: emacs, clojure and Google App Engine.
For comparison, my current web prototyping combination is TextMate, Rails, and Heroku. Prior to that it was a mix of python, php or perl, with vim.
There are already number of articles on getting GAE and Clojure to work. Consider this me making notes for myself because I keep forgetting the Emacs shortcuts!
I settled on Aquamacs to start out with emacs on the Mac. It seems to be more forgiving if I use normal Mac keyboard shortcuts while I learn emacs keys. Also makes it easy to switch between it and TextMate.
The other feature I love is full screen mode: ⌘-Shift-Return
To get command line access, you need to go to Tools->Install Command
Line Tools. This gives you an “
aquamacs” shortcut in the shell. I
aliased it to “
For some help on learning emacs, consider:
Google App Engine (GAE)
The GAE distribution is available here: GAE Download.
I setup my shell to include a $GAE_BASE directory for where I unpacked it, and added $GAE_BASE/bin to my path.
Creating a Clojure Project
The first post I read assumed that you were starting with a manual layout of your project. I’m going to use lein, a build manager for clojure, similar to rake for ruby. Behind the scenes lein uses Java’s maven as a package management system (similar to gems).
To make things a bit more interesting, I plan to write a very basic CMS to explore the various APIs. I’m keeping everything on the githubs.
The steps to getting setup look something like:
$ lein new gaecms $ mkdir -p war/WEB-INF
Then make some changes to your project.clj file:
(defproject gae-cms "1.0.0-SNAPSHOT" :description "A basic CMS built on Google App Engine (GAE)" :dependencies [[org.clojure/clojure "1.2.0"] [org.clojure/clojure-contrib "1.2.0"] [compojure "0.4.1"] [ring/ring-servlet "0.2.1"] [appengine "0.4-SNAPSHOT"]] :dev-dependencies [[leiningen/lein-swank "1.2.0-SNAPSHOT"]] :compile-path "war/WEB-INF/classes" :library-path "war/WEB-INF/lib")
To save some typing, you can clone: git://github.com/gmwils/gaecms.git
To run the interpreter locally, try the following:
$ lein deps $ lein swank
To test out that the interpreted mode is working, open up src/gae_cms/core.clj in AQ.
Then connect to the server:
From within the editor, you can now run either of the following:
C-x C-e % evaluate current line C-c C-k % compile the current file
You also have an interactive clojure shell for typing commands into. Try adding the following into your source code and then pressing C-x C-e to evaluate:
You should see your current CLASSPATH printed out.
Setup for GAE
$HOME/war/WEB-INF/web.xml map the URLs that you want your custom
servlet to handle. In this case, send everything into the servlet:
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <display-name>CMS on GAE</display-name> <servlet> <servlet-name>cms</servlet-name> <servlet-class>gae-cms.core</servlet-class> </servlet> <servlet-mapping> <servlet-name>cms</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
$HOME/war/WEB-INF/appengine-web.xml add the following to setup
Google App Engine to refer to your servlet above.
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0"> <application>cms-clj</application> <!-- GAE app id for your app --> <version>v0-1</version> <!-- Arbritrary Version Id --> </appengine-web-app>
Next, update src/gaecms/core.clj with:
(ns gaecms.core (:gen-class :extends javax.servlet.http.HttpServlet) (:use compojure.core [ring.util.servlet :only [defservice]]) (:require [compojure.route :as route])) (defroutes cms-public (GET "/"  "<html><title>GAE CMS</title><body><h1>Hello World!</h1></body>") ) (defroutes cms cms-public (route/not-found "Page not found")) ; 404 error page (defservice cms)
To test this locally, try:
$ lein deps $ lein compile $ $GAESDK/bin/dev_appserver.sh war
Deploying to Google
First go to the GAE console and create an application. The following should then work:
$ lein deps $ lein compile $ $GAESDK/bin/appcfg.sh update war
I’m still playing with getting it working with Google App Engine. The above is enough to get hello world working.