Search code examples
macosclojureleiningennrepl

copy result from leiningen repl into clipboard


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.


Solution

  • 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