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