Skip to content

Commit

Permalink
Inject cider REPL dependencies at cider-jack-in
Browse files Browse the repository at this point in the history
So users don't have to fiddle with profiles.clj and the like, see
details in clojure-emacs#1531 Supports both leiningen and boot. Additionally there is
a defcustom `cider-inject-dependencies-at-jack-in` to control this
functionality (defaults to t); other tools (like clj-refactor) can
modify `cider-jack-in-dependencies`, `cider-jack-in-lein-plugins` and
`cider-jack-in-nrepl-middlewares` to inject their own dependencies.

Fix clojure-emacs#1531, clojure-emacs#1534
  • Loading branch information
benedekfazekas committed Feb 11, 2016
1 parent 475d58c commit 93b7b92
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ and try to associate the created connection with this project automatically.

### Changes

* [#1531](https://github.com/clojure-emacs/cider/issues/1531) `cider-jack-in` now injects its own dependencies using CLI. Both leiningen and boot are supported. Set `cider-inject-dependencies-at-jack-in` to nil to opt out. Extension point for other tools to inject their own dependencies is `cider-add-repl-dependencies`.
* `cider-inspect` now operates by default on the last sexp. Its behavior can be altered via prefix arguments.
* Requires Clojure(Script) 1.7 or newer.
* Requires Java 7 or newer.
Expand Down
21 changes: 14 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ specific CIDER release.**
- [Installation](#installation)
- [Prerequisites](#prerequisites)
- [Installation via package.el](#installation-via-packageel)
- [Setting up CIDER's nREPL middleware](#setting-up-ciders-nrepl-middleware)
- [Using Leiningen](#using-leiningen)
- [Using Boot](#using-boot)
- [CIDER's nREPL middleware](#ciders-nrepl-middleware)
- [Setting up a standalone REPL](#setting-up-a-standalone-repl)
- [Using embedded nREPL server](#using-embedded-nrepl-server)
- [Basic Usage](#basic-usage)
- [Setting up a Leiningen or Boot project (optional)](#setting-up-a-leiningen-or-boot-project-optional)
Expand Down Expand Up @@ -218,12 +217,20 @@ Stable by adding this to your Emacs initialization:
[GNU ELPA repository](https://elpa.gnu.org/). It's the only package repository
enabled by default in Emacs and you should not disable it!**

### Setting up CIDER's nREPL middleware
### CIDER's nREPL middleware

Much of CIDER's functionality depends on the presence of CIDER's own
[nREPL middleware][cider-nrepl].
[nREPL middleware][cider-nrepl]. When `cider-jack-in` (<kbd>C-c M-j</kbd>) is used CIDER takes care of injecting it and its other dependencies.

#### Using Leiningen
**`profiles.clj` or `profile.boot` don't need to be modified anymore for the above usecase!**

If you don't want `cider-jack-in` to inject dependencies automatically, set `cider-inject-dependencies-at-jack-in` to nil. Note that you'll have to setup the dependencies yourself (see the section below).

If a standalone REPL is preferred, you need to invoke `cider-connect` (instead of `cider-jack-in`) and you'll need to manually add the dependencies to your Clojure project (explained in the following section).

#### Setting up a standalone REPL

##### Using Leiningen #####

Use the convenient plugin for defaults, either in your project's
`project.clj` file or in the :repl profile in `~/.lein/profiles.clj`.
Expand All @@ -242,7 +249,7 @@ A minimal `profiles.clj` for CIDER would be:
middleware will always get loaded, causing `lein` to start slower. You really
need it just for `lein repl` and this is what the `:repl` profile is for.**

#### Using Boot
##### Using Boot #####

Boot users can configure the tool to include the middleware automatically in
all of their projects using a `~/.boot/profile.boot` file like so:
Expand Down
73 changes: 73 additions & 0 deletions cider.el
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,11 @@ This variable is used by `cider-connect'."
:type 'boolean
:version "0.9.0")

(defcustom cider-inject-dependencies-at-jack-in t
"When nil, do not inject repl dependencies (most likely nREPL middlewares) at `cider-jack-in' time."
:type 'boolean
:version '(cider . "0.11.0"))

(defvar cider-ps-running-nrepls-command "ps u | grep leiningen"
"Process snapshot command used in `cider-locate-running-nrepl-ports'.")

Expand All @@ -177,6 +182,18 @@ Sub-match 1 must be the project path.")
(defvar cider-host-history nil
"Completion history for connection hosts.")

(defvar cider-jack-in-dependencies
'(("org.clojure/tools.nrepl" "0.2.12"))
"Clojure artifacts for starting the REPL. List of dependencies where elements are lists of artifact name and version.")

(defvar cider-jack-in-lein-plugins
`(("cider/cider-nrepl" ,(upcase cider-version)))
"List of Clojure artifacts for starting the REPL. List of Leiningen plugins where elements are lists of artifact name and version.")

(defvar cider-jack-in-nrepl-middlewares
'("cider.nrepl/cider-middleware")
"List of Clojure artifacts for starting the REPL. List of nREPL middleware names.")

;;;###autoload
(defun cider-version ()
"Display CIDER's version."
Expand Down Expand Up @@ -204,6 +221,58 @@ Sub-match 1 must be the project path.")
("boot" cider-boot-parameters)
("gradle" cider-gradle-parameters)))

(defun boot-command-prefix (dependencies)
(concat
(mapconcat
(lambda (dep) (format "-d %s:%s" (car dep) (cadr dep)))
dependencies
" ")
" "))

(defun boot-repl-task-params (params middlewares)
(replace-regexp-in-string
"repl"
(concat
"repl "
(mapconcat
(lambda (middleware) (format "-m %s" middleware))
middlewares
" "))
params))

(defun cider-boot-jack-in-dependencies (params dependencies plugins middlewares)
(concat
(boot-command-prefix
(seq-concatenate 'list dependencies plugins))
(boot-repl-task-params params middlewares)))

(defun cider-lein-jack-in-dependencies (params dependencies lein-plugins)
(concat
(mapconcat
'identity
(seq-concatenate
'list
(seq-map (lambda (dependency) (format "update-in :dependencies conj \"[%s \\\"%s\\\"]\"" (car dependency) (cadr dependency))) dependencies)
(seq-map (lambda (plugin) (format "update-in :plugins conj \"[%s \\\"%s\\\"]\"" (car plugin) (cadr plugin))) lein-plugins))
" -- ")
" -- "
params))

(defun cider-inject-jack-in-dependencies (params project-type)
"Modify the PARAMS so that REPL dependencies as set in `cider-jack-in-dependencies', `cider-jack-in-lein-plugins' and `cider-jack-in-nrepl-middlewares' are injected from the CLI according to the used PROJECT-TYPE.
Eliminates the need for hacking profiles.clj or the boot script for supporting cider with its nREPL middleware and dependencies."
(pcase project-type
("lein" (cider-lein-jack-in-dependencies
params
cider-jack-in-dependencies
cider-jack-in-lein-plugins))
("boot" (cider-boot-jack-in-dependencies
params
cider-jack-in-dependencies
cider-jack-in-lein-plugins
cider-jack-in-nrepl-middlewares))
("gradle" "")))

(defcustom cider-cljs-lein-repl "(cemerick.piggieback/cljs-repl (cljs.repl.rhino/repl-env))"
"Clojure form that returns a ClojureScript REPL environment.
This is only used in lein projects. It is evaluated in a Clojure REPL and
Expand Down Expand Up @@ -298,6 +367,10 @@ own buffer."
(cider-jack-in-params project-type))
(cider-jack-in-params project-type))
(cider-jack-in-params project-type)))
(params (if cider-inject-dependencies-at-jack-in
(cider-inject-jack-in-dependencies params project-type)
params))

(cmd (format "%s %s" (cider-jack-in-command project-type) params)))
(when-let ((repl-buff (cider-find-reusable-repl-buffer nil project-dir)))
(let ((nrepl-create-client-buffer-function #'cider-repl-create)
Expand Down
14 changes: 14 additions & 0 deletions test/cider-tests.el
Original file line number Diff line number Diff line change
Expand Up @@ -655,3 +655,17 @@
(should (equal (cider-project-name "") "-"))
(should (equal (cider-project-name "path/to/project") "project"))
(should (equal (cider-project-name "path/to/project/") "project")))

(ert-deftest cider-inject-jack-in-dependencies ()
(should (string= (cider-inject-jack-in-dependencies "repl :headless" "lein")
"update-in :dependencies conj \"[org.clojure/tools.nrepl \\\"0.2.12\\\"]\" -- update-in :plugins conj \"[cider/cider-nrepl \\\"0.11.0-SNAPSHOT\\\"]\" -- repl :headless"))
(should (string= (cider-inject-jack-in-dependencies "repl -s wait" "boot")
"-d org.clojure/tools.nrepl:0.2.12 -d cider/cider-nrepl:0.11.0-SNAPSHOT repl -m cider.nrepl/cider-middleware -s wait")))

(ert-deftest cider-inject-jack-in-dependencies-add-refactor-nrepl ()
(setq cider-jack-in-lein-plugins (seq-concatenate 'list cider-jack-in-lein-plugins '(("refactor-nrepl" "2.0.0"))))
(setq cider-jack-in-nrepl-middlewares (seq-concatenate 'list cider-jack-in-nrepl-middlewares '("refactor-nrepl.middleware/wrap-refactor")))
(should (string= (cider-inject-jack-in-dependencies "repl :headless" "lein")
"update-in :dependencies conj \"[org.clojure/tools.nrepl \\\"0.2.12\\\"]\" -- update-in :plugins conj \"[cider/cider-nrepl \\\"0.11.0-SNAPSHOT\\\"]\" -- update-in :plugins conj \"[refactor-nrepl \\\"2.0.0\\\"]\" -- repl :headless"))
(should (string= (cider-inject-jack-in-dependencies "repl -s wait" "boot")
"-d org.clojure/tools.nrepl:0.2.12 -d cider/cider-nrepl:0.11.0-SNAPSHOT -d refactor-nrepl:2.0.0 repl -m cider.nrepl/cider-middleware -m refactor-nrepl.middleware/wrap-refactor -s wait")))

0 comments on commit 93b7b92

Please sign in to comment.