branch: elpa/inf-clojure
commit d6a23b658f1eb6a8abdc835de8a811e9b3a039bc
Author: Bozhidar Batsov <[email protected]>
Commit: Bozhidar Batsov <[email protected]>

    Deduplicate Clojure-family REPL feature definitions
    
    The clojure, babashka, node-babashka, and lein-clr entries in
    inf-clojure-repl-features were near-identical copies differing
    only in their arglists catch clause. Extract the shared features
    into inf-clojure--clojure-repl-base-features and derive each
    variant via inf-clojure--merge-repl-features, overriding only
    arglists. node-babashka is now a true alias for babashka.
    
    The resulting runtime data structure is identical, so all existing
    feature lookup and update code works unchanged.
---
 inf-clojure.el            | 87 +++++++++++++++++++++++------------------------
 test/inf-clojure-tests.el | 31 +++++++++++++++++
 2 files changed, 73 insertions(+), 45 deletions(-)

diff --git a/inf-clojure.el b/inf-clojure.el
index 498b9c0d03..c0d20a5d15 100644
--- a/inf-clojure.el
+++ b/inf-clojure.el
@@ -82,8 +82,29 @@
                                     (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)")
+    (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 (typically `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 +134,34 @@
               (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
+    (babashka . ,(inf-clojure--merge-repl-features
+                  inf-clojure--clojure-repl-base-features
+                  '((arglists .
+                              "(try (-> '%s clojure.core/resolve 
clojure.core/meta :arglists)
+                              (catch Throwable e nil))"))))
+    (node-babashka . ,(inf-clojure--merge-repl-features
+                       inf-clojure--clojure-repl-base-features
+                       '((arglists .
+                                   "(try (-> '%s clojure.core/resolve 
clojure.core/meta :arglists)
+                              (catch Throwable e nil))"))))
+    (clojure . ,(inf-clojure--merge-repl-features
+                 inf-clojure--clojure-repl-base-features
+                 '((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
+                            (catch #?(:clj Throwable :cljr Exception) e 
nil))"))))
+    (lein-clr . ,(inf-clojure--merge-repl-features
+                  inf-clojure--clojure-repl-base-features
+                  '((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)")))))
+                             (catch Exception e nil))"))))))
 
 (defvar-local inf-clojure-repl-type nil
   "Symbol to define your REPL type.
diff --git a/test/inf-clojure-tests.el b/test/inf-clojure-tests.el
index af6dea905a..c1327a0b03 100644
--- a/test/inf-clojure-tests.el
+++ b/test/inf-clojure-tests.el
@@ -158,4 +158,35 @@ 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 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 "differentiates arglists across clojure-family REPL types"
+    (let ((clj-arglists (inf-clojure--get-feature 'clojure 'arglists nil))
+          (bb-arglists (inf-clojure--get-feature 'babashka 'arglists nil))
+          (clr-arglists (inf-clojure--get-feature 'lein-clr 'arglists nil)))
+      (expect clj-arglists :not :to-equal bb-arglists)
+      (expect clj-arglists :not :to-equal clr-arglists)
+      (expect bb-arglists :not :to-equal clr-arglists))))
+
 ;;; inf-clojure-tests.el ends here

Reply via email to