It’s been a while since I blogged about Clojure, since I’ve been pretty busy and haven’t had as much time as I would like to play with it. Before I ran out of time, however, there were a few blog posts I had been planning to write, so I think it’s time to get around to finishing those up. There are three( right now) in total; This one, which is about setting up Slime, One about the test-is framework, and a review of Programming Clojure.
If you’ve done any Lisp programming at all, you’ve probably heard of Slime. Slime is an Emacs module that communicates with Lisp processes and acts as a Repl. It allows you to evaluate expressions in other buffers using the intepreter Slime is running, as well as a bunch of other really cool stuff that I haven’t delved into much. I mostly just use it as a Repl; even just having a repl and having C-x C-e work for non-elisp stuff is quite nice.
To setup Slime to work with clojure, I have the following in addition to the clojure customizations I described here:
(add-to-list 'swank-clojure-extra-classpaths "/home/nflath/.emacs.d/clojure-contrib/clojure-contrib.jar") (add-to-list 'swank-clojure-extra-classpaths "/home/nflath/.emacs.d/clojure/") (setq slime-repl-history-file "~/.emacs.d/.slime-history.eld") (setq swank-clojure-jar-path "/home/nflath/repos-staging/.emacs.d/clojure/clojure-1.1.0-alpha-SNAPSHOT.jar") (slime)
Going over this now, I see some of the Slime setup went into the segment I posted about, so to be clear the full setup you should have for both clojure and slime is:
(setq clojure-src-root "/home/nflath/.emacs.d") (require 'clojure-mode) (add-to-list 'auto-mode-alist '("\\.clj$" . clojure-mode)) (setq swank-clojure-extra-classpaths '()) (add-to-list 'swank-clojure-extra-classpaths "/home/nflath/.emacs.d/clojure-contrib/clojure-contrib.jar") (add-to-list 'swank-clojure-extra-classpaths "/home/nflath/.emacs.d/clojure/") (setq slime-repl-history-file "~/.emacs.d/.slime-history.eld") (setq swank-clojure-jar-path "/home/nflath/repos-staging/.emacs.d/clojure/clojure-1.1.0-alpha-SNAPSHOT.jar") (clojure-slime-config) (slime)
These lines essentially setup the classpath Slime will use to look for Java and clojure classes, as well as the location of Clojure itself. You will need to modify these path values in order for them to work on your machine, but it should be fairly easy to figure out where the paths should point. The last line, (slime), will just start the slime interpreter. I’m a big fan of doing things when starting emacs, since I do it so infrequently.
I also use the ’show’ function described here when programming in Clojure. What it does is it displays the methods for the object under point. While this can often be too much info, since Object provides a lot of methods you probably don’t want, it is fairly nice. To do this, I have the following in my user.clj:
(use 'clojure.contrib.repl-utils)
Which will automatically load the repl-utils library that comes with clojure-contrib if user.clj is in slime’s classpath. You should browse through all the functions in this library, actually; it has some great functions for use in the repl. One function especially that we are interested in is show, which displays all the methods that could be called on an object. To integrate this into your Emacs session outside of the slime repl, add this function to your initialization file:
(defun slime-java-describe (symbol-name) "Get details on Java class/instance at point." (interactive (list (slime-read-symbol-name "Java Class/instance: "))) (when (not symbol-name) (error "No symbol given")) (save-excursion (set-buffer (slime-output-buffer)) (unless (eq (current-buffer) (window-buffer)) (pop-to-buffer (current-buffer) t)) (goto-char (point-max)) (insert (concat "(show " symbol-name ")")) (when symbol-name (slime-repl-return) (other-window 1)))) (define-key slime-mode-map (kbd "C-c d") 'slime-java-describe) (define-key slime-repl-mode-map (kbd "C-c d") 'slime-java-describe)
Now, in your Clojure buffers, C-c d will pop up the slime buffer in another window and display the results of calling show on the thing under point. It doesn’t work as well in the Slime Repl buffer itself, but that’s a limitation I’m willing to live with. Another macro I like in the repl-utils package is source, which will display the source of any built-in function or macro. This allows you to learn a huge amount about idiomatic clojure code by examining the code that makes up clojure itself.
A few notes about the above setup: I have found the slime-clojure connection to be extremely dependent on the ordering in which you load packages. Slime must be started before clojure-test.el is required, or else you won’t be able to use a Slime REPL. The same is true for requiring slime: don’t do it. I don’t know why these cause massive issues, and they shouldn’t, but unfortunately they do. If you encounter any problems, it’s probably due to the order of statements in your initialization file.
That’s all the Slime and Clojure setup I have right now; I’ll no doubt add more as I keep using Clojure. If there are any good Slime customizations you have, please share them in the comments: I love adding new things to my emacs repertoire.
The slime-java-describe function is neat, but it’s essentially duplicating functionality already present in the Slime inspector. Try C-c S-i on a Java object to explore its methods. M-. (or slime-edit-definition) also provides you with a nicer version of repl-utils/source.
> I love adding new things to my emacs repertoire.
Me too, the only thing better than adding things to my Emacs config is removing code and still having the same functionality. =) Your add-to-list calls with swank-clojure-extra-classpaths should be redundant if you’ve called clojure-slime-config with the right clojure-src-root set.
I’ve tried to make it so once clojure-mode is installed (ideally through ELPA) you should only need one line to configure the rest of slime. (two lines if you use a custom install location.) The repl-history var looks handy though; I didn’t know about that. Thanks!
Slime-Clojure Setup Musings of a Software Engineering Student was a wonderful read. I’m always looking for more information about this, thanks for the awesome post, keep them coming!