Occasionally I would like to poke a result in the repl in other software. Is there a convenient way to copy the outcome of a function run in a repl to system clipboard? I know I can spit
the result out to a file. I'm using mac os x.
you can always rebind *out*
special variable, to point to a new location. For example you could collect all your output to string:
user> (def result (java.io.StringWriter.))
#'user/result
user> (binding [*out* result]
(println :aaa)
(println :bbb))
nil
user> (str result)
":aaa\n:bbb\n"
this is a temporary binding, beaning that *out*
would be intact outside the binding
block:
user> (println :aaa)
:aaa
nil
also you could reset the out on a thread level using set!
:
user> (def result (java.io.StringWriter.))
#'user/result
user> (set! *out* result)
#object[java.io.StringWriter 0x66c129d9 ""]
user> (println :aaa)
nil
user> (println :bbb)
nil
user> (str result)
":aaa\n:bbb\n"
then, you can put this string into clipboard using java.awt classes:
user> (import 'java.awt.Toolkit)
java.awt.Toolkit
user> (import 'java.awt.datatransfer.StringSelection)
java.awt.datatransfer.StringSelection
user> (.. Toolkit
(getDefaultToolkit)
(getSystemClipboard)
(setContents (StringSelection. (str result)) nil))
nil
That's it. Now just paste it. Should work properly on mac.
Then you can just generalize it with a macro:
(defmacro with-clipboard [& body]
`(binding [*out* (java.io.StringWriter.)]
(let [result# (do ~@body)]
(.. Toolkit
(getDefaultToolkit)
(getSystemClipboard)
(setContents (StringSelection. (str *out*)) nil))
result#)))
and use it like this:
user> (with-clipboard
(println :hello)
(println :clipboard)
(+ 10 20))
;; => 30
and clipboard will contain:
:hello
:clipboard