From c8f7bc8e40f3f72e34c583d04c23c038f3c9197b Mon Sep 17 00:00:00 2001 From: Rene Descartes Date: Sat, 30 Aug 2025 10:43:49 -0600 Subject: [PATCH 1/4] Add jack-in support for ClojureCLR --- CHANGELOG.md | 1 + .../ROOT/pages/basics/up_and_running.adoc | 1 + doc/modules/ROOT/pages/caveats.adoc | 13 ---- .../ROOT/pages/platforms/clojureclr.adoc | 22 ++++--- lisp/cider-jack-in.el | 61 +++++++++++++++++++ 5 files changed, 76 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 394b55fbe..84f45e681 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - [#4143](https://github.com/clojure-emacs/cider/pull/4143): Highlight the `#break`/`#dbg`/`#light` debugging reader tags in `clojure-ts-mode` buffers too. - [#4117](https://github.com/clojure-emacs/cider/pull/4117): Add `cider-use-completing-read-for-symbol` (off by default): when enabled, symbol prompts (e.g. `cider-doc`, `cider-find-var`) read through `completing-read` over a lazy, runtime-backed collection, so they work with `completing-read` UIs (Vertico, Ivy, Helm) and annotate candidates with their type and namespace. - [#4129](https://github.com/clojure-emacs/cider/pull/4129): Render completion annotations as an aligned type/namespace column (via an `affixation-function`) in UIs that support it, such as the built-in `*Completions*`, Corfu and Vertico. +- [#3839](https://github.com/clojure-emacs/cider/pull/3839): Add jack-in support for ClojureCLR. ### Changes diff --git a/doc/modules/ROOT/pages/basics/up_and_running.adoc b/doc/modules/ROOT/pages/basics/up_and_running.adoc index de313a37f..c6491cd4a 100644 --- a/doc/modules/ROOT/pages/basics/up_and_running.adoc +++ b/doc/modules/ROOT/pages/basics/up_and_running.adoc @@ -199,6 +199,7 @@ The following Clojure build tools are supported so far - kbd:[M-3 C-c C-x j u] jack-in using babashka. - kbd:[M-4 C-c C-x j u] jack-in using nbb. - kbd:[M-5 C-c C-x j u] jack-in using basilisp. +- kbd:[M-6 C-c C-x j u] jack-in using ClojureCLR. Here is an example of how to bind kbd:[F12] for quickly bringing up a babashka REPL: diff --git a/doc/modules/ROOT/pages/caveats.adoc b/doc/modules/ROOT/pages/caveats.adoc index ce28b2d8e..136df1e45 100644 --- a/doc/modules/ROOT/pages/caveats.adoc +++ b/doc/modules/ROOT/pages/caveats.adoc @@ -64,19 +64,6 @@ loaded. As a workaround remove from your Emacs config. -== ClojureCLR Support - -CIDER currently has very basic support for ClojureCLR (via Arcadia's nREPL server). The reasons for this are the following: - -* nREPL itself runs only on the JVM (because it leverages Java APIs -internally). There's an -https://github.com/clojure/clr.tools.nrepl[nREPL port for ClojureCLR], but -it's not actively maintained and it doesn't behave like the Clojure nREPL. -* `cider-nrepl` uses a lot of Java code internally itself. - -Those issues are not insurmountable, but are beyond the scope of our current roadmap. -If someone would like to tackle them, we'd be happy to provide assistance. - == Injecting dependencies and Leiningen pedantic: abort mode Because injection currently creates an override of the nREPL dependency that diff --git a/doc/modules/ROOT/pages/platforms/clojureclr.adoc b/doc/modules/ROOT/pages/platforms/clojureclr.adoc index e858f3f31..9141a2c70 100644 --- a/doc/modules/ROOT/pages/platforms/clojureclr.adoc +++ b/doc/modules/ROOT/pages/platforms/clojureclr.adoc @@ -2,27 +2,31 @@ == Current Status -ClojureCLR on CIDER is not great due to the lack of a fully-functional nREPL -server for ClojureCLR. There are currently two options: +You will get basic CIDER functionality with ClojureCLR. Two nREPL server options: -- https://github.com/clojure/clr.tools.nrepl[clr.tools.nrepl]: A direct (but incomplete) port of the reference Clojure nREPL server. -- https://github.com/arcadia-unity/Arcadia/blob/master/Editor/NRepl.cs[Arcadia's nREPL]: A basic, but working nREPL implementation in C#. +- https://github.com/clojure/clr.tools.nrepl[clr.tools.nrepl]: At present port of babashka's nREPL server (https://github.com/babashka/babashka.nrepl[babashka.nrepl]). +- https://github.com/clojure/clr.tools.nrepl/tree/master/partial-nrepl-nrepl-port[port of nrepl/nrepl]: A non-working, work-in-progress port of nrepl/nrepl, which may + ultimately better integrate with CIDER once CIDER's middleware (cider-nrepl) is also adapted/ported. -If you need to use CIDER with ClojureCLR today Arcadia's nREPL is your only usable option. That being said - `clr.tools.nrepl` is a much -more sophisticated project and ideally we should get it over to the finish line. +CIDER currently has basic support for ClojureCLR via a port of Babashka's nREPL + server. The reasons for the basic support is that: `cider-nrepl`, the CIDER + middleware, uses a lot of Java code internally itself and would need to be + adapted/ported like any other clojure library adapted/ported to ClojureCLR. + +Alternatives to using CIDER with ClojureCLR include https://github.com/clojure-emacs/inf-clojure[inf-clojure] and https://github.com/nrepl/neat[neat]. == Usage NOTE: Contributions welcome! -As `cider-jack-in` doesn't support ClojureCLR projects out-of-the-box currently, you'll need to start an nREPL server externally and -connect to it with `cider-connect`. +`cider-jack-in-universal` will jack into a clr.tools.nrepl server as long as a `deps-clr.edn` file +exists in the project directory, otherwise you may call `cider-jack-in-universal` with prefix +argument 6, by either `M-6` or `C-u 6` followed by `M-x cider-jack-in-universal`. == Plans In an ideal world we'll achieve the following objectives: -- out-of-the-box ClojureCLR support with `cider-jack-in` - feature parity between Clojure's nREPL implementation and `clr.tools.nrepl` (the project can use some help) - adapting `cider-nrepl` for ClojureCLR (some of its codebase is JVM-specific) diff --git a/lisp/cider-jack-in.el b/lisp/cider-jack-in.el index 40c554ccf..ae707577e 100644 --- a/lisp/cider-jack-in.el +++ b/lisp/cider-jack-in.el @@ -225,6 +225,30 @@ By default we favor the project-specific shadow-cljs over the system-wide." :safe #'stringp :package-version '(cider . "1.14.0")) +(defcustom cider-clojure-clr-cli-command + "cljr" + "The command used to execute ClojureCLR." + :type 'string + :group 'cider + :safe #'stringp + :package-version '(cider . "2.0.1")) + +(defcustom cider-clojure-clr-cli-parameters + "-X clojure.tools.nrepl/start-server!" + "Params passed to ClojureCLR to start an nREPL server via `cider-jack-in'." + :type 'string + :group 'cider + :safe #'stringp + :package-version '(cider . "2.0.1")) + +;; Clojure git deps require :git/sha even when :git/tag is set, just do full SHA +(defcustom cider-clojure-clr-cli-nrepl-sha "a6bf822a5f72ec613f703eaf95420758591f2437" + "The version of clr.tools.nrepl injected on jack-in with ClojureCLR." + :type 'string + :group 'cider + :safe #'stringp + :package-version '(cider . "2.0.1")) + ;;; Jack-in defaults and toggles @@ -668,6 +692,30 @@ Does so by concatenating PARAMS and DEPENDENCIES." " " params))) +(defun cider-clojure-clr-cli-jack-in-dependencies (params dependencies &optional command) + "Create ClojureCLR clr.core.cli jack-in dependencies. +Does so by concatenating DEPENDENCIES, and PARAMS into a +suitable `cljr` invocation and quoting, also accounting for COMMAND if +provided." + (let* ((all-deps (thread-last dependencies + (cider--dedupe-deps) + (seq-map (lambda (dep) + (if (listp (cadr dep)) + (format "%s {%s}" + (car dep) + (seq-reduce + (lambda (acc v) + (concat acc (format " :%s \"%s\" " (car v) (cdr v)))) + (cadr dep) + "")) + (format "%s {:git/sha \"%s\"}" (car dep) (cadr dep))))))) + (deps (format "{:deps {%s}}" + (string-join all-deps " "))) + (deps-quoted (cider--shell-quote-argument deps command))) + (format "-Sdeps %s %s" + deps-quoted + (if params (format " %s" params) "")))) + (defun cider-add-clojure-dependencies-maybe (dependencies) "Return DEPENDENCIES with an added Clojure dependency if requested. See also `cider-jack-in-auto-inject-clojure'." @@ -727,6 +775,12 @@ COMMAND is the resolved jack-in command, used to handle PowerShell quoting." (cider-add-clojure-dependencies-maybe cider-jack-in-dependencies) (cider-jack-in-normalized-nrepl-middlewares))) +(defun cider--clojure-clr-cli-inject-deps (params _project-type _command) + "Inject CIDER deps into PARAMS for a ClojureCLR CLI project." + (cider-clojure-clr-cli-jack-in-dependencies + params + `(("io.github.clojure/clr.tools.nrepl" ,cider-clojure-clr-cli-nrepl-sha)))) + (defun cider-inject-jack-in-dependencies (params project-type &optional command) "Return PARAMS with injected REPL dependencies for PROJECT-TYPE. Looks up the tool's :inject-fn in `cider-jack-in-tools' and calls it with @@ -894,6 +948,13 @@ Throws an error if PROJECT-TYPE is unknown." :project-files '("basilisp.edn") :dispatch-prefix-arg 5) +(cider-register-jack-in-tool 'clojure-clr-cli + :command-var 'cider-clojure-clr-cli-command + :params-var 'cider-clojure-clr-cli-parameters + :project-files '("deps-clr.edn") + :inject-fn #'cider--clojure-clr-cli-inject-deps + :dispatch-prefix-arg 6) + ;;; ClojureScript jack-in helpers From 0e82e42bd0e2967708961997b70d8e35a5f9510b Mon Sep 17 00:00:00 2001 From: rene-descartes2021 <88462753+rene-descartes2021@users.noreply.github.com> Date: Thu, 10 Sep 2026 14:40:27 -0600 Subject: [PATCH 2/4] Update doc/modules/ROOT/pages/platforms/clojureclr.adoc Co-authored-by: Bozhidar Batsov --- doc/modules/ROOT/pages/platforms/clojureclr.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/modules/ROOT/pages/platforms/clojureclr.adoc b/doc/modules/ROOT/pages/platforms/clojureclr.adoc index 9141a2c70..520263ebd 100644 --- a/doc/modules/ROOT/pages/platforms/clojureclr.adoc +++ b/doc/modules/ROOT/pages/platforms/clojureclr.adoc @@ -4,7 +4,7 @@ You will get basic CIDER functionality with ClojureCLR. Two nREPL server options: -- https://github.com/clojure/clr.tools.nrepl[clr.tools.nrepl]: At present port of babashka's nREPL server (https://github.com/babashka/babashka.nrepl[babashka.nrepl]). +- https://github.com/clojure/clr.tools.nrepl[clr.tools.nrepl]: currently a port of https://github.com/babashka/babashka.nrepl[babashka.nrepl] to ClojureCLR. - https://github.com/clojure/clr.tools.nrepl/tree/master/partial-nrepl-nrepl-port[port of nrepl/nrepl]: A non-working, work-in-progress port of nrepl/nrepl, which may ultimately better integrate with CIDER once CIDER's middleware (cider-nrepl) is also adapted/ported. From 7dedcec51c4a991de30013625a2c82207bcd59b9 Mon Sep 17 00:00:00 2001 From: rene-descartes2021 <88462753+rene-descartes2021@users.noreply.github.com> Date: Thu, 10 Sep 2026 14:40:47 -0600 Subject: [PATCH 3/4] Update doc/modules/ROOT/pages/platforms/clojureclr.adoc Co-authored-by: Bozhidar Batsov --- doc/modules/ROOT/pages/platforms/clojureclr.adoc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/modules/ROOT/pages/platforms/clojureclr.adoc b/doc/modules/ROOT/pages/platforms/clojureclr.adoc index 520263ebd..51f5c9d31 100644 --- a/doc/modules/ROOT/pages/platforms/clojureclr.adoc +++ b/doc/modules/ROOT/pages/platforms/clojureclr.adoc @@ -8,10 +8,9 @@ You will get basic CIDER functionality with ClojureCLR. Two nREPL server options - https://github.com/clojure/clr.tools.nrepl/tree/master/partial-nrepl-nrepl-port[port of nrepl/nrepl]: A non-working, work-in-progress port of nrepl/nrepl, which may ultimately better integrate with CIDER once CIDER's middleware (cider-nrepl) is also adapted/ported. -CIDER currently has basic support for ClojureCLR via a port of Babashka's nREPL - server. The reasons for the basic support is that: `cider-nrepl`, the CIDER - middleware, uses a lot of Java code internally itself and would need to be - adapted/ported like any other clojure library adapted/ported to ClojureCLR. +CIDER's support is basic because `cider-nrepl`, the middleware behind most of +CIDER's features, uses a lot of Java internally and would need to be ported to +ClojureCLR like any other Clojure library. Alternatives to using CIDER with ClojureCLR include https://github.com/clojure-emacs/inf-clojure[inf-clojure] and https://github.com/nrepl/neat[neat]. From 469d9e7c15e8a1d84013dfef29a372158bd2ec78 Mon Sep 17 00:00:00 2001 From: rene-descartes2021 <88462753+rene-descartes2021@users.noreply.github.com> Date: Thu, 10 Sep 2026 14:41:18 -0600 Subject: [PATCH 4/4] Update lisp/cider-jack-in.el Co-authored-by: Bozhidar Batsov --- lisp/cider-jack-in.el | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lisp/cider-jack-in.el b/lisp/cider-jack-in.el index ae707577e..0eda26b84 100644 --- a/lisp/cider-jack-in.el +++ b/lisp/cider-jack-in.el @@ -775,11 +775,13 @@ COMMAND is the resolved jack-in command, used to handle PowerShell quoting." (cider-add-clojure-dependencies-maybe cider-jack-in-dependencies) (cider-jack-in-normalized-nrepl-middlewares))) -(defun cider--clojure-clr-cli-inject-deps (params _project-type _command) - "Inject CIDER deps into PARAMS for a ClojureCLR CLI project." +(defun cider--clojure-clr-cli-inject-deps (params _project-type command) + "Inject CIDER deps into PARAMS for a ClojureCLR CLI project. +COMMAND is the resolved jack-in command, used to handle PowerShell quoting." (cider-clojure-clr-cli-jack-in-dependencies params - `(("io.github.clojure/clr.tools.nrepl" ,cider-clojure-clr-cli-nrepl-sha)))) + `(("io.github.clojure/clr.tools.nrepl" ,cider-clojure-clr-cli-nrepl-sha)) + command)) (defun cider-inject-jack-in-dependencies (params project-type &optional command) "Return PARAMS with injected REPL dependencies for PROJECT-TYPE.