Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Emit parsed forms as a lazy seq

Thank you, John Hughes (see "Why Functional Programming Matters")
  • Loading branch information...
commit b26828e87962200a1bb456194463bac7bcfc8c9f 1 parent 08e394a
Colin Jones authored
41 spec/reply/eval_modes/nrepl_spec.clj
View
@@ -0,0 +1,41 @@
+(ns reply.eval-modes.nrepl-spec
+ (:use [speclj.core]
+ [reply.eval-modes.nrepl]))
+
+(describe "parsed-forms"
+ (with eof (Object.))
+
+ (it "gets an eof when readLine says it's done"
+ (should= [@eof]
+ (with-in-str ""
+ (doall (parsed-forms @eof)))))
+
+ (it "gets one form"
+ (should= ["foo"]
+ (with-in-str "foo"
+ (doall (parsed-forms @eof)))))
+
+ (it "gets multiline forms"
+ (should= ["(+ 1 2\n3)"]
+ (with-in-str "(+ 1 2\n3)"
+ (doall (parsed-forms @eof)))))
+
+ (it "gets multiline forms, with overlap"
+ (should= ["(+ 1 2\n3)" "(- 3\n1)"]
+ (with-in-str "(+ 1 2\n3) (- 3\n1)"
+ (doall (parsed-forms @eof)))))
+
+ (it "gets multiple forms on a single line"
+ (should= ["1" "2" "3"]
+ (with-in-str "1 2 3"
+ (doall (parsed-forms @eof)))))
+
+ (it "gets an empty couple of lines"
+ (should= [""]
+ (with-in-str "\n\n"
+ (doall (parsed-forms @eof)))))
+
+ (it "gets whitespace"
+ (should= [""]
+ (with-in-str " \n \n"
+ (doall (parsed-forms @eof))))))
46 src/clj/reply/eval_modes/nrepl.clj
View
@@ -81,6 +81,34 @@
[complete-forms {:ns (last results)}]))))
[[] request-exit])))
+(defn parsed-forms
+ ([request-exit] (parsed-forms request-exit nil))
+ ([request-exit text-so-far]
+ (if-let [next-text (.readLine *in*)]
+ (let [concatted-text (if text-so-far
+ (str text-so-far \newline next-text)
+ next-text)
+ parse-tree (sjacket.parser/parser concatted-text)
+ completed? #(not= :net.cgrand.parsley/unfinished (:tag %))]
+ (if (empty? (:content parse-tree))
+ (list "")
+ (let [complete-forms (take-while completed? (:content parse-tree))
+ remainder (drop-while completed? (:content parse-tree))
+ form-strings (map sjacket/str-pt
+ (remove #(contains? #{:whitespace :comment :discard}
+ (:tag %))
+ complete-forms))]
+ (cond (seq remainder)
+ (lazy-seq
+ (concat form-strings
+ (parsed-forms request-exit
+ (apply str (map sjacket/str-pt remainder)))))
+ (seq form-strings)
+ form-strings
+ :else ; all whitespace and/or comments, probably
+ (list "")))))
+ (list request-exit))))
+
(defn run-repl
([connection] (run-repl connection nil))
([connection {:keys [prompt] :as options}]
@@ -92,20 +120,10 @@
read-error (Object.)
execute (partial execute-with-client connection
(assoc options :interactive true))
- [raw-input read-result]
- (try
- (binding [*ns* (eval-state/get-ns)]
- (repl-parse eof execute))
- (catch Exception e
- [e read-error]))]
- (cond (reply.exit/done? eof read-result)
- nil
- (= read-error read-result)
- (do (println raw-input) ; where we stash any read exceptions
- (recur ns))
- :else
- ; TODO: expect result as seq of forms to consume and eval on this side
- (recur (:ns read-result))))))))
+ forms (parsed-forms eof)]
+ (if (reply.exit/done? eof (first forms))
+ nil
+ (recur (last (doall (map execute forms))))))))))
;; TODO: this could be less convoluted if we could break backwards-compat
(defn- url-for [attach host port]
Please sign in to comment.
Something went wrong with that request. Please try again.