This episode is for subscribers only. Sign Up or Log in to watch it.

15. Using Figwheel With Emacs, part 2: CIDER

Published 20 August 16

By using Figwheel with CIDER you get both a Clojure and a ClojureScript REPL at the same time, and you get all the nice features of CIDER. It’s a more complex setup than just straight inf-clojure, so before we get there we need to talk a bit about nREPL and Piggieback, tooling you should be familiar with, no matter which editor you are using.

Show notes

So if inf-clojure is so great, why are all the cool kids talking about CIDER? Well, to understand that we need to talk about nREPL.

nREPL isn’t so much a REPL as it is a backend server for Clojure tooling. You can use it to power a REPL, or a documentation browser, or a refactoring tool, anything that can benefit from hooking into and interacting with a Clojure process.

You can send a message to an nREPL server, and it will send you one or more messages in return. If you send it an “eval” message, it will evaluate some code and send back the result. If you send it a “describe” message it will tell you all the operations it supports. Send it a “load-file” message and it will (re)load a certain file.

Messages are sent over the wire using a binary format called BEncode, but that’s not so important, conceptually you can think of a message as a map with key-value pairs.

All main Clojure IDEs and editors are powered by nREPL, including CIDER. Communicating programmatically with a REPL process over input and output streams is tedious, it also means it’s impossible to distinguish between a REPL result and other program output. In contrast nREPL provides a richer interaction model.

Emacs config

(package-install 'cider)

(add-hook 'clojure-mode-hook 'cider-mode)

;; To auto detect Chestnut or Figwheel projects
;; You can also just use the customize interface to set this variable
(setq cider-cljs-lein-repl
      "(cond
  (and (resolve 'user/run) (resolve 'user/browser-repl)) ;; Chestnut projects
  (eval '(do (user/run)
             (user/browser-repl)))

  (try
    (require 'figwheel-sidecar.repl-api)
    (resolve 'figwheel-sidecar.repl-api/start-figwheel!)
    (catch Throwable _))
  (eval '(do (figwheel-sidecar.repl-api/start-figwheel!)
             (figwheel-sidecar.repl-api/cljs-repl)))

  (try
    (require 'cemerick.piggieback)
    (resolve 'cemerick.piggieback/cljs-repl)
    (catch Throwable _))
  (eval '(cemerick.piggieback/cljs-repl (cljs.repl.rhino/repl-env)))

  :else
  (throw (ex-info \"Failed to initialize CLJS repl. Add com.cemerick/piggieback and optionally figwheel-sidecar to your project.\" {})))")

project.clj

To use Figwheel with CIDER, you need to have both Piggieback and Figwheel Sidecar as dependencies, and also make sure the Piggieback middleware is loaded in nREPL.

(defproject example "0.1.0"
  :dependencies [[org.clojure/clojure "1.9.0-alpha10"]
                 [org.clojure/clojurescript "1.9.89"]]

  :profiles {:dev
             {:dependencies [[figwheel-sidecar "0.5.4-7"]
                             [com.cemerick/piggieback "0.2.1"]]
              :repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}}})

After that switching an nREPL-based REPL to a Figwheel REPL is as easy as

(require 'figwheel-sidecar.repl-api)

(figwheel-sidecar.repl-api/start-figwheel!)
(figwheel-sidecar.repl-api/cljs-repl)