Skip to content

Commit edddc70

Browse files
committed
Merge pull request #170 from Malabarba/debug
Debugging in Cider
2 parents 2f0365e + 928be13 commit edddc70

File tree

6 files changed

+644
-0
lines changed

6 files changed

+644
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ middleware to `:nrepl-middleware` under `:repl-options`.
3232
[cider.nrepl.middleware.apropos/wrap-apropos
3333
cider.nrepl.middleware.classpath/wrap-classpath
3434
cider.nrepl.middleware.complete/wrap-complete
35+
cider.nrepl.middleware.debug/wrap-debug
3536
cider.nrepl.middleware.format/wrap-format
3637
cider.nrepl.middleware.info/wrap-info
3738
cider.nrepl.middleware.inspect/wrap-inspect
@@ -90,6 +91,7 @@ Middleware | Op(s) | Description
9091
`wrap-apropos` | `apropos` | Pattern search for symbols and documentation.
9192
`wrap-classpath` | `classpath` | Java classpath.
9293
`wrap-complete` | `complete` | Simple completion. Supports both Clojure & ClojureScript.
94+
`wrap-debug` | `init-debugger` | Establish a channel for `cider-debug` commands.
9395
`wrap-format` | `format-(code/edn)` | Code and data formatting.
9496
`wrap-info` | `info/eldoc` | File/line, arglists, docstrings and other metadata for vars.
9597
`wrap-inspect` |`inspect-(start/refresh/pop/push/reset)` | Inspect a Clojure expression.

project.clj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
:url "http://www.eclipse.org/legal/epl-v10.html"}
1212
:dependencies [[compliment "0.2.1-SNAPSHOT"]
1313
[cljs-tooling "0.1.5-SNAPSHOT"]
14+
[debugger "0.1.6"]
1415
[cljfmt "0.1.10"]
1516
[org.tcrawley/dynapath "0.2.3"]
1617
[org.clojure/tools.nrepl "0.2.7"]
@@ -24,6 +25,7 @@
2425
:dev {:repl-options {:nrepl-middleware [cider.nrepl.middleware.apropos/wrap-apropos
2526
cider.nrepl.middleware.classpath/wrap-classpath
2627
cider.nrepl.middleware.complete/wrap-complete
28+
cider.nrepl.middleware.debug/wrap-debug
2729
cider.nrepl.middleware.format/wrap-format
2830
cider.nrepl.middleware.info/wrap-info
2931
cider.nrepl.middleware.inspect/wrap-inspect

src/cider/nrepl.clj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
[cider.nrepl.middleware.apropos]
44
[cider.nrepl.middleware.classpath]
55
[cider.nrepl.middleware.complete]
6+
[cider.nrepl.middleware.debug]
67
[cider.nrepl.middleware.format]
78
[cider.nrepl.middleware.info]
89
[cider.nrepl.middleware.inspect]
@@ -20,6 +21,7 @@
2021
'[cider.nrepl.middleware.apropos/wrap-apropos
2122
cider.nrepl.middleware.classpath/wrap-classpath
2223
cider.nrepl.middleware.complete/wrap-complete
24+
cider.nrepl.middleware.debug/wrap-debug
2325
cider.nrepl.middleware.format/wrap-format
2426
cider.nrepl.middleware.info/wrap-info
2527
cider.nrepl.middleware.inspect/wrap-inspect
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
(ns cider.nrepl.middleware.debug
2+
(:require [clojure.tools.nrepl.transport :as transport]
3+
[clojure.tools.nrepl.middleware :refer [set-descriptor!]]
4+
[clojure.tools.nrepl.misc :refer [response-for]]
5+
[cider.nrepl.middleware.util.instrument :refer [instrument]]
6+
[debugger.core :refer [break]]))
7+
8+
;;;; ## Interaction with the client
9+
;;; `wrap-debug` receives an initial message from the client, stores
10+
;;; it in `debugger-message`, and `breakpoint` answers it.
11+
(def debugger-message (atom nil))
12+
13+
(defn wrap-debug [h]
14+
(fn [{:keys [op force] :as msg}]
15+
(if (= "init-debugger" op)
16+
(let [stored-message @debugger-message]
17+
(if (and stored-message (not force))
18+
(transport/send (:transport msg)
19+
(response-for msg :status :done))
20+
(do (when stored-message
21+
(transport/send (:transport stored-message)
22+
(response-for stored-message :status :done)))
23+
;; TODO: Redefine this in the session binding map, see inspect.clj.
24+
(reset! debugger-message msg))))
25+
(h msg))))
26+
27+
(defn breakpoint
28+
"Send value and coordinates to the client through the debug channel.
29+
Sends a response to the message stored in debugger-message."
30+
[value extras]
31+
;; Notify cider that a (break) is incoming, along with the value of
32+
;; the instrumented sexp and instructions on how to find it in the
33+
;; code.
34+
(transport/send
35+
(:transport @debugger-message)
36+
(response-for @debugger-message
37+
(assoc extras
38+
:value (pr-str value)
39+
:breakfunction nil)))
40+
;; Send the actual break.
41+
(binding [*out* (new java.io.StringWriter)]
42+
(break value)))
43+
44+
(defn instrument-and-eval
45+
"Instrument form and evaluate the result.
46+
Call cider.nrepl.middleware.util.instrument."
47+
[ex form]
48+
(eval
49+
(instrument (merge {:coor [], :breakfunction breakpoint} ex)
50+
form)))
51+
52+
(set-descriptor!
53+
#'wrap-debug
54+
{:handles
55+
{"init-debugger"
56+
{:doc "Initialize the debugger so that #'breakpoint works correctly.
57+
This does not respond immediately. It sends a response when a breakpoint is reached."
58+
:requires {"id" "A message id that will be responded to when a breakpoint is reached."}
59+
:returns {"status" "debugging"}}}})

0 commit comments

Comments
 (0)