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!
Emacs
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 “aq
“.
For some help on learning emacs, consider:
You may also want to setup Clojure to run with Emacs. This article assumes you are using lein.
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:
M-x slime-connect
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:
(System/getProperty "java.class.path")
You should see your current CLASSPATH printed out.
Setup for GAE
In $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>
In $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.
For more details, I suggest you follow the Compojure on GAE blog. Specifically, the article on Deploying to App Engineis a good overview.
Next steps include getting interactive development working with GAE, and actually handling dynamic content.