+
+;; This file is not part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see .
+
+;;; Commentary:
+;;
+;; Tests for inf-clojure.
+
+;;; Code:
+
+(message "Running tests on Emacs %s" emacs-version)
+
+(require 'buttercup)
+(require 'assess) ;; requires Emacs 26, due to a dependency on seq.el
+(require 'inf-clojure)
+
+(cl-defmacro ict-with-assess-buffers ((&rest varlist) &body body)
+ `(assess-with-temp-buffers (,@varlist)
+ (clojure-mode)
+ (inf-clojure-minor-mode)
+ ,@body))
+
+(defun ict-bounds-string (bounds)
+ (buffer-substring (car bounds) (cdr bounds)))
+
+(describe "inf-clojure--kw-to-symbol"
+ (it "returns symbol form of the given keyword"
+ (expect (inf-clojure--kw-to-symbol "symbol") :to-equal "symbol")
+ (expect (inf-clojure--kw-to-symbol ":clj.core/str") :to-equal "clj.core/str")
+ (expect (inf-clojure--kw-to-symbol "::keyword") :to-equal "keyword")
+ (expect (inf-clojure--kw-to-symbol nil) :to-equal nil)))
+
+(describe "completion bounds at point"
+ (it "computes bounds for plain-text"
+ (ict-with-assess-buffers
+ ((a (insert "plain-text")))
+ (with-current-buffer a
+ (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point))
+ :to-equal "plain-text"))))
+
+ (it "computes bounds for @deref"
+ (ict-with-assess-buffers
+ ((a (insert "@deref")))
+ (with-current-buffer a
+ (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point))
+ :to-equal "deref"))))
+
+ (it "computes bounds for ^:keyword"
+ (ict-with-assess-buffers
+ ((a (insert "^:keyword")))
+ (with-current-buffer a
+ (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point))
+ :to-equal ":keyword"))))
+
+ (it "computes bounds for ::keyword"
+ (ict-with-assess-buffers
+ ((a (insert "::keyword")))
+ (with-current-buffer a
+ (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point))
+ :to-equal "::keyword"))))
+
+ (it "computes bounds for [^:keyword (combined break chars and keyword)"
+ (ict-with-assess-buffers
+ ((a (insert "[^:keyword")))
+ (with-current-buffer a
+ (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point))
+ :to-equal ":keyword"))))
+
+ (it "computes no bounds for point directly after a break expression"
+ (ict-with-assess-buffers
+ ((a (insert "@")))
+ (with-current-buffer a
+ (expect (inf-clojure-completion-bounds-of-expr-at-point)
+ :to-be nil))))
+
+ (it "computes bounds for [symbol"
+ (ict-with-assess-buffers
+ ((a (insert "[symbol")))
+ (with-current-buffer a
+ (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point))
+ :to-equal "symbol"))))
+
+ (it "computes bounds for (@deref (multiple break chars)"
+ (ict-with-assess-buffers
+ ((a (insert "(@deref")))
+ (with-current-buffer a
+ (expect (ict-bounds-string (inf-clojure-completion-bounds-of-expr-at-point))
+ :to-equal "deref")))))
+
+(describe "inf-clojure--sanitize-command"
+ (it "sanitizes the command correctly"
+ (expect (inf-clojure--sanitize-command "(doc println)") :to-equal "(doc println)\n"))
+
+ (it "trims newline at the right of a command"
+ (expect (inf-clojure--sanitize-command "(doc println)\n\n\n\n") :to-equal "(doc println)\n"))
+
+ (it "returns empty string when the command is empty"
+ (expect (inf-clojure--sanitize-command " ") :to-equal ""))
+
+ (it "only removes whitespace at the end of the command - fix 152"
+ (expect (inf-clojure--sanitize-command "1 5") :to-equal "1 5\n")))
+
+(describe "inf-clojure--forms-without-newlines"
+ (it "removes newlines between toplevel forms"
+ (expect (inf-clojure--forms-without-newlines
+ "(def foo 3)\n\n\n(def bar 4)")
+ :to-equal "(def foo 3)\n(def bar 4)"))
+ (it "doesn't remove newlines inside forms or strings"
+ (expect (inf-clojure--forms-without-newlines
+ "
+
+(defn foo []
+
+ :foo)
+
+
+(def thing \"this
+
+is a string\")
+
+(defn bar [])")
+ ;; note no leading newline, newlines inside defn remain,
+ ;; newlines inside string remain
+ :to-equal "(defn foo []
+
+ :foo)
+(def thing \"this
+
+is a string\")
+(defn bar [])")))
+
+
+(describe "inf-clojure--update-feature"
+ (it "updates new forms correctly"
+ (let ((inf-clojure-repl-features (inf-clojure--update-feature 'cljs 'doc "new doc")))
+ (expect (inf-clojure--get-feature 'cljs 'doc nil)
+ :to-equal "new doc")))
+ (describe "if the repl type is unknown"
+ (it "signals an error"
+ (expect (inf-clojure--update-feature 'not-found 'doc "new doc")
+ :to-throw))))
+
+;;; inf-clojure-tests.el ends here
diff --git a/todo.org b/todo.org
new file mode 100644
index 0000000..811c287
--- /dev/null
+++ b/todo.org
@@ -0,0 +1,85 @@
+* Core
+
+** DONE set repl type on connection not first command
+For some reason ~inf-clojure--set-repl-type~ is called in:
+1. inf-clojure--send-string
+2. inf-clojure-reload-form
+3. inf-clojure-reload-all-form
+
+Seems better to do this on the two different connection methods and then be done with it?
+
+** DONE do we need repl type in both source buffer and connection?
+ these can get out of sync and lead to confusing errors when closing a repl and opening a new one. It seems like we keep the repl-type in the source buffer to prevent a single ~(with-current-buffer (process-buffer proc) inf-clojure-repl-type)~
+
+** DONE Better dispatch for the implementations
+Right now the functions are kinda clunky cond statements:
+#+BEGIN_SRC emacs-lisp
+ (defun inf-clojure-cljs-features-dispatch (feature)
+ (case feature
+ ;; ((load) "(cljs.core/load-file \"%s\")")
+ ((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\")")
+ ((ns-vars) "(cljs.repl/dir %s)")
+ ((set-ns) "(cljs.core/in-ns '%s)")
+ ((macroexpand) "(cljs.core/macroexpand '%s)")
+ ((macroexpand-1) "(cljs.core/macroexpand-1 '%s)")
+ ;; ((completion) inf-clojure-completion-form-lumo)
+ ))
+#+END_SRC
+
+I really want something similar to ~(defprotocol Inf-clojure-REPL (doc ...)(source ...))~ rather than just this super open ended dispatch on symbols. I just don't know enough elisp at the moment. Also, the current function version prevents introspection and providing a way of listing the repl's capabilities without duplicating the keys. Or maybe a hack of sending all of the known keys in and seeing which return strings. Still not great.
+
+** TODO Nicer interface to create a command
+Right now everything is just a format string with a _single_ ~%s~ in it and that's called with ~(format feature-form e)~ where ~e~ is a symbol, or a form, or a whatever makes sense for that type of feature. This isn't super elegant although it does keep inf-clojure honest in that _all_ it does it format commands to ask a simple repl. But there could probably be a better way.
+
+** DONE Simpler way to define an implementation
+This first pass is very mechanical and just rearranging so we can easily see which features are where. In the future we should look into just providing the repl namespace and seeing how far we can get with that. For instance, an API like ~(inf-clojure-register 'bb "bb.repl")~ and this would tell us where ~source~, ~doc~, ~apropos~ ...etc live. No reason to duplicate all of these.
+
+** DONE ability to update repl commands
+ we had this feature originally but now they are all literals. This is almost entirely fine but one problem. It would be common to toss clojure completions on the class path and then add the completions form for clojure.
+
+This should come back but only in a sense: if you don't have this on the classpath its obviously unacceptable to throw errors every time the user hits tab. Do we need some state recording if this is on the classpath or not maybe?
+
+#+BEGIN_SRC emacs-lisp
+ (defcustom inf-clojure-completion-form
+ "(complete.core/completions \"%s\")"
+ "Form to query inferior Clojure for completion candidates."
+ :type 'string
+ :safe #'stringp
+ :package-version '(inf-clojure . "2.0.0"))
+#+END_SRC
+** TODO Multiple connections
+As proven by CIDER, multiple connections are just a pain. Scoping, navigating into dependencies, etc. This is a monster lurking
+
+** TODO navigation to source
+The source primitive is quite nice but we most likely need a way to navigate to source. Possibly punt on this and just suggest people use with clojure-lsp?
+
+** TODO PREPL
+Be nice to implement this now that we have parseedn in elisp to understand edn.
+
+** DONE inhibit custom repl-type and startup form
+its nice to have these in dir-locals to just start up. but if you normally have ~clojure -m cljs.main -r~ as the startup command but you want to crank up a clj repl there's no way without removing those dir locals.
+* Nice-to-haves
+** TODO Put repl type in modeline
+Rather than just ~*inf-clojure*~ we could put the repl type. Make it easy to follow and makes it easy to see when it gets it wrong.
+
+** TODO How do CIDER and inf-clojure play nice on the same emacs?
+inf-clojure and CIDER are fighting over the keymappings. I've been doing a bit of a kludge to remove CIDER's tentacles from my clojure files for developing:
+#+BEGIN_SRC emacs-lisp
+ (seq-doseq (buffer (buffer-list))
+ (with-current-buffer buffer
+ (cider-mode -1))
+ (remove-hook 'clojure-mode-hook #'cider-mode))
+#+END_SRC
+Seems a bit heavy handed but its working for me so far.
+
+** TODO is disabling color still required?
+ in the readme it mentions that color should be turned off. in my usage I haven't run into this problem at all. perhaps no longer true?
+** TODO nice startup
+There's some project detection but that's becoming less and less useful as time goes on. Shadow, lein, deps.edn can all easily be mixed in the same project. And then lumo, planck, or bb scripts could live side by side. Rather than trying to guess the project type, I think i'd like to mimic geiser's style of handling multiple scheme backends. Perhaps ~m-x inf-clojure-run-planck~ and similar could help out.
+
+Some considerations:
+- is this path aware? IE, don't show an option to run planck, lumo, etc, if they aren't visible or installed?
+- should it have a rebuild function so that user registered implementations can show up in the ~m-x~ menu as well?
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy