Skip to content

Commit

Permalink
Allow predicates in plugin and middleware lists
Browse files Browse the repository at this point in the history
  • Loading branch information
raxod502 committed Mar 22, 2018
1 parent 1ee97c4 commit 80bbf96
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* [#2191](https://github.com/clojure-emacs/cider/issues/2191): Add support for jacking-in just with the `clojure` command-line tool and `tools.deps`.
* Make it possible to start a Nashorn ClojureScript REPL.
* [#2235](https://github.com/clojure-emacs/cider/pull/2235): Make the REPL ignore blank input rather than evaluating.
* [#2238](https://github.com/clojure-emacs/cider/pull/2238): Allow specifying predicates for entries in `cider-jack-in-lein-plugins` and `cider-jack-in-nrepl-middlewares`.

### Bugs Fixed

Expand Down
53 changes: 48 additions & 5 deletions cider.el
Original file line number Diff line number Diff line change
Expand Up @@ -358,17 +358,60 @@ specifying the artifact ID, and the second element the version number."
(string :tag "Version"))))

(defvar cider-jack-in-lein-plugins nil
"List of Leiningen plugins where elements are lists of artifact name and version.")
"List of Leiningen plugins to be injected at jack-in.
Each element is a list of artifact name and version, followed optionally by
keyword arguments. The only keyword argument currently accepted is
`:predicate', which should be given a function that takes the list (name,
version, and keyword arguments) and returns non-nil to indicate that the
plugin should actually be injected. (This is useful primarily for packages
that extend CIDER, not for users. For example, a refactoring package might
want to inject some middleware only when within a project context.)")
(put 'cider-jack-in-lein-plugins 'risky-local-variable t)
(cider-add-to-alist 'cider-jack-in-lein-plugins
"cider/cider-nrepl" (upcase cider-version))

(defun cider-jack-in-normalized-lein-plugins ()
"Return a normalized list of Leiningen plugins to be injected.
See `cider-jack-in-lein-plugins' for the format, except that the list
returned by this function does not include keyword arguments."
(thread-last cider-jack-in-lein-plugins
(seq-filter
(lambda (spec)
(if-let* ((pred (plist-get (seq-drop spec 2) :predicate)))
(funcall pred spec)
t)))
(mapcar
(lambda (spec)
(seq-take spec 2)))))

(defvar cider-jack-in-nrepl-middlewares nil
"List of Clojure variable names.
Each of these Clojure variables should hold a vector of nREPL middlewares.")
Each of these Clojure variables should hold a vector of nREPL middlewares.
Instead of a string, an element can be a list containing a string followed
by optional keyword arguments. The only keyword argument currently
accepted is `:predicate', which should be given a function that takes the
list (string and keyword arguments) and returns non-nil to indicate that
the middlewares should actually be injected.")
(put 'cider-jack-in-nrepl-middlewares 'risky-local-variable t)
(add-to-list 'cider-jack-in-nrepl-middlewares "cider.nrepl/cider-middleware")

(defun cider-jack-in-normalized-nrepl-middlewares ()
"Return a normalized list of middleware variable names.
See `cider-jack-in-nrepl-middlewares' for the format, except that the list
returned by this function only contains strings."
(thread-last cider-jack-in-nrepl-middlewares
(seq-filter
(lambda (spec)
(or (not (listp spec))
(if-let* ((pred (plist-get (cdr spec) :predicate)))
(funcall pred spec)
t))))
(mapcar
(lambda (spec)
(if (listp spec)
(car spec)
spec)))))

(defun cider--list-as-boot-artifact (list)
"Return a boot artifact string described by the elements of LIST.
LIST should have the form (ARTIFACT-NAME ARTIFACT-VERSION). The returned
Expand Down Expand Up @@ -483,14 +526,14 @@ dependencies."
(cider-add-clojure-dependencies-maybe
cider-jack-in-dependencies)
cider-jack-in-dependencies-exclusions
cider-jack-in-lein-plugins))
(cider-jack-in-normalized-lein-plugins)))
("boot" (cider-boot-jack-in-dependencies
global-opts
params
(cider-add-clojure-dependencies-maybe
cider-jack-in-dependencies)
cider-jack-in-lein-plugins
cider-jack-in-nrepl-middlewares))
(cider-jack-in-normalized-lein-plugins)
(cider-jack-in-normalized-nrepl-middlewares)))
("clojure" (cider-clojure-jack-in-dependencies
global-opts
params
Expand Down
57 changes: 56 additions & 1 deletion test/cider-tests.el
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,62 @@
:to-equal "-C -o -i \"(require 'cider.tasks)\" -d org.clojure/tools.nrepl\\:0.2.12 -d cider/cider-nrepl\\:0.11.0 cider.tasks/add-middleware -m cider.nrepl/cider-middleware repl -s wait"))
(it "can concat in a gradle project"
(expect (cider-inject-jack-in-dependencies "-m" "--no-daemon clojureRepl" "gradle")
:to-equal "-m --no-daemon clojureRepl"))))
:to-equal "-m --no-daemon clojureRepl")))

