Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a better way to debug clojure code?

Tags:

clojure

I've been working with Clojure for few weeks now, primarily with Lein+Luminus framework. I've been looking for a way to debug code while on the REPL.

I really like the way how pry(on Ruby) works, when it comes to debugging and runtime invocation. Is there an equivalent to pry for clojure code? or probably a technique/tool that I've missed?

like image 258
Coding active Avatar asked May 19 '15 10:05

Coding active


1 Answers

There are two paths to consider to improve your REPL and debugging experience:

  • Using a REPL and debugger integrated with your editor or IDE of choice
  • Using an embedded nREPL server

The first is an essential part of setting up your local Clojure development environment and should be done regardless. The second option, using an embedded nREPL server, is closer in usage to how you would use a binding.pry call in your code since it gives you access to the running application, but it isn't used to stop execution at a certain point, but rather give you a REPL with access to your running application and it doesn't provide any additional debugging features on its own.

Editor/IDE with REPL and Debugger

Text editors like Emacs and Vim have excellent Clojure support (both for editing and interacting with a REPL), and most Java IDE's have Clojure support as well.

At this point (May 2015) I'd highly recommend trying Jetbrain's Intellij IDEA with the Cursive plugin because of its excellent support for debugging. You can use the free community edition of Intellij, and the Cursive plugin is (at this point) free as well.

Intellij IDEA

To install Cursive, you go into Intellij's settings, add the correct Cursive plugin repository for the version of Intellij you have, install Cursive, and restart the IDE.

Once Cursive is active, you can simply open an existing Leiningen project in Intellij via "File > Open...". To get a REPL running, click "Run > Edit Configurations" in the main menu. In the window that appears, click the "+" button at the top left and select "Clojure REPL > Local". I'd change the name of the run configuration from "Unnamed" to something like "REPL", but otherwise keep the defaults and press "OK" to save the run configuration.

Now you have a way to run a REPL set up for the project you've opened. You can now click "Run > Run 'REPL'" (or whatever you named that run configuration) for a normal REPL, or better yet click "Run > Debug 'REPL'" to boot up the REPL in a debug mode that allows you to use Intellij's debugging features to debug your Clojure code. Set break points, add breakpoint conditions, run code and inspect frames, variables, etc., like you would in any debugger.

In your case, you'd want to click "Run > Debug 'REPL'" and then execute in that REPL the code you use to boot up your application.

Embedded nREPL Server

The above approach assumes that you first start a Clojure REPL and then boot up your application. If instead you want to have your application boot up normally and then optionally get a REPL that lives inside the running Clojure program, using nREPL directly is your best option.

From its own README:

nREPL is a Clojure network REPL that provides a REPL server and client, along with some common APIs of use to IDEs and other tools that may need to evaluate Clojure code in remote environments.

You should follow these instructions to add a running nREPL server to your application, but here is the most important part:

=> (use '[clojure.tools.nrepl.server :only (start-server stop-server)])
nil
=> (defonce server (start-server :port 7888))
#'user/server

Once you have a running nREPL server as part of your Clojure application, you can attach to it using your editor or IDE of choice (each editor/IDE has a different way of doing this, but most expose a way to attach to a running REPL by providing the host (usually localhost) and the port on which an nREPL server is running), or by invoking Leiningen directly at the command-line like this:

lein repl :connect <port>

You can specify the <port> when you configure the nREPL server as shown above. It also prints it out when it starts.

like image 176
semperos Avatar answered Oct 12 '22 10:10

semperos