branch: elpa/inf-clojure
commit 07a5799706c3519045da4ca0fda14ff81149a7e3
Merge: 5fcfde6b7f ac11ae287b
Author: Bozhidar Batsov <[email protected]>
Commit: Bozhidar Batsov <[email protected]>

    Merge branch 'deduplicate-repl-features'
---
 inf-clojure.el            | 89 +++++++++++++++++++----------------------------
 test/inf-clojure-tests.el | 35 +++++++++++++++++++
 2 files changed, 71 insertions(+), 53 deletions(-)

diff --git a/inf-clojure.el b/inf-clojure.el
index 498b9c0d03..3e55fe06db 100644
--- a/inf-clojure.el
+++ b/inf-clojure.el
@@ -77,13 +77,36 @@
                                     (boot . "boot repl")
                                     (clojure . "clojure")
                                     (cljs . "clojure -M -m cljs.main -r")
+                                    (clojure-clr . "Clojure.Main")
                                     (lein-clr . "lein clr repl")
                                     (planck . "planck -d")
                                     (babashka . "bb")
                                     (joker . "joker")))
 
+(defun inf-clojure--merge-repl-features (base overrides)
+  "Return a new feature alist by merging OVERRIDES onto BASE.
+Keys in OVERRIDES take precedence over those in BASE."
+  (append overrides
+          (cl-remove-if (lambda (entry)
+                          (assq (car entry) overrides))
+                        base)))
+
+(defvar inf-clojure--clojure-repl-base-features
+  '((load . "(clojure.core/load-file \"%s\")")
+    (doc . "(clojure.repl/doc %s)")
+    (source . "(clojure.repl/source %s)")
+    (arglists . "(try (-> '%s clojure.core/resolve clojure.core/meta 
:arglists) (catch Throwable e nil))")
+    (apropos . "(doseq [var (sort (clojure.repl/apropos \"%s\"))] (println 
(str var)))")
+    (ns-vars . "(clojure.repl/dir %s)")
+    (set-ns . "(clojure.core/in-ns '%s)")
+    (macroexpand . "(clojure.core/macroexpand '%s)")
+    (macroexpand-1 . "(clojure.core/macroexpand-1 '%s)"))
+  "Base feature forms shared by Clojure-family REPLs.
+Individual REPL types override specific entries (e.g. `arglists')
+via `inf-clojure--merge-repl-features'.")
+
 (defvar inf-clojure-repl-features
-  '((cljs . ((doc . "(cljs.repl/doc %s)")
+  `((cljs . ((doc . "(cljs.repl/doc %s)")
              (source . "(cljs.repl/source %s)")
              (arglists . "(try (->> '%s cljs.core/resolve cljs.core/meta 
:arglists) (catch :default _ nil))")
              (apropos . "(cljs.repl/apropos \"%s\")")
@@ -113,58 +136,17 @@
               (set-ns . "(in-ns '%s)")
               (macroexpand . "(macroexpand '%s)")
               (macroexpand-1 . "(macroexpand-1 '%s)")))
-    (babashka . ((load . "(clojure.core/load-file \"%s\")")
-                 (doc . "(clojure.repl/doc %s)")
-                 (source . "(clojure.repl/source %s)")
-                 (arglists .
-                           "(try (-> '%s clojure.core/resolve 
clojure.core/meta :arglists)
-                              (catch Throwable e nil))")
-                 (apropos . "(doseq [var (sort (clojure.repl/apropos \"%s\"))] 
(println (str var)))")
-                 (ns-vars . "(clojure.repl/dir %s)")
-                 (set-ns . "(clojure.core/in-ns '%s)")
-                 (macroexpand . "(clojure.core/macroexpand '%s)")
-                 (macroexpand-1 . "(clojure.core/macroexpand-1 '%s)")))
-    (node-babashka . ((load . "(clojure.core/load-file \"%s\")")
-                 (doc . "(clojure.repl/doc %s)")
-                 (source . "(clojure.repl/source %s)")
-                 (arglists .
-                           "(try (-> '%s clojure.core/resolve 
clojure.core/meta :arglists)
-                              (catch Throwable e nil))")
-                 (apropos . "(doseq [var (sort (clojure.repl/apropos \"%s\"))] 
(println (str var)))")
-                 (ns-vars . "(clojure.repl/dir %s)")
-                 (set-ns . "(clojure.core/in-ns '%s)")
-                 (macroexpand . "(clojure.core/macroexpand '%s)")
-                 (macroexpand-1 . "(clojure.core/macroexpand-1 '%s)")))
-    (clojure . ((load . "(clojure.core/load-file \"%s\")")
-                (doc . "(clojure.repl/doc %s)")
-                (source . "(clojure.repl/source %s)")
-                (arglists .
-                          "(try
-                             (:arglists
-                              (clojure.core/meta
-                               (clojure.core/resolve
-                                (clojure.core/read-string \"%s\"))))
-                            (catch #?(:clj Throwable :cljr Exception) e nil))")
-                (apropos . "(doseq [var (sort (clojure.repl/apropos \"%s\"))] 
(println (str var)))")
-                (ns-vars . "(clojure.repl/dir %s)")
-                (set-ns . "(clojure.core/in-ns '%s)")
-                (macroexpand . "(clojure.core/macroexpand '%s)")
-                (macroexpand-1 . "(clojure.core/macroexpand-1 '%s)")))
-    (lein-clr . ((load . "(clojure.core/load-file \"%s\")")
-                 (doc . "(clojure.repl/doc %s)")
-                 (source . "(clojure.repl/source %s)")
-                 (arglists .
-                           "(try
-                             (:arglists
-                              (clojure.core/meta
-                               (clojure.core/resolve
-                                (clojure.core/read-string \"%s\"))))
-                             (catch Exception e nil))")
-                 (apropos . "(doseq [var (sort (clojure.repl/apropos \"%s\"))] 
(println (str var)))")
-                 (ns-vars . "(clojure.repl/dir %s)")
-                 (set-ns . "(clojure.core/in-ns '%s)")
-                 (macroexpand . "(clojure.core/macroexpand '%s)")
-                 (macroexpand-1 . "(clojure.core/macroexpand-1 '%s)")))))
+    (babashka . ,(copy-alist inf-clojure--clojure-repl-base-features))
+    (node-babashka . ,(copy-alist inf-clojure--clojure-repl-base-features))
+    (clojure . ,(copy-alist inf-clojure--clojure-repl-base-features))
+    (clojure-clr . ,(inf-clojure--merge-repl-features
+                     inf-clojure--clojure-repl-base-features
+                     '((arglists .
+                                 "(try (-> '%s clojure.core/resolve 
clojure.core/meta :arglists) (catch Exception e nil))"))))
+    (lein-clr . ,(inf-clojure--merge-repl-features
+                  inf-clojure--clojure-repl-base-features
+                  '((arglists .
+                              "(try (-> '%s clojure.core/resolve 
clojure.core/meta :arglists) (catch Exception e nil))"))))))
 
 (defvar-local inf-clojure-repl-type nil
   "Symbol to define your REPL type.
@@ -497,6 +479,7 @@ port is an integer, or a string to startup an interpreter 
like
 Should be a symbol that is a key in `inf-clojure-repl-features'."
   :package-version '(inf-clojure . "3.0.0")
   :type '(choice (const :tag "clojure" clojure)
+                 (const :tag "clojure-clr" clojure-clr)
                  (const :tag "cljs" cljs)
                  (const :tag "planck" planck)
                  (const :tag "joker" joker)
diff --git a/test/inf-clojure-tests.el b/test/inf-clojure-tests.el
index af6dea905a..ffe29d75f8 100644
--- a/test/inf-clojure-tests.el
+++ b/test/inf-clojure-tests.el
@@ -158,4 +158,39 @@ is a string\")
       (expect (inf-clojure--update-feature 'not-found 'doc "new doc")
               :to-throw))))
 
