branch: elpa/inf-clojure commit 675e9bed1503b7a1161ed1c1f517803bef929077 Author: dan sutton <d...@dpsutton.com> Commit: Bozhidar Batsov <bozhidar.bat...@gmail.com>
Handle newlines between forms for `inf-clojure-eval-buffer` This sends the contents of the buffer. However, newlines cause the prompt to be returned. You can see this with even a regular clojure repl: ```bash ❯❯❯ clojure Clojure 1.10.2 user=> user=> user=> ``` (note using `clj` has rlwrap which hides a bit of this so make sure to use `clojure`). But what we can do is make sure to transform ```clojure (defn foo [] ...) (defn bar [] ...) ``` into ```clojure (defn foo [] ...) (defn bar [] ...) ``` So that the newlines don't trigger more repl prompts. Real world usage below: Before: ```clojure parse=> nil parse=> parse=> nil parse=> parse=> #'parse/data parse=> parse=> #'parse/parse-where parse=> parse=> #'parse/keywords parse=> parse=> #'parse/tokenize parse=> parse=> #'parse/parse parse=> parse=> #'parse/translate-where parse=> parse=> nil parse=> parse=> #'parse/query parse=> parse=> #'parse/query-test parse=> parse=> #'parse/bonus-points-test parse=> ``` After: ```clojure user=> nil parse=> nil parse=> #'parse/data parse=> #'parse/parse-where parse=> #'parse/keywords parse=> parse=> #'parse/parse parse=> #'parse/translate-where parse=> nil parse=> #'parse/query parse=> #'parse/query-test parse=> #'parse/bonus-points-test parse=> ``` --- inf-clojure.el | 34 +++++++++++++++++++++++++++++----- test/inf-clojure-tests.el | 29 +++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/inf-clojure.el b/inf-clojure.el index 4d32d06..a97066b 100644 --- a/inf-clojure.el +++ b/inf-clojure.el @@ -683,16 +683,40 @@ HOST is the host the process is running on, PORT is where it's listening." (interactive "shost: \nnport: ") (inf-clojure (cons host port))) +(defun inf-clojure--forms-without-newlines (str) + "Remove newlines between toplevel forms. +STR is a string of contents to be evaluated. When sending +multiple forms to a socket repl, each newline triggers a prompt. +So we replace all newlines between top level forms but not inside +of forms." + (condition-case nil + (with-temp-buffer + (progn + (clojurec-mode) + (insert str) + (whitespace-cleanup) + (goto-char (point-min)) + (while (not (eobp)) + (while (looking-at "\n") + (delete-char 1)) + (unless (eobp) + (clojure-forward-logical-sexp)) + (unless (eobp) + (forward-char))) + (buffer-substring-no-properties (point-min) (point-max)))) + (scan-error str))) + (defun inf-clojure-eval-region (start end &optional and-go) "Send the current region to the inferior Clojure process. Sends substring between START and END. Prefix argument AND-GO means switch to the Clojure buffer afterwards." (interactive "r\nP") - ;; drops newlines at the end of the region - (let ((str (replace-regexp-in-string - "[\n]+\\'" "" - (buffer-substring-no-properties start end)))) - (inf-clojure--send-string (inf-clojure-proc) str)) + (let* ((str (buffer-substring-no-properties start end)) + ;; newlines over a socket repl between top level forms cause + ;; a prompt to be returned. so here we dump the region into a + ;; temp buffer, and delete all newlines between the forms + (formatted (inf-clojure--forms-without-newlines str))) + (inf-clojure--send-string (inf-clojure-proc) formatted)) (when and-go (inf-clojure-switch-to-repl t))) (defun inf-clojure-eval-string (code) diff --git a/test/inf-clojure-tests.el b/test/inf-clojure-tests.el index 71f9266..635ac2c 100644 --- a/test/inf-clojure-tests.el +++ b/test/inf-clojure-tests.el @@ -119,6 +119,35 @@ (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"