[#348] nrepl: support multiple top level expressions

This commit is contained in:
Michiel Borkent 2020-04-11 21:36:33 +02:00
parent 56a798135c
commit e2bdd7eae2
2 changed files with 40 additions and 25 deletions

View file

@ -3,8 +3,10 @@
(:refer-clojure :exclude [send future binding]) (:refer-clojure :exclude [send future binding])
(:require [babashka.impl.bencode.core :refer [write-bencode read-bencode]] (:require [babashka.impl.bencode.core :refer [write-bencode read-bencode]]
[clojure.string :as str] [clojure.string :as str]
[clojure.tools.reader.reader-types :as r]
[sci.core :as sci] [sci.core :as sci]
[sci.impl.interpreter :refer [eval-string*]] [sci.impl.interpreter :refer [eval-string* eval-form]]
[sci.impl.parser :as p]
[sci.impl.utils :as sci-utils] [sci.impl.utils :as sci-utils]
[sci.impl.vars :as vars]) [sci.impl.vars :as vars])
(:import [java.io StringWriter OutputStream InputStream PushbackInputStream EOFException BufferedOutputStream] (:import [java.io StringWriter OutputStream InputStream PushbackInputStream EOFException BufferedOutputStream]
@ -38,16 +40,19 @@
(defn eval-msg [ctx o msg] (defn eval-msg [ctx o msg]
(try (try
(let [ns-str (get msg :ns)
sci-ns (when ns-str (sci-utils/namespace-object (:env ctx) (symbol ns-str) true nil))
sw (StringWriter.)]
(sci/with-bindings (cond-> {sci/out sw}
sci-ns (assoc vars/current-ns sci-ns))
(when @dev? (println "current ns" (vars/current-ns-name)))
(let [code-str (get msg :code) (let [code-str (get msg :code)
value (if (str/blank? code-str) reader (r/indexing-push-back-reader (r/string-push-back-reader code-str))
::nil ns-str (get msg :ns)
(eval-string* ctx code-str)) sci-ns (when ns-str (sci-utils/namespace-object (:env ctx) (symbol ns-str) true nil))]
(when @dev? (println "current ns" (vars/current-ns-name)))
(sci/with-bindings (cond-> {}
sci-ns (assoc vars/current-ns sci-ns))
(loop []
(let [sw (StringWriter.)
form (p/parse-next ctx reader)
value (if (identical? :edamame.impl.parser/eof form) ::nil
(sci/with-bindings {sci/out sw}
(eval-form ctx form)))
out-str (not-empty (str sw)) out-str (not-empty (str sw))
env (:env ctx)] env (:env ctx)]
(swap! env update-in [:namespaces 'clojure.core] (swap! env update-in [:namespaces 'clojure.core]
@ -61,7 +66,9 @@
(send o (response-for msg {"out" out-str}))) (send o (response-for msg {"out" out-str})))
(send o (response-for msg (cond-> {"ns" (vars/current-ns-name)} (send o (response-for msg (cond-> {"ns" (vars/current-ns-name)}
(not (identical? value ::nil)) (assoc "value" (pr-str value))))) (not (identical? value ::nil)) (assoc "value" (pr-str value)))))
(send o (response-for msg {"status" #{"done"}}))))) (when (not (identical? ::nil value))
(recur)))))
(send o (response-for msg {"status" #{"done"}})))
(catch Exception ex (catch Exception ex
(swap! (:env ctx) update-in [:namespaces 'clojure.core] (swap! (:env ctx) update-in [:namespaces 'clojure.core]
assoc '*e ex) assoc '*e ex)

View file

@ -76,7 +76,15 @@
"id" (new-id!) "id" (new-id!)
"ns" "unicorn"}) "ns" "unicorn"})
(let [reply (read-reply in session @id)] (let [reply (read-reply in session @id)]
(is (= "unicorn" (:value reply))))))) (is (= "unicorn" (:value reply))))))
(testing "multiple top level expressions results in two value replies"
(bencode/write-bencode os {"op" "eval"
"code" "(+ 1 2 3) (+ 1 2 3)"
"session" session
"id" (new-id!)})
(let [reply-1 (read-reply in session @id)
reply-2 (read-reply in session @id)]
(is (= "6" (:value reply-1) (:value reply-2))))))
(testing "load-file" (testing "load-file"
(bencode/write-bencode os {"op" "load-file" "file" "(ns foo) (defn foo [] :foo)" "session" session "id" (new-id!)}) (bencode/write-bencode os {"op" "load-file" "file" "(ns foo) (defn foo [] :foo)" "session" session "id" (new-id!)})
(read-reply in session @id) (read-reply in session @id)