Clojure development: migrate to cider on Debian

Having successfully migrated to the cider Clojure/emacs development environment on Max OS X (used when mobile), I turned to migrating the environment on the main Debian box (used at home). The actual migration process was very similar, but as Debian Wheezy still ships emacs23, I had to download and install package.el manually. The .emacs initialisation is the same, though.

The problem I encountered on the Debian platform was somewhat different to that described earlier. This time, when attempting to cider-jack-in, I would get this stacktrace in the *cider-error* buffer:

  java.lang.IllegalAccessError: pp does not exist
  at clojure.core$refer.doInvoke (core.clj:3849)
  clojure.lang.RestFn.applyTo (RestFn.java:139)
  clojure.core$apply.invoke (core.clj:619)
  clojure.core$load_lib.doInvoke (core.clj:5394)
  clojure.lang.RestFn.applyTo (RestFn.java:142)
  clojure.core$apply.invoke (core.clj:619)
  clojure.core$load_libs.doInvoke (core.clj:5413)
  clojure.lang.RestFn.applyTo (RestFn.java:137)
  clojure.core$apply.invoke (core.clj:619)
  clojure.core$require.doInvoke (core.clj:5496)
  clojure.lang.RestFn.applyTo (RestFn.java:137)
  clojure.core$apply.invoke (core.clj:617)
  user$eval1081.invoke (NO_SOURCE_FILE:1)
  clojure.lang.Compiler.eval (Compiler.java:6619)
  clojure.lang.Compiler.eval (Compiler.java:6582)
  clojure.core$eval.invoke (core.clj:2852)
  clojure.main$repl$read_eval_print__6588$fn__6591.invoke (main.clj:259)
  clojure.main$repl$read_eval_print__6588.invoke (main.clj:259)
  clojure.main$repl$fn__6597.invoke (main.clj:277)
  clojure.main$repl.doInvoke (main.clj:277)
  clojure.lang.RestFn.invoke (RestFn.java:1096)
  clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__589.invoke (interruptible_eval.clj:56)
  clojure.lang.AFn.applyToHelper (AFn.java:159)
  clojure.lang.AFn.applyTo (AFn.java:151)
  clojure.core$apply.invoke (core.clj:617)
  clojure.core$with_bindings_STAR_.doInvoke (core.clj:1788)
  clojure.lang.RestFn.invoke (RestFn.java:425)
  clojure.tools.nrepl.middleware.interruptible_eval$evaluate.invoke (interruptible_eval.clj:41)
  clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__630$fn__633.invoke (interruptible_eval.clj:171)
  clojure.core$comp$fn__4154.invoke (core.clj:2330)
  clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__623.invoke (interruptible_eval.clj:138)
  clojure.lang.AFn.run (AFn.java:24)
  java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1146)
  java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:615)
  java.lang.Thread.run (Thread.java:679)

Nonetheless, everything seemed to work in the repl. Oddly, the error only manifested itself intermittently. The command that was causing the error appeared to be this initialisation statement, defined in nrepl-client.el:

  (defvar nrepl-repl-requires-sexp "(clojure.core/apply clojure.core/require 
    '[[clojure.repl :refer (source apropos dir pst doc find-doc)]  
      [clojure.java.javadoc :refer (javadoc)]
      [clojure.pprint :refer (pp pprint)]])"
  "Things to require in the tooling session and the REPL buffer.")

This string is sent to the newly-launched repl on startup by the function cider-init-repl-buffer, defined in cider-repl.el. Fiddling with the order of requires didn't make any difference; one change that did work was to :require :all from clojure.pprint, but that seemed to be a sledgehammer approach.

Figuring that an intermittent issue might be caused by a race between cider and lien repl initialisation, I added a short pause to cider-init-repl-buffer:

  defun cider-init-repl-buffer (connection buffer &optional noprompt)
    "Initialize the REPL for CONNECTION in BUFFER.
  Insert a banner, unless NOPROMPT is non-nil."
    (with-current-buffer buffer
      (unless (eq major-mode (quote cider-repl-mode))
        (cider-repl-mode))
      ;; use the same requires by default as clojure.main does
      (sit-for 1) ; allow lein repl to come up fully?
      (cider-eval-sync nrepl-repl-requires-sexp)
      (cider-repl-reset-markers)
      (unless noprompt
        (cider-repl--insert-banner-and-prompt nrepl-buffer-ns))
      (cider-remember-clojure-buffer cider-current-clojure-buffer)
      (current-buffer)))

No more intermittent stacktraces (or at least they are so rare I haven't seen one yet).