I have just switched over to using SLIME instead of the basic Lisp interaction that was provided with clojure-mode. A discussion on the clojure-group prompted me to do this. In this same discussion there where questions about how people setup Clojure and how it can be difficult for new users to get started. My setup is not perfect but I am really starting to like it. I thought I would share with others and maybe get some feedback on improvements I can make. I will update this entry as I make changes to my setup.
Overview
Let me tell you a little bit about my setup so that you can get into how cool it is and then get excited about reading all of the stuff below.
I have a command on my system named
clj.
clj => starts a REPL
clj some_file.clj => Runs the script some_file.clj
clj some_file.clj arg1 arg2 => Runs the script some_file.clj and passes
arg1 arg2 to the script
When I start to get serious, I create a "project" which looks like this:
my-project
.cljrc.clj
bin
lib
src
test
The file
.cljrc.clj establishes this as a Clojure project. If I execute clj anywhere within this project it will determine the root of the project by locating the .cljrc.clj file and then start the REPL in that directory. It will also load any jar files within the lib directory into the classpath. The file .cljrc.clj is passed as a parameter to the REPL which will execute the Clojure code contained therein.bin contains commands that allow me to do things like run my tests, compile java code, package java code in a jar file and put it in the lib directory for use from Clojure, etc...All source files go into
src and all tests go into test.I can run SLIME from emacs and the
clj script will be used to start Clojure. Once I have started a REPL using this command. I can open emacs and connect to the running REPL and interact with it from within emacs.Configure Emacs
I did not use
M-x clojure-install to configure emacs. Instead, I followed this tutorial http://riddell.us/tutorial/slime_swank/slime_swank.html which worked for me on OS X even though it targets Ubuntu. After doing this, I had SLIME working with Clojure in emacs.Here is my .emacs file:
;; clojure-mode
(add-to-list 'load-path "/opt/clojure/clojure-mode")
(require 'clojure-mode)
;; swank-clojure
(add-to-list 'load-path "/opt/clojure/swank-clojure")
(setq swank-clojure-binary "clj")
(require 'swank-clojure-autoload)
;; slime
(eval-after-load "slime"
`(progn (slime-setup '(slime-repl))))
(add-to-list 'load-path "/opt/slime")
(require 'slime)
(slime-setup)
Notice that I added the
swank-clojure-binary line instead of swank-clojure-config.The Ruby Script
This is the Ruby script that I use to start Clojure. I don't do much Ruby coding so please don't laugh.
#!/usr/bin/env ruby -wKU
JAVA_HOME="/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home"
JAVA="#{JAVA_HOME}/bin/java"
GIT_ROOT=ENV['GIT_ROOT']
CLJ="/opt/clojure"
LIB="#{GIT_ROOT}/library"
classpath=".:src:test:classes" +
":#{CLJ}/clojure/clojure.jar" +
":#{CLJ}/clojure-contrib/clojure-contrib.jar" +
":#{CLJ}/swank-clojure" +
":#{LIB}/tools/ant.jar" +
":#{LIB}/tools/ant-launcher.jar" +
":#{GIT_ROOT}/research/clojure/fpl-clojure-util/fpl-clojure-util.jar"
JLINE="#{LIB}/bin-tools/jline-0.9.94.jar"
def find_root(d, repl_config)
Dir.chdir(d)
if Dir.pwd == "/"
nil
else
if Dir.glob("#{repl_config}").size == 1
Dir.pwd
else
find_root("../", repl_config)
end
end
end
repl_config=".cljrc.clj"
dir = Dir.pwd
if find_root(dir, repl_config)
puts "Running in #{Dir.pwd}"
else
Dir.chdir(dir)
puts "Running in #{Dir.pwd}"
puts "Using default #{repl_config}"
repl_config="~/.cljrc.clj"
end
if File.directory? "lib"
Dir.foreach("lib") do |x|
if x =~ /.*.jar$/
classpath = classpath + ":lib/#{x}"
end
end
end
if ARGV[0]
puts "Running Clojure Script... #{ARGV[0]}"
if ARGV[0].size > 1
system("#{JAVA} -Xms500M -Xmx500M -cp #{classpath} "+
"clojure.lang.Script #{ARGV.shift} -- #{ARGV.join(" ")}")
else
system("#{JAVA} -Xms500M -Xmx500M -cp #{classpath} "+
"clojure.lang.Script #{ARGV[0]}")
end
else
puts "Starting Clojure REPL..."
system("#{JAVA} -cp #{classpath}:#{JLINE} jline.ConsoleRunner "+
"clojure.lang.Repl #{repl_config}")
end
Note: This file has been updated in a more recent blog post.
I name this file
clj and put it somewhere in my path. If you want to use this then you will need to modify the default libraries that are loaded.Here is what I have in
.cljrc.clj:
(use '[clojure.contrib.duck-streams :only (spit)])
(use '[swank.swank :only (start-server ignore-protocol-version)])
(defn exit [] (. System exit 0))
(defn swank-server []
(ignore-protocol-version "2009-09-08")
(spit (java.io.File. "port.txt") "")
(start-server "port.txt" :port 4005 :dont-close true))
This code will be executed when you run
clj within a project. It defines an exit function that you can use to exit the REPL. It also defines a function that will start a swank server from within the REPL. You will need to the set the correct value for ignore-protocol-version. If you don't know what to put here then you can delete this line and emacs will give you a hint as to what it should be.So how does this all work?
On Mac OS X I have associated the
.clj file type with Carbon Emacs. This allows me to open a file for editing by typing open some_file.clj. I can also use wildcards to open multiple files from the command line in emacs.Once emacs is open, start SLIME by typing
M-x slime. This will start the Clojure REPL using the clj script with the classpath just how you want it.You may also connect to an existing REPL. Start the REPL from the command line using
clj. Once the REPL is up type (swank-server). In emacs, type M-x slime-connect. Emacs will ask about the host and port, press enter twice. That's how I do it for now. I am still working on it. Once I get more comfortable using SLIME I will update this post with any improvements I have made. The one improvement that I do want to make is to change my method of testing to fit with
clojure-test-mode so that I can utilize its featues.

No comments:
Post a Comment