Fork me on GitHub
#planck
<
2019-02-18
>
pyrmont02:02:22

Hi all 👋

pyrmont02:02:17

Is it possible to bind *out* to something that would allow me to capture it as a string? I'd like to capture the output of planck.core/load-string and I assume the output from that is going to *out* (but maybe not?).

mfikes02:02:13

@mike858 If the forms being evaluated write to out, then you can capture any such output using with-out-str. For example

(with-out-str (planck.core/load-string "(pr :hi)"))
evaluates to
":hi"

pyrmont02:02:29

I'm probably going about this the wrong way but what I want to do is to send a string to a socket REPL, have it be evaluated and then have the output (including error messages) saved into a string I can send back on the wire. A socket REPL will output to the wire at the moment but I'm messing about with a plugin for Neovim that would send a buffer of ClojureScript to the socket REPL and there are two problems: (1) an unclosed form will return nothing because the REPL is waiting for the closing parenthesis; (2) there's no way to tell when the output received back on the socket in Neovim is the 'end'. My idea was to wrap the code as a string, unwrap it on the REPL, load it in, capture the output, send that back as a string. I can then have the Neovim plugin wait until it gets the 'end' of the string and know I'm at the end of the output. Hopefully that made sense.

pyrmont02:02:36

Basically what I want to do is be able to send a buffer to a Planck socket REPL and have it be evaluated (with some kind of response to indicate whether it was successful or unsuccessful). There are other solutions for REPL development in Vim but they're all based on nREPL.

mfikes02:02:56

One thing to consider is that output could be printed asynchronously. For example

(js/setTimeout #(prn :hi) 5000)

mfikes02:02:53

Yeah, I tend to use conventional REPL support in Cursive, with Tubular.

mfikes02:02:03

Not perfect, but, it works.

pyrmont02:02:31

Yeah. I do my development via a Raspberry Pi on my iPhone :(

pyrmont02:02:05

That's part of why I got very excited by Planck :D

pyrmont02:02:00

It took about 15 hours but successfully compiled Planck on Raspbian on Friday! The --fast option only takes a couple of hours.

mfikes02:02:01

So, you have Planck running on the Pi?

mfikes02:02:21

And then, how is your iPhone related? It is your terminal?

pyrmont02:02:43

Works great :D I do have the very slow initial function evaluation that someone complained about on GitHub.

pyrmont02:02:51

I meant to write a reply to that.

pyrmont03:02:51

I have two young kids and my wife's been ill so I don't have much time to program except on the train to and from work (I work as an in-house lawyer). I use Blink on the iPhone to connect to my Pi at home via Mosh (connection is to fickle for SSH). I then program in Vim.

mfikes03:02:51

Interesting. For testing out simple pure functions, you could use Replete as well.

pyrmont03:02:02

Yeah, I have that too! :)

pyrmont03:02:48

But it's not too much fun trying to program in the little input field on the standard iOS keyboard. Blink has its own custom keys (TAB, CTRL, etc).

mfikes03:02:05

Hah. Before all of this existed, I used to use my iPhone to SSH into my Linux box and execute forms in a Clojure REPL. 🙂

mfikes03:02:55

So, I see why you can't use Tubular 🙂

pyrmont03:02:58

Oh, and your suggestion for with-out-str works for capturing printed output but the output from load-string didn't get captured.

mfikes03:02:01

I guess load-string itself returns the value of the last form it evaluates...

pyrmont03:02:29

I've also tried:

(import '[goog.string StringBuffer])
(def sb (StringBuffer.))
(binding [*out* (StringBufferWriter. sb)] 
  (planck.core/load-string "(+ 1 2)"))

pyrmont03:02:42

That's true.

pyrmont03:02:20

It's really the warnings and error messages that I need as well. You can get the error from *e but I'm not sure where the warning message goes.

pyrmont03:02:36

Maybe with-out-str would work for that. Something to try :)

mfikes03:02:17

If you want the return value as a string, you could (pr-str (planck.core/load-string "(+ 1 2)")) ?

pyrmont03:02:29

Hmmm, no, that didn't work either.

pyrmont03:02:05

pr-str is helpful for the return value :D

pyrmont03:02:24

Thanks! I'll have to think more about how to get those warnings.

mfikes03:02:07

I bet you could set! *print-err-fn* to something that would capture errors

pyrmont03:02:26

Ooh. Thanks :)

pyrmont03:02:38

I'll have a look at that!

pyrmont03:02:39

Oh, and thanks for Planck. It's terrific :D

mfikes03:02:55

Glad you are finding value in it 🙂

pyrmont06:02:42

Hmmm. Perhaps this is the point at which I call it quits but for some reason set! refuses to actually set the new value.

(defn eg []
  ((set! *print-err-fn* *print-fn*) 
   (str *print-err-fn*)))
; => #'cljs.user/eg
(eg)
; => function PLANCK_PRINT_ERR_FN() {
; =>     [native code]
; => }

pyrmont06:02:59

Whoops. That's not true. Ignore the above.

pyrmont09:02:20

Hmmm... following further investigation, I think there's a limitation in REPLs with respect to errors. I can rebind *print-err-fn* to a different function but I can't avoid errors being printed out to the console. However, this isn't purely a Planck thing. I've tried something similar with clj -m cljs.main --repl-env node and the result is the same. Presumably there's something about the way errors are handled by the REPL code that won't allow errors to be redirected.