From ed8ee403fbf35ce0cd6e868aaeac1bf23325d218 Mon Sep 17 00:00:00 2001 From: Benj Date: Mon, 28 Nov 2022 10:49:11 +0100 Subject: [PATCH 1/4] Allow connecting to nbb via connect-clj (#3061) This is for nbb, scittle, joyride. Better support for "pain" repls, support "cljs" without setup. we want to 1. connect with a plain client 2. make any assumptions explicit 3. connect cljs buffers with those plain repls 1. Check for cider middleware being present, before using it (already being done) 2. Check for cider-library-present-p, before relying on anything in the runtime 3. Make assumptions about the runtime explicit My suggestion is =cider-connection-capabilities=. Currently, there was an implicit assumption about the compilation error format. =cider-connection-capabilities= Is my suggestion for 2. =cider-repls= Now returns cljs, if the repl capabilities include 'cljs This way we can make a "plain" clj client, upgrade on connect with cljs capability and have it be connected in cljs buffers. This is more a concession / workaround the current repl-type setup. In the future we might get rid of repl-type? The only reason we have it, and creaating issue 3., is because we want to be ergonomic about which buffer to use inside a given source buffer. I found that I am able to juggle multiple clients by swapping to the buffer I want, thereby setting it active. This can be a user command. Can also make a modeline element that swaps between clj/cljs like calva. slack discussion: https://clojurians.slack.com/archives/C04CAKAGADU Format docstring Fix cljs check --- CHANGELOG.md | 2 ++ cider-connection.el | 33 ++++++++++++++++++++++++++++++++- cider-eval.el | 18 ++++++++++++++---- cider-overlays.el | 1 + cider-repl.el | 3 ++- cider.el | 6 +++++- test/cider-connection-tests.el | 20 ++++++++++++++++++++ 7 files changed, 76 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4792e29ff..a0cad9b5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ - [#3251](https://github.com/clojure-emacs/cider/pull/3251): Disable undo in `*cider-stacktrace*` buffers. - Consecutive overlays will not be spuriously deleted. - [#3260](https://github.com/clojure-emacs/cider/pull/3260): Scroll REPL buffer in other frame. +- [#3061](https://github.com/clojure-emacs/cider/issues/3061): Allow + connect-clj for plain cljs repls (nbb etc). ## 1.5.0 (2022-08-24) diff --git a/cider-connection.el b/cider-connection.el index dace07129..11e396bbd 100644 --- a/cider-connection.el +++ b/cider-connection.el @@ -343,6 +343,19 @@ buffer." (when cider-auto-mode (cider-enable-on-existing-clojure-buffers)) + (setf cider-connection-capabilities + (append + (pcase (cider-runtime) + ('clojure '(clojure jvm-compilation-errors)) + ('babashka '(babashka jvm-compilation-errors)) + (_ '())) + (when + ;; see `cider-sync-tooling-eval', but it is defined on a higher layer + (nrepl-dict-get + (nrepl-sync-request:eval "cljs.core/demunge" (current-buffer) nil 'tooling) + "value") + '(cljs)))) + (run-hooks 'cider-connected-hook))))) (defun cider--disconnected-handler () @@ -437,6 +450,18 @@ about this buffer (like variable `cider-repl-type')." (plist-get nrepl-endpoint :host) (plist-get nrepl-endpoint :port)))))) +(defvar-local cider-connection-capabilities '() + "A list of some of the capabilites of this connection buffer. +Aka what assumptions we make about the runtime. +This is more genaral than +`cider-nrepl-op-supported-p' and `cider-library-present-p'. +But does not need to replace them.") + +(defun cider-connection-has-capability-p (capability) + "Return non nil when the cider connection has CAPABILITY." + (with-current-buffer (cider-current-repl) + (member capability cider-connection-capabilities))) + ;;; Connection Management Commands @@ -885,7 +910,13 @@ no linked session or there is no REPL of TYPE within the current session." (cond ((null buffer-repl-type) nil) ((or (null type) (eq type 'multi) (eq type 'any)) t) ((listp type) (member buffer-repl-type type)) - (t (string= type buffer-repl-type))))) + (t + (or (string= type buffer-repl-type) + (let ((capabilities + (buffer-local-value 'cider-connection-capabilities buffer))) + (cond ((listp type) + (cl-some (lambda (it) (member it capabilities)) type)) + (t (member type capabilities))))))))) (defun cider--get-host-from-session (session) "Returns the host associated with SESSION." diff --git a/cider-eval.el b/cider-eval.el index 6e1fd4440..a7c4aecbc 100644 --- a/cider-eval.el +++ b/cider-eval.el @@ -462,6 +462,13 @@ Uses the value of the `out' slot in RESPONSE." (cider-nrepl-sync-request:eval "(clojure.stacktrace/print-cause-trace *e)"))) +(defun cider-default-err-eval-print-handler () + "Display the last exception without middleware support. +When clojure.stracktrace is not present." + (cider--handle-err-eval-response + (cider-nrepl-sync-request:eval + "(println (ex-data *e))"))) + (defun cider--render-stacktrace-causes (causes &optional error-types) "If CAUSES is non-nil, render its contents into a new error buffer. Optional argument ERROR-TYPES contains a list which should determine the @@ -498,9 +505,10 @@ into a new error buffer." (defun cider-default-err-handler () "This function determines how the error buffer is shown. It delegates the actual error content to the eval or op handler." - (if (cider-nrepl-op-supported-p "stacktrace") - (cider-default-err-op-handler) - (cider-default-err-eval-handler))) + (cond ((cider-nrepl-op-supported-p "stacktrace") (cider-default-err-op-handler)) + ((cider-library-present-p "clojure.stacktrace") (cider-default-err-eval-handler)) + (t (cider-default-err-eval-print-handler)))) + ;; The format of the error messages emitted by Clojure's compiler changed in ;; Clojure 1.10. That's why we're trying to match error messages to both the @@ -739,7 +747,9 @@ when `cider-auto-inspect-after-eval' is non-nil." (cider-emit-interactive-eval-output out)) (lambda (_buffer err) (cider-emit-interactive-eval-err-output err) - (unless cider-show-error-buffer + (when (or (not cider-show-error-buffer) + (not (cider-connection-has-capability-p 'jvm-compilation-errors))) + ;; Display errors as temporary overlays (let ((cider-result-use-clojure-font-lock nil)) (cider--display-interactive-eval-result diff --git a/cider-overlays.el b/cider-overlays.el index 3c56e8060..614388a07 100644 --- a/cider-overlays.el +++ b/cider-overlays.el @@ -303,6 +303,7 @@ focused." (let* ((font-value (if cider-result-use-clojure-font-lock (cider-font-lock-as-clojure value) value)) + (font-value (string-trim-right font-value)) (used-overlay (when (and point cider-use-overlays) (cider--make-result-overlay font-value :where point diff --git a/cider-repl.el b/cider-repl.el index eff5f99ba..80f47ec04 100644 --- a/cider-repl.el +++ b/cider-repl.el @@ -153,7 +153,8 @@ you'd like to use the default Emacs behavior use (make-obsolete-variable 'cider-repl-print-level 'cider-print-options "0.21") (defvar cider-repl-require-repl-utils-code - '((clj . "(clojure.core/apply clojure.core/require clojure.main/repl-requires)") + '((clj . "(when-let [requires (resolve 'clojure.main/repl-requires)] + (clojure.core/apply clojure.core/require @requires))") (cljs . "(require '[cljs.repl :refer [apropos dir doc find-doc print-doc pst source]])"))) (defcustom cider-repl-init-code (list (cdr (assoc 'clj cider-repl-require-repl-utils-code))) diff --git a/cider.el b/cider.el index b79c89a0a..0bf597291 100644 --- a/cider.el +++ b/cider.el @@ -778,9 +778,13 @@ Generally you should not disable this unless you run into some faulty check." :safe #'booleanp :package-version '(cider . "0.17.0")) +(defun cider-clojurescript-present-p () + "Return non nil when ClojureScript is present." + (nrepl-dict-get (cider-sync-tooling-eval "cljs.core/demunge") "value")) + (defun cider-verify-clojurescript-is-present () "Check whether ClojureScript is present." - (unless (cider-library-present-p "cljs.core") + (unless (cider-clojurescript-present-p) (user-error "ClojureScript is not available. See https://docs.cider.mx/cider/basics/clojurescript for details"))) (defun cider-verify-piggieback-is-present () diff --git a/test/cider-connection-tests.el b/test/cider-connection-tests.el index 1ff79dd52..a096d0a03 100644 --- a/test/cider-connection-tests.el +++ b/test/cider-connection-tests.el @@ -370,6 +370,26 @@ (expect (cider-repls) :to-equal (list a b)) (kill-buffer b) (expect (cider-repls) :to-equal (list a)) + (sesman-unregister 'CIDER session)))))) + + (describe "cljs capability" + (it "Upgraded clj repl counts as cljs" + (let ((default-directory (expand-file-name "/tmp/some-dir"))) + (cider-test-with-buffers + (a b) + (let ((session (list "some-session" a b))) + (with-current-buffer a + (setq cider-repl-type 'clj)) + (with-current-buffer b + (setq cider-repl-type 'cljs)) + (sesman-register 'CIDER session) + (expect (cider-repls 'cljs) :to-equal (list b)) + + (with-current-buffer a + (setf cider-connection-capabilities + (append cider-connection-capabilities '(cljs)))) + + (expect (cider-repls) :to-equal (list a b)) (sesman-unregister 'CIDER session))))))) (describe "cider--connection-info" From f0dc573b3483a6d507d4598b439bc12c750e5ab9 Mon Sep 17 00:00:00 2001 From: Benj Date: Fri, 2 Dec 2022 18:44:21 +0100 Subject: [PATCH 2/4] Update connection-capability code --- cider-connection.el | 6 +++--- cider-eval.el | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/cider-connection.el b/cider-connection.el index 11e396bbd..d73052bf6 100644 --- a/cider-connection.el +++ b/cider-connection.el @@ -453,13 +453,13 @@ about this buffer (like variable `cider-repl-type')." (defvar-local cider-connection-capabilities '() "A list of some of the capabilites of this connection buffer. Aka what assumptions we make about the runtime. -This is more genaral than +This is more general than `cider-nrepl-op-supported-p' and `cider-library-present-p'. But does not need to replace them.") -(defun cider-connection-has-capability-p (capability) +(defun cider-connection-has-capability-p (connection-buffer capability) "Return non nil when the cider connection has CAPABILITY." - (with-current-buffer (cider-current-repl) + (with-current-buffer connection-buffer (member capability cider-connection-capabilities))) diff --git a/cider-eval.el b/cider-eval.el index a7c4aecbc..fb5945f2c 100644 --- a/cider-eval.el +++ b/cider-eval.el @@ -747,8 +747,11 @@ when `cider-auto-inspect-after-eval' is non-nil." (cider-emit-interactive-eval-output out)) (lambda (_buffer err) (cider-emit-interactive-eval-err-output err) + (when (or (not cider-show-error-buffer) - (not (cider-connection-has-capability-p 'jvm-compilation-errors))) + (not (cider-connection-has-capability-p + (current-buffer) + 'jvm-compilation-errors))) ;; Display errors as temporary overlays (let ((cider-result-use-clojure-font-lock nil)) From 65b9ce1cca9502db8e7621314df348ca0c0c370e Mon Sep 17 00:00:00 2001 From: Benj Date: Sat, 3 Dec 2022 10:32:39 +0100 Subject: [PATCH 3/4] Make buffer optional for cider-connection-has-capability-p --- cider-connection.el | 7 ++++--- cider-eval.el | 4 +--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/cider-connection.el b/cider-connection.el index d73052bf6..ab71b3480 100644 --- a/cider-connection.el +++ b/cider-connection.el @@ -457,9 +457,10 @@ This is more general than `cider-nrepl-op-supported-p' and `cider-library-present-p'. But does not need to replace them.") -(defun cider-connection-has-capability-p (connection-buffer capability) - "Return non nil when the cider connection has CAPABILITY." - (with-current-buffer connection-buffer +(defun cider-connection-has-capability-p (capability :optional connection-buffer) + "Return non nil when the cider connection has CAPABILITY. +By default it assumes the connection buffer is current." + (with-current-buffer (or connection-buffer (current-buffer)) (member capability cider-connection-capabilities))) diff --git a/cider-eval.el b/cider-eval.el index fb5945f2c..da20f78ad 100644 --- a/cider-eval.el +++ b/cider-eval.el @@ -749,9 +749,7 @@ when `cider-auto-inspect-after-eval' is non-nil." (cider-emit-interactive-eval-err-output err) (when (or (not cider-show-error-buffer) - (not (cider-connection-has-capability-p - (current-buffer) - 'jvm-compilation-errors))) + (not (cider-connection-has-capability-p 'jvm-compilation-errors))) ;; Display errors as temporary overlays (let ((cider-result-use-clojure-font-lock nil)) From d66c8315a2a696bb07c161149bd7aaa805ff310d Mon Sep 17 00:00:00 2001 From: Benj Date: Sat, 3 Dec 2022 12:00:00 +0100 Subject: [PATCH 4/4] Add a doc for using cider-connect-clj to connect to scittle,nbb.. --- doc/modules/ROOT/nav.adoc | 1 + .../pages/platforms/scittle_and_friends.adoc | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 doc/modules/ROOT/pages/platforms/scittle_and_friends.adoc diff --git a/doc/modules/ROOT/nav.adoc b/doc/modules/ROOT/nav.adoc index fd76a3f74..599eb069a 100644 --- a/doc/modules/ROOT/nav.adoc +++ b/doc/modules/ROOT/nav.adoc @@ -13,6 +13,7 @@ * Alternative Platforms ** xref:platforms/overview.adoc[Overview] ** xref:platforms/babashka.adoc[Babashka] +** xref:platforms/scittle_and_friends.adoc[Scittle and Friends] * Using CIDER ** xref:usage/interactive_programming.adoc[Interactive Programming] ** xref:usage/cider_mode.adoc[Using cider-mode] diff --git a/doc/modules/ROOT/pages/platforms/scittle_and_friends.adoc b/doc/modules/ROOT/pages/platforms/scittle_and_friends.adoc new file mode 100644 index 000000000..5c72c6460 --- /dev/null +++ b/doc/modules/ROOT/pages/platforms/scittle_and_friends.adoc @@ -0,0 +1,29 @@ += Scittle, Nbb, Joyride, and future plain repls + +The default cider (clj-repl) should be capable of connecting to any +nrepl server that provides minimal functionality. + +As such, all of these work: +https://github.com/babashka/nbb[nbb], +https://github.com/babashka/scittle[scittle], https://github.com/BetterThanTomorrow/joyride[joyride] + +First start an nrepl server (the project's Readme usually has a section +on starting a nrepl server). + +You can use + +kbd:[M-x `cider-connect-clj` ] + +to connect to any plain Clojure(Script) nrepl server. + +Features: + +* Eval, load file etc. +* Errors as overlays. (The default cider error buffer is not implemented currently). +* Other nrepl features the server provides; This might be rather minimal. + +Nbb, Scittle and Joyride all have quite cool completions already. + +== Note + +For nbb you can alternatively connect via cljs, see xref:platform/nbb.adoc[Nbb]