planck

Planck ClojureScript REPL
pyrmont 2019-02-18T02:35:22.001300Z

Hi all 👋

pyrmont 2019-02-18T02:37:17.003800Z

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?).

mfikes 2019-02-18T02:42:13.005400Z

@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"

pyrmont 2019-02-18T02:50:29.013900Z

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.

pyrmont 2019-02-18T02:54:36.017700Z

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.

mfikes 2019-02-18T02:54:56.018200Z

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

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

mfikes 2019-02-18T02:55:53.018700Z

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

mfikes 2019-02-18T02:56:03.019100Z

Not perfect, but, it works.

pyrmont 2019-02-18T02:56:31.019900Z

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

pyrmont 2019-02-18T02:57:05.020800Z

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

pyrmont 2019-02-18T02:58:00.023Z

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

mfikes 2019-02-18T02:58:01.023100Z

So, you have Planck running on the Pi?

pyrmont 2019-02-18T02:58:05.023300Z

Yeah!

mfikes 2019-02-18T02:58:21.024100Z

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

pyrmont 2019-02-18T02:58:43.024700Z

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

pyrmont 2019-02-18T02:58:51.025Z

I meant to write a reply to that.

pyrmont 2019-02-18T03:00:51.028300Z

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.

mfikes 2019-02-18T03:01:51.030100Z

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

pyrmont 2019-02-18T03:02:02.030400Z

Yeah, I have that too! :)

pyrmont 2019-02-18T03:02:48.032100Z

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).

mfikes 2019-02-18T03:03:05.032900Z

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. 🙂

mfikes 2019-02-18T03:03:55.034200Z

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

pyrmont 2019-02-18T03:03:58.034400Z

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

mfikes 2019-02-18T03:07:01.038100Z

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

pyrmont 2019-02-18T03:07:29.038700Z

I've also tried:

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

pyrmont 2019-02-18T03:07:42.038900Z

That's true.

pyrmont 2019-02-18T03:08:20.040Z

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.

pyrmont 2019-02-18T03:08:36.040600Z

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

mfikes 2019-02-18T03:10:17.041200Z

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

pyrmont 2019-02-18T03:10:29.041300Z

Hmmm, no, that didn't work either.

pyrmont 2019-02-18T03:12:05.042Z

pr-str is helpful for the return value :D

pyrmont 2019-02-18T03:12:24.042600Z

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

mfikes 2019-02-18T03:14:07.043200Z

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

pyrmont 2019-02-18T03:22:26.043500Z

Ooh. Thanks :)

pyrmont 2019-02-18T03:22:38.043900Z

I'll have a look at that!

pyrmont 2019-02-18T03:23:39.044800Z

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

mfikes 2019-02-18T03:23:55.045Z

Glad you are finding value in it 🙂

pyrmont 2019-02-18T06:16:42.047100Z

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]
; => }

pyrmont 2019-02-18T06:18:59.047700Z

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

pyrmont 2019-02-18T09:07:20.051100Z

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.