Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ middleware to to `:nrepl-middleware` under `:repl-options`.
[cider.nrepl.middleware.apropos/wrap-apropos
cider.nrepl.middleware.classpath/wrap-classpath
cider.nrepl.middleware.complete/wrap-complete
cider.nrepl.middleware.debug/wrap-debug
cider.nrepl.middleware.format/wrap-format
cider.nrepl.middleware.info/wrap-info
cider.nrepl.middleware.inspect/wrap-inspect
Expand Down Expand Up @@ -90,6 +91,7 @@ Middleware | Op(s) | Description
`wrap-apropos` | `apropos` | Pattern search for symbols and documentation.
`wrap-classpath` | `classpath` | Java classpath.
`wrap-complete` | `complete` | Simple completion. Supports both Clojure & ClojureScript.
`wrap-debug` | `init-debugger` | Establish a channel for `cider-debug` commands.
`wrap-format` | `format-(code/edn)` | Code and data formatting.
`wrap-info` | `info/eldoc` | File/line, arglists, docstrings and other metadata for vars.
`wrap-inspect` |`inspect-(start/refresh/pop/push/reset)` | Inspect a Clojure expression.
Expand Down
2 changes: 2 additions & 0 deletions project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[compliment "0.2.1-SNAPSHOT"]
[cljs-tooling "0.1.5-SNAPSHOT"]
[debugger "0.1.6"]
[cljfmt "0.1.10"]
[org.tcrawley/dynapath "0.2.3"]
[org.clojure/tools.nrepl "0.2.7"]
Expand All @@ -24,6 +25,7 @@
:dev {:repl-options {:nrepl-middleware [cider.nrepl.middleware.apropos/wrap-apropos
cider.nrepl.middleware.classpath/wrap-classpath
cider.nrepl.middleware.complete/wrap-complete
cider.nrepl.middleware.debug/wrap-debug
cider.nrepl.middleware.format/wrap-format
cider.nrepl.middleware.info/wrap-info
cider.nrepl.middleware.inspect/wrap-inspect
Expand Down
2 changes: 2 additions & 0 deletions src/cider/nrepl.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
[cider.nrepl.middleware.apropos]
[cider.nrepl.middleware.classpath]
[cider.nrepl.middleware.complete]
[cider.nrepl.middleware.debug]
[cider.nrepl.middleware.format]
[cider.nrepl.middleware.info]
[cider.nrepl.middleware.inspect]
Expand All @@ -20,6 +21,7 @@
'[cider.nrepl.middleware.apropos/wrap-apropos
cider.nrepl.middleware.classpath/wrap-classpath
cider.nrepl.middleware.complete/wrap-complete
cider.nrepl.middleware.debug/wrap-debug
cider.nrepl.middleware.format/wrap-format
cider.nrepl.middleware.info/wrap-info
cider.nrepl.middleware.inspect/wrap-inspect
Expand Down
59 changes: 59 additions & 0 deletions src/cider/nrepl/middleware/debug.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
(ns cider.nrepl.middleware.debug
(:require [clojure.tools.nrepl.transport :as transport]
[clojure.tools.nrepl.middleware :refer [set-descriptor!]]
[clojure.tools.nrepl.misc :refer [response-for]]
[cider.nrepl.middleware.util.instrument :refer [instrument]]
[debugger.core :refer [break]]))

;;;; ## Interaction with the client
;;; `wrap-debug` receives an initial message from the client, stores
;;; it in `debugger-message`, and `breakpoint` answers it.
(def debugger-message (atom nil))

(defn wrap-debug [h]
(fn [{:keys [op force] :as msg}]
(if (= "init-debugger" op)
(let [stored-message @debugger-message]
(if (and stored-message (not force))
(transport/send (:transport msg)
(response-for msg :status :done))
(do (when stored-message
(transport/send (:transport stored-message)
(response-for stored-message :status :done)))
;; TODO: Redefine this in the session binding map, see inspect.clj.
(reset! debugger-message msg))))
(h msg))))

(defn breakpoint
"Send value and coordinates to the client through the debug channel.
Sends a response to the message stored in debugger-message."
[value extras]
;; Notify cider that a (break) is incoming, along with the value of
;; the instrumented sexp and instructions on how to find it in the
;; code.
(transport/send
(:transport @debugger-message)
(response-for @debugger-message
(assoc extras
:value (pr-str value)
:breakfunction nil)))
;; Send the actual break.
(binding [*out* (new java.io.StringWriter)]
(break value)))

(defn instrument-and-eval
"Instrument form and evaluate the result.
Call cider.nrepl.middleware.util.instrument."
[ex form]
(eval
(instrument (merge {:coor [], :breakfunction breakpoint} ex)
form)))

(set-descriptor!
#'wrap-debug
{:handles
{"init-debugger"
{:doc "Initialize the debugger so that #'breakpoint works correctly.
This does not respond immediately. It sends a response when a breakpoint is reached."
:requires {"id" "A message id that will be responded to when a breakpoint is reached."}
:returns {"status" "debugging"}}}})
Loading