我正在尝试让clojure程序中的所有print语句将其字符串放在core.async通道上。有没有办法可以做到这一点?
(我正试图让cljsbuild
将其编译器消息发送到前端。)
答案 0 :(得分:2)
(def is (java.io.PipedInputStream.))
(def os (java.io.PipedOutputStream. is))
(def channel (chan))
(.start (Thread. (fn []
(let [buffer (byte-array 1024)]
(while true
(let [n (.read is buffer 0 1024)]
(>!! channel (vec (take n buffer)))))))))
(binding [*out* (java.io.OutputStreamWriter. os)]
(println "Hello, world!"))
答案 1 :(得分:1)
gfredericks在#clojure irc中给了我这个参考。他建议我改编nREPL的作用:
(defn- session-out
"Returns a PrintWriter suitable for binding as *out* or *err*. All of
the content written to that PrintWriter will (when .flush-ed) be sent on the
given transport in messages specifying the given session-id.
`channel-type` should be :out or :err, as appropriate."
[channel-type session-id transport]
(let [buf (clojure.tools.nrepl.StdOutBuffer.)]
(PrintWriter. (proxy [Writer] []
(close [] (.flush ^Writer this))
(write [& [x ^Integer off ^Integer len]]
(locking buf
(cond
(number? x) (.append buf (char x))
(not off) (.append buf x)
; the CharSequence overload of append takes an *end* idx, not length!
(instance? CharSequence x) (.append buf ^CharSequence x (int off) (int (+ len off)))
:else (.append buf ^chars x off len))
(when (<= *out-limit* (.length buf))
(.flush ^Writer this))))
(flush []
(let [text (locking buf (let [text (str buf)]
(.setLength buf 0)
text))]
(when (pos? (count text))
(t/send (or (:transport *msg*) transport)
(response-for *msg* :session session-id
channel-type text))))))
true)))