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); and an extension point
(`cider-add-repl-dependencies`) so other tools like clj-refactor
can inject to their own dependencies, middlewares.

Fix clojure-emacs#1531 and clojure-emacs#1534
  • Loading branch information
benedekfazekas committed Feb 9, 2016
1 parent 475d58c commit e28d0ad
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 4 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
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,12 +218,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 modifies the CLI starting up the REPL to inject its own dependencies. Both Leiningen and Boot powered projects are supported.

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

If this behaviour is not preferred set `cider-inject-dependencies-at-jack-in` to nil. At `cider-jack-in` the CLI command is always shown in the minibuffer (or see it in the `*Messages*` buffer).

If a standalone REPL is preferred and `cider-connect` is used adding the middlewares are still needed as CIDER can not control dependencies of an independent REPL.

#### When 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 +250,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
82 changes: 82 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 jack in time."
:type 'boolean
:version "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,15 @@ Sub-match 1 must be the project path.")
(defvar cider-host-history nil
"Completion history for connection hosts.")

(defvar cider-repl-dependencies
`((("org.clojure/tools.nrepl" "0.2.12"))
(("cider/cider-nrepl" ,(upcase cider-version)))
("cider.nrepl/cider-middleware"))
"List of Clojure artifacts for starting the REPL.
First item is a list of dependencies where elements are lists of artifact name and version.
Second item is a list of leiningen plugins where elements are lists of artifact name and version.
Third item is a list of nrepl middleware names.")

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

(defun boot-command-prefix (dependencies)
(concat
(mapconcat
'identity
(seq-map (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
'identity
(seq-map (lambda (middleware) (format "-m %s" middleware)) middlewares)
" "))
params))

(defun cider-boot-jack-in-dependencies (params repl-deps)
(concat
(boot-command-prefix
(seq-concatenate 'list
(car repl-deps)
(cadr repl-deps)))
(boot-repl-task-params params (car (last repl-deps)))))

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

(defun cider-add-repl-dependencies (dependencies lein-plugins middlewares)
"Extension point to add REPL dependencies to `cider-repl-dependencies' so they are injected from the CLI at cider jack in."
(let ((orig-deps (car cider-repl-dependencies))
(orig-plugins (cadr cider-repl-dependencies))
(orig-middlewares (car (last cider-repl-dependencies))))
(setq
cider-repl-dependencies
`(,(if (not dependencies)
orig-deps
(seq-concatenate 'list orig-deps dependencies))
,(if (not lein-plugins)
orig-plugins
(seq-concatenate 'list orig-plugins lein-plugins))
,(if (not middlewares)
orig-middlewares
(seq-concatenate 'list orig-middlewares middlewares))))))

(defun cider-jack-in-dependencies (params project-type)
"Modify the params so that REPL dependencies as set in `cider-repl-dependencies' 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."
(pcase project-type
("lein" (cider-lein-jack-in-dependencies params cider-repl-dependencies))
("boot" (cider-boot-jack-in-dependencies params cider-repl-dependencies))
("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 +376,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-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

0 comments on commit e28d0ad

Please sign in to comment.