Skip to content

Commit

Permalink
Dynamically load middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
vspinu authored and bbatsov committed Sep 16, 2017
1 parent cf079c4 commit 48dc5d2
Show file tree
Hide file tree
Showing 25 changed files with 548 additions and 599 deletions.
38 changes: 19 additions & 19 deletions project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,27 @@

:profiles {:provided {:dependencies [[org.clojure/clojure "1.7.0"]]}

: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.enlighten/wrap-enlighten
cider.nrepl.middleware.format/wrap-format
cider.nrepl.middleware.info/wrap-info
cider.nrepl.middleware.inspect/wrap-inspect
cider.nrepl.middleware.macroexpand/wrap-macroexpand
cider.nrepl.middleware.ns/wrap-ns
cider.nrepl.middleware.spec/wrap-spec
cider.nrepl.middleware.out/wrap-out
:dev {:repl-options {:nrepl-middleware [cider.nrepl/wrap-apropos
cider.nrepl/wrap-classpath
cider.nrepl/wrap-complete
cider.nrepl/wrap-debug
cider.nrepl/wrap-enlighten
cider.nrepl/wrap-format
cider.nrepl/wrap-info
cider.nrepl/wrap-inspect
cider.nrepl/wrap-macroexpand
cider.nrepl/wrap-ns
cider.nrepl/wrap-out
cider.nrepl/wrap-refresh
cider.nrepl/wrap-resource
cider.nrepl/wrap-spec
cider.nrepl/wrap-stacktrace
cider.nrepl/wrap-test
cider.nrepl/wrap-trace
cider.nrepl/wrap-tracker
cider.nrepl/wrap-undef
cider.nrepl.middleware.pprint/wrap-pprint
cider.nrepl.middleware.pprint/wrap-pprint-fn
cider.nrepl.middleware.refresh/wrap-refresh
cider.nrepl.middleware.resource/wrap-resource
cider.nrepl.middleware.stacktrace/wrap-stacktrace
cider.nrepl.middleware.test/wrap-test
cider.nrepl.middleware.trace/wrap-trace
cider.nrepl.middleware.track-state/wrap-tracker
cider.nrepl.middleware.undef/wrap-undef
cider.nrepl.middleware.version/wrap-version]}
:dependencies [[org.clojure/tools.nrepl "0.2.13"]
;; For developing the Leiningen plugin.
Expand Down
433 changes: 389 additions & 44 deletions src/cider/nrepl.clj

Large diffs are not rendered by default.

27 changes: 6 additions & 21 deletions src/cider/nrepl/middleware/apropos.clj
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
and may be case senstive. Types returned correspond to Apropos types.
Docstring search returns the full doc; symbol search returns an abbreviated
version."
[ns query search-ns docs? privates? case-sensitive? filter-regexps]
[{:keys [ns query search-ns docs? privates? case-sensitive? filter-regexps]}]
(let [ns-vars (if privates? ns-interns ns-publics)
var-doc* (if docs? var-doc (partial var-doc 1))
search-prop (if docs? var-doc var-name)
Expand All @@ -61,24 +61,9 @@

;;; ## Middleware

(defn handle-apropos
"Return a sequence of vars whose name matches the query pattern, or if
specified, having the pattern in their docstring."
[{:keys [ns query search-ns docs? privates? case-sensitive? filter-regexps] :as msg}]
{:apropos-matches (find-symbols ns query search-ns docs? privates? case-sensitive? filter-regexps)})
(defn apropos [msg]
{:apropos-matches (find-symbols msg)})

(defn wrap-apropos
"Middleware that handles apropos requests"
[handler]
(with-safe-transport handler
"apropos" handle-apropos))

;; nREPL middleware descriptor info
(set-descriptor!
#'wrap-apropos
{:handles
{"apropos"
{:doc (:doc (meta #'handle-apropos))
:requires {"query" "The search query."}
:optional {"filter-regexps" "All vars from namespaces matching any regexp from this list would be dropped from the result."}
:returns {"apropos-matches" "A list of matching symbols."}}}})
(defn handle-apropos [handler msg]
(with-safe-transport handler msg
"apropos" apropos))
13 changes: 2 additions & 11 deletions src/cider/nrepl/middleware/classpath.clj
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,6 @@
(defn classpath-reply [msg]
{:classpath (classpath)})

(defn wrap-classpath
"Middleware that provides the java classpath."
[handler]
(with-safe-transport handler
(defn handle-classpath [handler msg]
(with-safe-transport handler msg
"classpath" classpath-reply))

(set-descriptor!
#'wrap-classpath
{:handles
{"classpath"
{:doc "Obtain a list of entries in the Java classpath."
:returns {"classpath" "A list of the Java classpath entries."}}}})
27 changes: 2 additions & 25 deletions src/cider/nrepl/middleware/complete.clj
Original file line number Diff line number Diff line change
Expand Up @@ -38,31 +38,8 @@
(jvm-complete-utils/flush-caches)
{})

(defn wrap-complete
"Middleware that looks up possible functions for the given (partial) symbol."
[handler]
(with-safe-transport handler
(defn handle-complete [handler msg]
(with-safe-transport handler msg
"complete" complete-reply
"complete-doc" doc-reply
"complete-flush-caches" flush-caches-reply))

(set-descriptor!
#'wrap-complete
(cljs/requires-piggieback
{:requires #{#'session/session}
:handles
{"complete"
{:doc "Return a list of symbols matching the specified (partial) symbol."
:requires {"ns" "The symbol's namespace"
"symbol" "The symbol to lookup"
"session" "The current session"}
:optional {"context" "Completion context for compliment."
"extra-metadata" "List of extra-metadata fields. Possible values: arglists, doc."}
:returns {"completions" "A list of possible completions"}}
"complete-doc"
{:doc "Retrieve documentation suitable for display in completion popup"
:requires {"ns" "The symbol's namespace"
"symbol" "The symbol to lookup"}
:returns {"completion-doc" "Symbol's documentation"}}
"complete-flush-caches"
{:doc "Forces the completion backend to repopulate all its caches"}}}))
55 changes: 12 additions & 43 deletions src/cider/nrepl/middleware/debug.clj
Original file line number Diff line number Diff line change
Expand Up @@ -603,46 +603,15 @@ this map (identified by a key), and will `dissoc` it afterwards."}
(response-for msg :status :done :list)
(transport/send (:transport msg))))

(defn wrap-debug [h]
(fn [{:keys [op input session] :as msg}]
(case op
"eval" (do (when (instance? clojure.lang.Atom session)
(swap! session assoc #'*skip-breaks* (atom nil)))
(h (maybe-debug msg)))
"debug-instrumented-defs" (instrumented-defs-reply msg)
"debug-input" (when-let [pro (@promises (:key msg))]
(deliver pro input))
"init-debugger" (initialize msg)
;; else
(h msg))))

(set-descriptor!
#'wrap-debug
(cljs/requires-piggieback
{:expects #{"eval"}
:requires #{#'pprint/wrap-pprint-fn #'session/session}
:handles
{"debug-input"
{:doc "Read client input on debug action."
:requires {"input" "The user's reply to the input request."}
:returns {"status" "done"}}
"init-debugger"
{:doc "Initialize the debugger so that `breakpoint` works correctly.
This usually does not respond immediately. It sends a response when a
breakpoint is reached or when the message is discarded."
:requires {"id" "A message id that will be responded to when a breakpoint is reached."}}
"debug-instrumented-defs"
{:doc "Return an alist of definitions currently thought to be instrumented on each namespace.
Due to Clojure's versatility, this could include false postives, but
there will not be false negatives. Instrumentations inside protocols
are not listed."
:returns {"status" "done"
"list" "The alist of (NAMESPACE . VARS) that are thought to be instrumented."}}
"debug-middleware"
{:doc "Debug a code form or fall back on regular eval."
:requires {"id" "A message id that will be responded to when a breakpoint is reached."
"code" "Code to debug, there must be a #dbg or a #break reader macro in it, or nothing will happen."
"file" "File where the code is located."
"ns" "Passed to \"eval\"."
"point" "Position in the file where the provided code begins."}
:returns {"status" "\"done\" if the message will no longer be used, or \"need-debug-input\" during debugging sessions"}}}}))
(defn handle-debug
[handler {:keys [op input session] :as msg}]
(case op
"eval" (do (when (instance? clojure.lang.Atom session)
(swap! session assoc #'*skip-breaks* (atom nil)))
(handler (maybe-debug msg)))
"debug-instrumented-defs" (instrumented-defs-reply msg)
"debug-input" (when-let [pro (@promises (:key msg))]
(deliver pro input))
"init-debugger" (initialize msg)
;; else
(handler msg)))
16 changes: 5 additions & 11 deletions src/cider/nrepl/middleware/enlighten.clj
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,8 @@
;; (ins/print-form form1 true)
(eval form1)))

(defn wrap-enlighten [h]
(fn [{:keys [op enlighten] :as msg}]
(if (and (= op "eval") enlighten)
(h (assoc msg :eval "cider.nrepl.middleware.enlighten/eval-with-enlighten"))
(h msg))))

(set-descriptor!
#'wrap-enlighten
;; We need to come before wrap-debug, so that the debugger can still
;; work if enlighten-mode is on.
{:expects #{"eval" #'d/wrap-debug}})
(defn handle-enlighten
[h {:keys [op enlighten] :as msg}]
(if (and (= op "eval") enlighten)
(h (assoc msg :eval "cider.nrepl.middleware.enlighten/eval-with-enlighten"))
(h msg)))
21 changes: 2 additions & 19 deletions src/cider/nrepl/middleware/format.clj
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,7 @@
[{:keys [edn pprint-fn] :as msg}]
{:formatted-edn (format-edn edn pprint-fn)})

(defn wrap-format
"Middleware that provides code formatting."
[handler]
(with-safe-transport handler
(defn handle-format [handler msg]
(with-safe-transport handler msg
"format-code" format-code-reply
"format-edn" format-edn-reply))

(set-descriptor!
#'wrap-format
{:requires #{#'pprint/wrap-pprint-fn}
:handles
{"format-code"
{:doc "Reformats the given Clojure code, returning the result as a string."
:requires {"code" "The code to format."}
:returns {"formatted-code" "The formatted code."}}
"format-edn"
{:doc "Reformats the given EDN data, returning the result as a string."
:requires {"edn" "The data to format."}
:optional {"print-right-margin" "The maximum column width of the formatted result."
"pprint-fn" "Fully qualified name of the print function to be used."}
:returns {"formatted-edn" "The formatted data."}}}})
29 changes: 2 additions & 27 deletions src/cider/nrepl/middleware/info.clj
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
[cider.nrepl.middleware.util.misc :as u]
[cider.nrepl.middleware.util.meta :as m]
[cljs-tooling.info :as cljs-info]
[clojure.tools.nrepl.middleware :refer [set-descriptor!]]
[clojure.tools.nrepl.middleware.session :as session]
[cider.nrepl.middleware.util.spec :as spec]))

(defn- boot-class-loader
Expand Down Expand Up @@ -280,31 +278,8 @@
{:inputs (format-arglists [inputs])})
(catch Throwable _ {:status :no-eldoc})))

(defn wrap-info
"Middleware that looks up info for a symbol within the context of a particular namespace."
[handler]
(with-safe-transport handler
(defn handle-info [handler msg]
(with-safe-transport handler msg
"info" info-reply
"eldoc" eldoc-reply
"eldoc-datomic-query" eldoc-datomic-query-reply))

(set-descriptor!
#'wrap-info
(cljs/requires-piggieback
{:requires #{#'session/session}
:handles
{"info"
{:doc "Return a map of information about the specified symbol."
:requires {"symbol" "The symbol to lookup"
"ns" "The current namespace"}
:returns {"status" "done"}}
"eldoc"
{:doc "Return a map of information about the specified symbol."
:requires {"symbol" "The symbol to lookup"
"ns" "The current namespace"}
:returns {"status" "done"}}
"eldoc-datomic-query"
{:doc "Return a map containing the inputs of the datomic query."
:requires {"symbol" "The symbol to lookup"
"ns" "The current namespace"}
:returns {"status" "done"}}}}))
65 changes: 11 additions & 54 deletions src/cider/nrepl/middleware/inspect.clj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
[cider.nrepl.middleware.util.misc :as u]
[clojure.tools.nrepl.middleware :refer [set-descriptor!]]
[clojure.tools.nrepl.misc :refer [response-for]]
[clojure.tools.nrepl.middleware.pr-values :refer [pr-values]]
[clojure.tools.nrepl.transport :as transport])
(:import clojure.tools.nrepl.transport.Transport))

Expand Down Expand Up @@ -82,56 +81,14 @@
(try (success msg (swap-inspector! msg inspect/set-page-size (:page-size msg)))
(catch Exception e (failure msg e :inspect-set-page-size-error))))

(defn wrap-inspect
"Middleware that adds a value inspector option to the eval op. Passing a
non-nil value in the `:inspect` slot will cause the last value returned by
eval to be inspected. Returns a string representation of the resulting
inspector's state in the `:value` slot."
[handler]
(fn [{:keys [op] :as msg}]
(case op
"eval" (eval-reply handler msg)
"inspect-pop" (pop-reply msg)
"inspect-push" (push-reply msg)
"inspect-refresh" (refresh-reply msg)
"inspect-get-path" (get-path-reply msg)
"inspect-next-page" (next-page-reply msg)
"inspect-prev-page" (prev-page-reply msg)
"inspect-set-page-size" (set-page-size-reply msg)
(handler msg))))

(set-descriptor!
#'wrap-inspect
(cljs/expects-piggieback
{:requires #{"clone" #'pr-values}
:expects #{"eval"}
:handles {"inspect-pop"
{:doc "Moves one level up in the inspector stack."
:requires {"session" "The current session"}
:returns {"status" "\"done\""}}
"inspect-push"
{:doc "Inspects the inside value specified by index."
:requires {"idx" "Index of the internal value currently rendered."
"session" "The current session"}
:returns {"status" "\"done\""}}
"inspect-refresh"
{:doc "Re-renders the currently inspected value."
:requires {"session" "The current session"}
:returns {"status" "\"done\""}}
"inspect-get-path"
{:doc "Returns the path to the current position in the inspected value."
:requires {"session" "The current session"}
:returns {"status" "\"done\""}}
"inspect-next-page"
{:doc "Jumps to the next page in paginated collection view."
:requires {"session" "The current session"}
:returns {"status" "\"done\""}}
"inspect-prev-page"
{:doc "Jumps to the previous page in paginated collection view."
:requires {"session" "The current session"}
:returns {"status" "\"done\""}}
"inspect-set-page-size"
{:doc "Sets the page size in paginated view to specified value."
:requires {"page-size" "New page size."
"session" "The current session"}
:returns {"status" "\"done\""}}}}))
(defn handle-inspect [handler msg]
(case (:op msg)
"eval" (eval-reply handler msg)
"inspect-pop" (pop-reply msg)
"inspect-push" (push-reply msg)
"inspect-refresh" (refresh-reply msg)
"inspect-get-path" (get-path-reply msg)
"inspect-next-page" (next-page-reply msg)
"inspect-prev-page" (prev-page-reply msg)
"inspect-set-page-size" (set-page-size-reply msg)
(handler msg)))
23 changes: 2 additions & 21 deletions src/cider/nrepl/middleware/macroexpand.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@
[cider.nrepl.middleware.util.misc :as u]
[cljs-tooling.util.analysis :as cljs-ana]
[clojure.pprint :as pp]
[clojure.tools.nrepl.middleware :refer [set-descriptor!]]
[clojure.tools.nrepl.misc :refer [response-for]]
[clojure.tools.nrepl.middleware.session :as session]
[clojure.tools.reader :as reader]
[clojure.walk :as walk])
(:import [clojure.lang Var]))
Expand Down Expand Up @@ -221,22 +218,6 @@
(defn macroexpansion-reply [msg]
{:expansion (macroexpansion msg)})

(defn wrap-macroexpand
"Middleware that provides a macroexpand op."
[handler]
(with-safe-transport handler
(defn handle-macroexpand [handler msg]
(with-safe-transport handler msg
"macroexpand" [macroexpansion-reply :macroexpand-error]))

(set-descriptor!
#'wrap-macroexpand
(cljs/requires-piggieback
{:requires #{#'session/session}
:handles
{"macroexpand"
{:doc "Produces macroexpansion of some form using the given expander."
:requires {"code" "The form to macroexpand."}
:optional {"ns" "The namespace in which to perform the macroexpansion. Defaults to 'user for Clojure and 'cljs.user for ClojureScript."
"expander" "The macroexpansion function to use. Possible values are \"macroexpand-1\", \"macroexpand\", or \"macroexpand-all\". Defaults to \"macroexpand\"."
"display-namespaces" "How to print namespace-qualified symbols in the result. Possible values are \"qualified\" to leave all namespaces qualified, \"none\" to elide all namespaces, or \"tidy\" to replace namespaces with their aliases in the given namespace. Defaults to \"qualified\"."
"print-meta" "If truthy, also print metadata of forms."}
:returns {"expansion" "The macroexpanded form."}}}}))

0 comments on commit 48dc5d2

Please sign in to comment.