views:

221

answers:

3

I'm currently in the process of adding functionality to an existing J2EE webapp, in a Tomcat container, and I'm writing my additions using Clojure. My setup is simple: I just add calls to static methods generated by clojure, and code all the hard work from the clojure side. The build process consists in compiling clojure code (lein uberjar) and then compiling the java code with that jar on the classpath.

In the webapp init, I have a call to a generated class that fires up a swank server with a (swank/start-repl). I'd like to be able to connect my Aquamacs' slime to that server, and work interactively from there (up to a point, I won't try nothing that requires a java-side recompilation). But I have a situation that I don't quite understand. If I do a \M-x slime-connect, I get a REPL prompt (after being notified that there's no inferior lisp process, which I think it's ok, since the inferior lisp process is running outside emacs control). I can evaluate forms perfectly, and I can even inspect things like my.own.namespace/my-var. However, if I visit a file with an already compiled clojure code, I can't seem to make slime recognize it as its source. Consider a simple clojure file:

(ns my.namespace
  (:gen-class
   :name my.namespace
   :methods [#^{:static true} [testFunc [] void]]))

(def *secret* "shhhh")

(defn -testFunc []
  (println (str "our secret is: " secret)))

Assuming that this was compiled and included in the uberjar loaded by the webapp, I can eval/inspect my.namespace/*secret*. But If I try to eval inside the code buffer, Slime thinks I'm on the user namespace (which can even make sense!). But now I'm left with a single working option - I have to evaluate - one by one, all the forms in the file! \C-c \C-l (loading the source file) won't do nothing - apparently just returns nil and outputs nothing else. Compiling everything seems to do just that - it compiles, shows errors if it finds them, but won't change my namespace. And the strangest is the \C-~ (sync package and directory), which using Common Lisp it does just what I want, but here it freezes the clojure REPL for good.

There's always the option of switching to the REPL, typing (in-ns 'my.namespace), and then all works properly. But that simply isn't practical enough when the clojure files are growing in number (as the namespace of the code buffer won't change automatically!)

My question is, then, whether I'm lacking a basic command/configuration - or if there's an obvious reason for this behavior to happen as such.

+4  A: 

I may be misunderstanding your problem, but can't you (while visiting this hypothetical buffer in emacs), hit C-c C-k to compile the buffer in your current Clojure instance (what Slime is connected to)?

Then, in the Slime buffer, switch to this namespace with a (in-ns 'my.namespace). Then you should have access to what you compiled in that namespace.

Isaac Hodes
Hmm, as I've written in a question's comment, that compilation will work, but my point is that I'm used to that `(in-ns 'my.namespace)` to be implicit after a compile/load-file. It worked this way in every Common Lisp implementation I've used with SLIME, IIRC; also, having to switch namespaces manually in a 10 or more file project (specially with more-than-desirable clojure restarts) leads to fatigue - and short after, insanity :) - so if I'm not doing something wrong and the interaction I'm having is supposed to be this way, I'll code a workaround!
Edgar
Oh, also, the `(in-ns 'my.namespace)` doesn't work at all if evaluated in place, on the .clj file buffer - I have to do it on the REPL, then that file's buffer switches its namespace. That is also less than obvious, for me.
Edgar
You're totally right–it's a pain in the ass. I've just gotten used to it, I guess, and hadn't coded w/ Slime/Swank before Clojure. Let me know if you get a work around! I take it things are working for you now? Is there something still that is unanswered? (Not that I answered anything, but I'd like to know if I could still help!)
Isaac Hodes
Well, despite not being fully satisfied with how things are right now, you answered my question - it wasn't a problem with my setup, it was the "normal" behavior. Here's a first attempt to workaround this issue: http://gist.github.com/522706 - it still doesn't do any auto-update when switching files, but add a keyboard shortcut to that fn and you'll save some time. Thanks, Isaac!
Edgar
Thanks for the emacs fn–might have to add it to .init. It can be useful to not automatically switch to the namespace of the buffer you just evaluated, though: if you don't have :reload set on a library you're importing, but you make a change to that lib, you need to re-compile it, but you won't want to be in its namespace. So the default does make sense, it's just often inconvenient.
Isaac Hodes
Hmm, I have to learn that :reload trick - what's the downside, an active file update monitor? But I see what you mean, and agree - I'll keep it manual. I've just made some generalization to the fn, see [here](http://gist.github.com/523802). It just falls back to `C-c M-p` in case there's no namespace or if you use a prefix.
Edgar
I decided to un-accept this answer - despite having originated an useful function (that I'll still use), i found a direct solution to the problem I mentioned. See my answer. Thanks anyway, Isaac!
Edgar
+2  A: 

Switching namespaces automatically on compile has never been the default for swank-clojure, though it might be an optional slime feature that happened to work with Clojure. But C-c M-p to switch the repl to the current buffer's namespace has always worked for me, and I've never heard of anyone having trouble with it.

Are you running on the latest stable versions of clojure-mode and slime-repl? Do you have swank-clojure.el installed? (You shouldn't need it.) It sounds like this could be due to mismatched versions of the elisp libs. If that's not the problem it could be an Aquamacs bug; swank-clojure is designed to work with GNU Emacs. It could also be a bug in slime if you are running from trunk rather than the latest elpa release.

technomancy
I've realized a couple of hours ago that `C-c M-p` did work perfectly on my setup (Aquamacs, latest stable release of clojure-mode and slime-repl, clojure-1.2-rc1). What keeps hanging is the `C-c ~`, but I'm guessing that SLIME command only works for Common Lisp implementations. What I was expecting to work is doing a `C-c C-l` (load) on a file - I expected the namespace to change, but it won't!Just for benefit of future readers, the function I sketched in http://gist.github.com/522706 also works, but it doesn't ask for a namespace - it guesses it from the first `(ns ...)` form in the buffer.
Edgar
A: 

I've just found out that removing the culprit for this issue: slime-redirect-inferior-output, from slime-repl.el, was being called from a hook I had setup. It turns out that it doesn't play well without an inferior-lisp-process (read, a swank server started from within emacs).

So a quick workaround hack is just to remove the error form from that function, like this. Now the hook proceeds, and the namespaces are automatically calculated. As intended. Thank you for the suggestions, nevertheless - they led me to this solution!

Edgar