From 16e1afcb749aa4db273675ca3a77156c249766da Mon Sep 17 00:00:00 2001 From: Wilbrt Date: Fri, 26 Sep 2025 17:31:19 +0300 Subject: [PATCH 1/4] 3834 Change cider-ns-refresh to use clj repl --- CHANGELOG.md | 1 + cider-client.el | 22 ++++++++++---------- cider-ns.el | 12 +++++------ doc/modules/ROOT/pages/usage/cider_mode.adoc | 2 +- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d772a97c..51b21edf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Bump the injected `nrepl` to [1.4.0](https://github.com/nrepl/nrepl/blob/master/CHANGELOG.md#140-2025-09-02). - Bump the injected `piggieback` to [0.6.1](https://github.com/nrepl/piggieback/blob/master/CHANGES.md#061-2025-12-31). +- [#3834](https://github.com/clojure-emacs/cider/issues/3834): Change cider-ns-refresh to always use Clojure REPL ### Bugs fixed diff --git a/cider-client.el b/cider-client.el index 97bd02a4d..7771b42d2 100644 --- a/cider-client.el +++ b/cider-client.el @@ -175,10 +175,10 @@ Skip check if repl is active if SKIP-ENSURE is non nil." nil 'ensure))))) -(defun cider-ensure-op-supported (op) - "Check for support of middleware op OP. +(defun cider-ensure-op-supported (op &optional connection) + "Check for support of middleware op OP for CONNECTION. Signal an error if it is not supported." - (unless (cider-nrepl-op-supported-p op) + (unless (cider-nrepl-op-supported-p op connection) (user-error "`%s' requires the nREPL op \"%s\" (provided by cider-nrepl)" this-command op))) (defun cider-nrepl-send-request (request callback &optional connection tooling) @@ -623,12 +623,12 @@ Optional arguments include SEARCH-NS, DOCS-P, PRIVATES-P, CASE-SENSITIVE-P." (user-error "Invalid regexp: %s" (nrepl-dict-get response "error-msg")) (nrepl-dict-get response "apropos-matches")))) -(defun cider-sync-request:classpath () - "Return a list of classpath entries." - (cider-ensure-op-supported "classpath") +(defun cider-sync-request:classpath (&optional connection) + "Return a list of classpath entries for CONNECTION." + (cider-ensure-op-supported "classpath" connection) (thread-first '("op" "classpath") - (cider-nrepl-send-sync-request) + (cider-nrepl-send-sync-request connection) (nrepl-dict-get "classpath"))) (defun cider--get-abs-path (path project) @@ -652,11 +652,11 @@ resolve those to absolute paths." (project (clojure-project-dir))) (mapcar (lambda (path) (cider--get-abs-path path project)) classpath)))) -(defun cider-classpath-entries () - "Return a list of classpath entries." +(defun cider-classpath-entries (&optional connection) + "Return a list of classpath entries for CONNECTION." (seq-map #'expand-file-name ; normalize filenames for e.g. Windows - (if (cider-nrepl-op-supported-p "classpath") - (cider-sync-request:classpath) + (if (cider-nrepl-op-supported-p "classpath" connection) + (cider-sync-request:classpath connection) (cider-fallback-eval:classpath)))) (defun cider-sync-request:completion (prefix) diff --git a/cider-ns.el b/cider-ns.el index 1f56c2099..4f1516fdb 100644 --- a/cider-ns.el +++ b/cider-ns.el @@ -219,13 +219,13 @@ presenting the error message as an overlay." error) (cider-ns--present-error error)))) -(defun cider-ns-refresh--save-modified-buffers () - "Ensure any relevant modified buffers are saved before refreshing. +(defun cider-ns-refresh--save-modified-buffers (&optional connection) + "Ensure any relevant modified buffers for CONNECTION are saved before refreshing. Its behavior is controlled by `cider-ns-save-files-on-refresh' and `cider-ns-save-files-on-refresh-modes'." (when cider-ns-save-files-on-refresh (let ((dirs (seq-filter #'file-directory-p - (cider-classpath-entries)))) + (cider-classpath-entries connection)))) (save-some-buffers (not (eq cider-ns-save-files-on-refresh 'prompt)) (lambda () @@ -297,14 +297,14 @@ refresh functions (defined in `cider-ns-refresh-before-fn' and `cider-ns-refresh-after-fn') from being invoked." (interactive "p") (cider-ensure-connected) - (cider-ensure-op-supported "refresh") - (cider-ensure-op-supported "cider.clj-reload/reload") - (cider-ns-refresh--save-modified-buffers) (let ((clear? (member mode '(clear 16))) (all? (member mode '(refresh-all 4))) (inhibit-refresh-fns (member mode '(inhibit-fns -1)))) (cider-map-repls :clj (lambda (conn) + (cider-ensure-op-supported "refresh" conn) + (cider-ensure-op-supported "cider.clj-reload/reload" conn) + (cider-ns-refresh--save-modified-buffers conn) ;; Inside the lambda, so the buffer is not created if we error out. (let ((log-buffer (or (get-buffer cider-ns-refresh-log-buffer) (cider-make-popup-buffer cider-ns-refresh-log-buffer)))) diff --git a/doc/modules/ROOT/pages/usage/cider_mode.adoc b/doc/modules/ROOT/pages/usage/cider_mode.adoc index 1353921e9..0e4650a4d 100644 --- a/doc/modules/ROOT/pages/usage/cider_mode.adoc +++ b/doc/modules/ROOT/pages/usage/cider_mode.adoc @@ -175,7 +175,7 @@ kbd:[C-u C-c C-c] | `cider-ns-refresh` | kbd:[C-c M-n (M-)r] -| Reload all modified files on the classpath. If invoked with a prefix argument, reload all files on the classpath. If invoked with a double prefix argument, clear the state of the namespace tracker before reloading. +| Reload all modified files on the classpath. If invoked with a prefix argument, reload all files on the classpath. If invoked with a double prefix argument, clear the state of the namespace tracker before reloading. Uses a clojure REPL whenever one exists. | `cider-doc` | kbd:[C-c C-d d] + From f65ea20d297299c4d13588d158d74721e21fa263 Mon Sep 17 00:00:00 2001 From: Wilbrt Date: Fri, 26 Sep 2025 19:13:24 +0300 Subject: [PATCH 2/4] 3834 Extend cider-map-repls to allow ensured op list --- cider-connection.el | 25 ++++++++++++++++++------- cider-ns.el | 4 +--- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/cider-connection.el b/cider-connection.el index f4181330e..c2eeaa9b0 100644 --- a/cider-connection.el +++ b/cider-connection.el @@ -1053,8 +1053,9 @@ throw an error if no linked session exists." (defun cider-map-repls (which function) "Call FUNCTION once for each appropriate REPL as indicated by WHICH. The function is called with one argument, the REPL buffer. The appropriate -connections are found by inspecting the current buffer. WHICH is one of -the following keywords: +connections are found by inspecting the current buffer. WHICH is either one of +the following keywords or a list starting with one of them followed by names of +operations that the REPL is expected to support: :auto - Act on the connections whose type matches the current buffer. In `cljc' files, mapping happens over both types of REPLs. :clj (:cljs) - Map over clj (cljs)) REPLs only. @@ -1064,23 +1065,33 @@ the following keywords: Error is signaled if no REPL buffers of specified type exist in current session." (declare (indent 1)) - (let ((cur-type (cider-repl-type-for-buffer))) - (cl-case which + (let ((cur-type (cider-repl-type-for-buffer)) + (which-key (or (car-safe which) which)) + (ops-to-support (cdr-safe which))) + (cl-case which-key (:clj-strict (when (eq cur-type 'cljs) (user-error "Clojure-only operation requested in a ClojureScript buffer"))) (:cljs-strict (when (eq cur-type 'clj) (user-error "ClojureScript-only operation requested in a Clojure buffer")))) - (let* ((type (cl-case which + (let* ((type (cl-case which-key ((:clj :clj-strict) 'clj) ((:cljs :cljs-strict) 'cljs) (:auto (if (eq cur-type 'multi) '(clj cljs) cur-type)))) - (ensure (cl-case which + (ensure (cl-case which-key (:auto nil) (t 'ensure))) (repls (cider-repls type ensure))) - (mapcar function repls)))) + (mapcar (lambda (repl) + (mapc (lambda (op) + (unless (nrepl-op-supported-p op repl) + (user-error "`%s' requires the nREPL op \"%s\" (provided by cider-nrepl)" + this-command op))) + ops-to-support) + (funcall function repl)) + repls)))) + ;; REPLs double as connections in CIDER, so it's useful to be able to refer to ;; them as connections in certain contexts. diff --git a/cider-ns.el b/cider-ns.el index 4f1516fdb..e99e6a014 100644 --- a/cider-ns.el +++ b/cider-ns.el @@ -300,10 +300,8 @@ refresh functions (defined in `cider-ns-refresh-before-fn' and (let ((clear? (member mode '(clear 16))) (all? (member mode '(refresh-all 4))) (inhibit-refresh-fns (member mode '(inhibit-fns -1)))) - (cider-map-repls :clj + (cider-map-repls '(:clj "refresh" "cider.clj-reload/reload") (lambda (conn) - (cider-ensure-op-supported "refresh" conn) - (cider-ensure-op-supported "cider.clj-reload/reload" conn) (cider-ns-refresh--save-modified-buffers conn) ;; Inside the lambda, so the buffer is not created if we error out. (let ((log-buffer (or (get-buffer cider-ns-refresh-log-buffer) From b5608dd11f792fa272e13fe37061330077586364 Mon Sep 17 00:00:00 2001 From: Wilbrt Date: Sun, 28 Sep 2025 14:25:09 +0300 Subject: [PATCH 3/4] 3834 Extend cider-repls to filter out REPLs that do not support needed ops, use the new format also in cider-toggle-trace-ns --- cider-connection.el | 22 +++++++++------------- cider-tracing.el | 3 +-- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/cider-connection.el b/cider-connection.el index c2eeaa9b0..da9483b92 100644 --- a/cider-connection.el +++ b/cider-connection.el @@ -1015,11 +1015,12 @@ Returns a list of the form ((session1 host1) (session2 host2) ...)." sessions :initial-value '())) -(defun cider-repls (&optional type ensure) +(defun cider-repls (&optional type ensure ops-to-support) "Return cider REPLs of TYPE from the current session. If TYPE is nil or multi, return all REPLs. If TYPE is a list of types, return only REPLs of type contained in the list. If ENSURE is non-nil, -throw an error if no linked session exists." +throw an error if no linked session exists. If OPS-TO-SUPPORT is non-nil, +filters out all the REPLs that do not support the designated ops." (let ((type (cond ((listp type) (mapcar #'cider-maybe-intern type)) @@ -1045,7 +1046,10 @@ throw an error if no linked session exists." (or (seq-filter (lambda (b) (unless (cider-cljs-pending-p b) - (cider--match-repl-type type b))) + (and (cider--match-repl-type type b) + (seq-every-p (lambda (op) + (nrepl-op-supported-p op b)) + ops-to-support)))) repls) (when ensure (cider--no-repls-user-error type))))) @@ -1082,16 +1086,8 @@ session." (ensure (cl-case which-key (:auto nil) (t 'ensure))) - (repls (cider-repls type ensure))) - (mapcar (lambda (repl) - (mapc (lambda (op) - (unless (nrepl-op-supported-p op repl) - (user-error "`%s' requires the nREPL op \"%s\" (provided by cider-nrepl)" - this-command op))) - ops-to-support) - (funcall function repl)) - repls)))) - + (repls (cider-repls type ensure ops-to-support))) + (mapcar function repls)))) ;; REPLs double as connections in CIDER, so it's useful to be able to refer to ;; them as connections in certain contexts. diff --git a/cider-tracing.el b/cider-tracing.el index bccaea407..3efe0a7cf 100644 --- a/cider-tracing.el +++ b/cider-tracing.el @@ -72,10 +72,9 @@ opposite of what that option dictates." "Toggle ns tracing. Defaults to the current ns. With prefix arg QUERY, prompts for a ns." (interactive "P") - (cider-map-repls :clj-strict + (cider-map-repls '(:clj-strict "toggle-trace-ns") (lambda (conn) (with-current-buffer conn - (cider-ensure-op-supported "toggle-trace-ns") (let ((ns (if query (completing-read "Toggle trace for ns: " (cider-sync-request:ns-list)) From b9e244e688d0dc472e8f55a66978c5212d097c5c Mon Sep 17 00:00:00 2001 From: Wilbrt Date: Sat, 4 Oct 2025 12:21:43 +0300 Subject: [PATCH 4/4] 3834 Update changelog, add test for new argument in cider-repls --- CHANGELOG.md | 2 +- doc/modules/ROOT/pages/usage/cider_mode.adoc | 2 +- test/cider-connection-tests.el | 23 ++++++++++++++++++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51b21edf7..18cbb1a4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,12 +8,12 @@ - Bump the injected `nrepl` to [1.4.0](https://github.com/nrepl/nrepl/blob/master/CHANGELOG.md#140-2025-09-02). - Bump the injected `piggieback` to [0.6.1](https://github.com/nrepl/piggieback/blob/master/CHANGES.md#061-2025-12-31). -- [#3834](https://github.com/clojure-emacs/cider/issues/3834): Change cider-ns-refresh to always use Clojure REPL ### Bugs fixed - [#3832](https://github.com/clojure-emacs/cider/issues/3832): Fix nrepl--eval-request sending duplicate info. - [#3837](https://github.com/clojure-emacs/cider/issues/3837): Fix broken stacktrace response when C-c C-p throws an exception. +- [#3834](https://github.com/clojure-emacs/cider/issues/3834): Fix cider-ns-refresh throwing an error when a clojure REPL exists, but cider-current-repl does not support the required operations. ## 1.19.0 (2025-07-10) diff --git a/doc/modules/ROOT/pages/usage/cider_mode.adoc b/doc/modules/ROOT/pages/usage/cider_mode.adoc index 0e4650a4d..1353921e9 100644 --- a/doc/modules/ROOT/pages/usage/cider_mode.adoc +++ b/doc/modules/ROOT/pages/usage/cider_mode.adoc @@ -175,7 +175,7 @@ kbd:[C-u C-c C-c] | `cider-ns-refresh` | kbd:[C-c M-n (M-)r] -| Reload all modified files on the classpath. If invoked with a prefix argument, reload all files on the classpath. If invoked with a double prefix argument, clear the state of the namespace tracker before reloading. Uses a clojure REPL whenever one exists. +| Reload all modified files on the classpath. If invoked with a prefix argument, reload all files on the classpath. If invoked with a double prefix argument, clear the state of the namespace tracker before reloading. | `cider-doc` | kbd:[C-c C-d d] + diff --git a/test/cider-connection-tests.el b/test/cider-connection-tests.el index 60a6765e2..99a4ac6c1 100644 --- a/test/cider-connection-tests.el +++ b/test/cider-connection-tests.el @@ -365,7 +365,8 @@ (expect (cider-repls) :to-have-same-items-as (list l1 l2))))))))) (describe "killed buffers" - (it "do not show up in it" + (it "do not show up in it +" (let ((default-directory (expand-file-name "/tmp/some-dir"))) (cider-test-with-buffers (a b) @@ -398,7 +399,25 @@ (append cider-connection-capabilities '(cljs)))) (expect (cider-repls) :to-equal (list a b)) - (sesman-unregister 'CIDER session))))))) + (sesman-unregister 'CIDER session)))))) + + (describe "when ops-to-support is not nil" + :var (nrepl-ops) + (it "only returns the repls that support the given ops" + (let ((proj-dir (expand-file-name "/tmp/proj-dir"))) + (let ((default-directory proj-dir)) + (with-repl-buffer ses-name 'clj b1 + (setq nrepl-ops (nrepl-dict "refresh" 't)) + (with-repl-buffer ses-name 'clj b2 + (with-repl-buffer ses-name 'cljs b3 + (expect (cider-repls nil nil '("refresh")) :to-equal (list b1)))))))) + (it "raises a user error when ensure is not nil and no repl that supports the ops exist" + (let ((proj-dir (expand-file-name "/tmp/proj-dir"))) + (let ((default-directory proj-dir)) + (with-repl-buffer ses-name 'clj b1 + (with-repl-buffer ses-name 'cljs b2 + (expect (cider-repls nil 't '("refresh")) :to-throw 'user-error)))))))) + (describe "cider--connection-info" (before-each