(describe "when there are predicates"
:var (plugins-predicate middlewares-predicate)

(before-each
(fset 'plugins-predicate (lambda (&rest _) t))
(fset 'middlewares-predicate (lambda (&rest _) t))
(setq-local cider-jack-in-lein-plugins '(("refactor-nrepl" "2.0.0" :predicate plugins-predicate) ("cider/cider-nrepl" "0.11.0")))
(setq-local cider-jack-in-nrepl-middlewares '(("refactor-nrepl.middleware/wrap-refactor" :predicate middlewares-predicate) "cider.nrepl/cider-middleware" ("another/middleware"))))
(it "includes plugins whose predicates return true"
(expect (cider-jack-in-normalized-lein-plugins)
:to-equal '(("refactor-nrepl" "2.0.0") ("cider/cider-nrepl" "0.11.0"))))
(it "includes middlewares whose predicates return true"
(expect (cider-jack-in-normalized-nrepl-middlewares)
:to-equal '("refactor-nrepl.middleware/wrap-refactor" "cider.nrepl/cider-middleware" "another/middleware")))
(it "ignores plugins whose predicates return false"
(spy-on 'plugins-predicate :and-return-value nil)
(expect (cider-jack-in-normalized-lein-plugins)
:to-equal '(("cider/cider-nrepl" "0.11.0"))))
(it "ignores plugins whose predicates return false"
(spy-on 'middlewares-predicate :and-return-value nil)
(expect (cider-jack-in-normalized-nrepl-middlewares)
:to-equal '("cider.nrepl/cider-middleware" "another/middleware")))
(it "calls plugin predicates with the whole list entry"
(spy-on 'plugins-predicate)
(cider-jack-in-normalized-lein-plugins)
(expect 'plugins-predicate
:to-have-been-called-with '("refactor-nrepl" "2.0.0" :predicate plugins-predicate)))
(it "calls middleware predicates with the whole list entry"
(spy-on 'middlewares-predicate)
(cider-jack-in-normalized-nrepl-middlewares)
(expect 'middlewares-predicate
:to-have-been-called-with '("refactor-nrepl.middleware/wrap-refactor" :predicate middlewares-predicate)))
(it "only calls plugin predicates for their own entries"
(spy-on 'plugins-predicate)
(cider-jack-in-normalized-lein-plugins)
(expect 'plugins-predicate :to-have-been-called-times 1))
(it "only calls middleware predicates for their own entries"
(spy-on 'middlewares-predicate)
(cider-jack-in-normalized-nrepl-middlewares)
(expect 'middlewares-predicate :to-have-been-called-times 1)))

(describe "when the middleware and plugin lists have been normalized"
(before-each
(spy-on 'cider-jack-in-normalized-nrepl-middlewares
:and-return-value '("refactor-nrepl.middleware/wrap-refactor" "cider.nrepl/cider-middleware"))
(spy-on 'cider-jack-in-normalized-lein-plugins
:and-return-value '(("refactor-nrepl" "2.0.0") ("cider/cider-nrepl" "0.11.0")))
(setq-local cider-jack-in-dependencies-exclusions '()))
(it "uses them in a lein project"
(expect (cider-inject-jack-in-dependencies "" "repl :headless" "lein")
:to-equal "update-in :dependencies conj \\[org.clojure/tools.nrepl\\ \\\"0.2.12\\\"\\] -- update-in :plugins conj \\[refactor-nrepl\\ \\\"2.0.0\\\"\\] -- update-in :plugins conj \\[cider/cider-nrepl\\ \\\"0.11.0\\\"\\] -- repl :headless"))
(it "uses them in a boot project"
(expect (cider-inject-jack-in-dependencies "" "repl -s wait" "boot")
:to-equal "-i \"(require 'cider.tasks)\" -d org.clojure/tools.nrepl\\:0.2.12 -d refactor-nrepl\\:2.0.0 -d cider/cider-nrepl\\:0.11.0 cider.tasks/add-middleware -m refactor-nrepl.middleware/wrap-refactor -m cider.nrepl/cider-middleware repl -s wait"))))

(describe "cider-jack-in-auto-inject-clojure"
(it "injects `cider-minimum-clojure-version' when `cider-jack-in-auto-inject-clojure' is set to minimal"
Expand Down

0 comments on commit 80bbf96

Please sign in to comment.