From d18cc7e763192adbb9ca52eede99c4f1365a6b6a Mon Sep 17 00:00:00 2001 From: Brandon Bloom Date: Mon, 18 Jun 2012 01:14:46 -0700 Subject: [PATCH] Implement with-out-str; also fixes CLJS-319 --- src/clj/cljs/core.clj | 12 +++++++- src/cljs/cljs/core.cljs | 61 +++++++++++++---------------------------- test/cljs/cljs/core_test.cljs | 2 + 3 files changed, 32 insertions(+), 43 deletions(-) diff --git a/src/clj/cljs/core.clj b/src/clj/cljs/core.clj index 70c1509..4f41636 100644 --- a/src/clj/cljs/core.clj +++ b/src/clj/cljs/core.clj @@ -1041,4 +1041,14 @@ (if (zero? ~'argc) (~'f) ~(gen-apply-to-helper)))) - (set! ~'*unchecked-if* false))) \ No newline at end of file + (set! ~'*unchecked-if* false))) + +(defmacro with-out-str + "Evaluates exprs in a context in which *print-fn* is bound to .append + on a fresh StringBuffer. Returns the string created by any nested + printing calls." + [& body] + `(let [sb# (goog.string/StringBuffer.)] + (binding [cljs.core/*print-fn* (fn [x#] (.append sb# x#))] + ~@body) + (cljs.core/str sb#))) diff --git a/src/cljs/cljs/core.cljs b/src/cljs/cljs/core.cljs index cbea7d9..a575db4 100644 --- a/src/cljs/cljs/core.cljs +++ b/src/cljs/cljs/core.cljs @@ -17,7 +17,7 @@ (def ^{:doc "Each runtime environment provides a diffenent way to print output. Whatever function *print-fn* is bound to will be passed any - Strings which should be printed."} + Strings which should be printed." :dynamic true} *print-fn* (fn [_] (throw (js/Error. "No *print-fn* fn set for evaluation environment")))) @@ -6104,39 +6104,16 @@ reduces them without incurring seq initialization" :else (list "#<" (str obj) ">"))))) -(defn- pr-sb [objs opts] - (let [first-obj (first objs) - sb (gstring/StringBuffer.)] - (doseq [obj objs] - (when-not (identical? obj first-obj) - (.append sb " ")) - (doseq [string (pr-seq obj opts)] - (.append sb string))) - sb)) - -(defn pr-str-with-opts - "Prints a sequence of objects to a string, observing all the - options given in opts" - [objs opts] - (str (pr-sb objs opts))) - -(defn prn-str-with-opts - "Same as pr-str-with-opts followed by (newline)" - [objs opts] - (let [sb (pr-sb objs opts)] - (.append sb \newline) - (str sb))) - (defn pr-with-opts "Prints a sequence of objects using string-print, observing all the options given in opts" [objs opts] - (let [first-obj (first objs)] - (doseq [obj objs] - (when-not (identical? obj first-obj) - (string-print " ")) - (doseq [string (pr-seq obj opts)] - (string-print string))))) + (doseq [string (pr-seq (first objs) opts)] + (string-print string)) + (doseq [obj (next objs)] + (string-print " ") + (doseq [string (pr-seq obj opts)] + (string-print string)))) (defn newline [opts] (string-print "\n") @@ -6154,16 +6131,6 @@ reduces them without incurring seq initialization" :meta *print-meta* :dup *print-dup*}) -(defn pr-str - "pr to a string, returning it. Fundamental entrypoint to IPrintable." - [& objs] - (pr-str-with-opts objs (pr-opts))) - -(defn prn-str - "Same as pr-str followed by (newline)" - [& objs] - (prn-str-with-opts objs (pr-opts))) - (defn pr "Prints the object(s) using string-print. Prints the object(s), separated by spaces if there is more than one. @@ -6172,6 +6139,11 @@ reduces them without incurring seq initialization" [& objs] (pr-with-opts objs (pr-opts))) +(defn pr-str + "pr to a string, returning it. Fundamental entrypoint to IPrintable." + [& objs] + (with-out-str (apply pr objs))) + (def ^{:doc "Prints the object(s) using string-print. print and println produce output for human consumption."} @@ -6182,7 +6154,7 @@ reduces them without incurring seq initialization" (defn print-str "print to a string, returning it" [& objs] - (pr-str-with-opts objs (assoc (pr-opts) :readably false))) + (with-out-str (apply print objs))) (defn println "Same as print followed by (newline)" @@ -6193,7 +6165,7 @@ reduces them without incurring seq initialization" (defn println-str "println to a string, returning it" [& objs] - (prn-str-with-opts objs (assoc (pr-opts) :readably false))) + (with-out-str (apply println objs))) (defn prn "Same as pr followed by (newline)." @@ -6201,6 +6173,11 @@ reduces them without incurring seq initialization" (pr-with-opts objs (pr-opts)) (newline (pr-opts))) +(defn prn-str + "Same as pr-str followed by (newline)" + [& objs] + (with-out-str (apply prn objs))) + (extend-protocol IPrintable boolean (-pr-seq [bool opts] (list (str bool))) diff --git a/test/cljs/cljs/core_test.cljs b/test/cljs/cljs/core_test.cljs index eae66ac..a7825ee 100644 --- a/test/cljs/cljs/core_test.cljs +++ b/test/cljs/cljs/core_test.cljs @@ -213,6 +213,7 @@ (assoc (cljs.core.ObjMap. nil (array) (js-obj)) :foo 5))) (assert (= "\"asdf\"" (pr-str "asdf"))) + (assert (= "1 1 2 2" (pr-str 1 1 2 2))) (assert (= "[1 true {:a 2, :b #\"x\\\"y\"} #]" (pr-str [1 true {:a 2 :b #"x\"y"} (array 3 4)]))) @@ -220,6 +221,7 @@ (assert (= "[1 true {:a 2, :b 42} #]\n" (prn-str [1 true {:a 2 :b 42} (array 3 4)]))) + (assert (= "12" (with-out-str (print 1) (print 2)))) (assert (= "asdf" (print-str "asdf"))) (assert (= "asdf\n" (println-str "asdf"))) -- 1.7.9.1