+(describe "inf-clojure--merge-repl-features"
+  (it "merges overrides onto a base alist"
+    (let ((base '((a . "base-a") (b . "base-b") (c . "base-c")))
+          (overrides '((b . "override-b"))))
+      (expect (inf-clojure--merge-repl-features base overrides)
+              :to-equal '((b . "override-b") (a . "base-a") (c . "base-c")))))
+  (it "preserves the base when overrides are empty"
+    (let ((base '((a . "base-a") (b . "base-b"))))
+      (expect (inf-clojure--merge-repl-features base nil)
+              :to-equal base))))
+
+(describe "inf-clojure-repl-features"
+  (it "provides all base features for clojure-family REPL types"
+    (let ((base-features '(load doc source apropos ns-vars set-ns
+                                macroexpand macroexpand-1 arglists)))
+      (dolist (repl-type '(clojure clojure-clr babashka node-babashka 
lein-clr))
+        (dolist (feature base-features)
+          (expect (inf-clojure--get-feature repl-type feature nil)
+                  :not :to-be nil)))))
+  (it "gives node-babashka the same features as babashka"
+    (let ((bb-features (alist-get 'babashka inf-clojure-repl-features))
+          (nbb-features (alist-get 'node-babashka inf-clojure-repl-features)))
+      (expect bb-features :to-equal nbb-features)))
+  (it "shares arglists across JVM REPL types"
+    (let ((clj-arglists (inf-clojure--get-feature 'clojure 'arglists nil))
+          (bb-arglists (inf-clojure--get-feature 'babashka 'arglists nil)))
+      (expect clj-arglists :to-equal bb-arglists)))
+  (it "uses a different arglists catch clause for CLR REPL types"
+    (let ((clj-arglists (inf-clojure--get-feature 'clojure 'arglists nil))
+          (clr-arglists (inf-clojure--get-feature 'clojure-clr 'arglists nil))
+          (lein-clr-arglists (inf-clojure--get-feature 'lein-clr 'arglists 
nil)))
+      (expect clj-arglists :not :to-equal clr-arglists)
+      (expect clr-arglists :to-equal lein-clr-arglists)
+      (expect clr-arglists :to-match "Exception"))))
+
 ;;; inf-clojure-tests.el ends here

Reply via email to