unrepl

discussing specification of an edn-based repl and its implementations.
pesterhazy 2017-06-15T09:11:25.974970Z

hola @volrath

volrath 2017-06-15T09:11:54.981441Z

hallo @pesterhazy !

cgrand 2017-06-15T09:28:44.210397Z

@richiardiandrea hmm find-ns happens to trigger an interesting shadowing bug, opened https://dev.clojure.org/jira/browse/CLJS-2088

cgrand 2017-06-15T10:10:41.776191Z

Identifying a repl:

(cond
  (find-ns '<http://clojure.java.io|clojure.java.io>) :clj
  (find-ns '<http://clojure.clr.io|clojure.clr.io>) :cljr
  (find-ns 'lumo.repl$macros) :lumo
  (find-ns 'planck.repl$macros) :planck
  (find-ns 'cljs.core$macros) :cljs-js
  (find-ns 'cljs.core) :cljs-jvm
  :else :unknown)

thheller 2017-06-15T11:13:26.502365Z

@cgrand find-ns is bootstrap only

cgrand 2017-06-15T11:14:27.513063Z

for repl sniffing it works enough in non-bootstrap

thheller 2017-06-15T11:14:27.513085Z

says so in the docs at least

cgrand 2017-06-15T11:15:14.521897Z

don’t use that in a lib though (advanced compilation...)

thheller 2017-06-15T11:15:56.529521Z

hmm you are right, actually works in normal as well

thheller 2017-06-15T11:19:11.564108Z

but sending that before every interaction would suck

pesterhazy 2017-06-15T11:42:25.819477Z

why not once per connection?

thheller 2017-06-15T13:02:08.868266Z

rlwrap nc localhost 8201
shadow-cljs - REPL - see (help), :repl/quit to exit
[13:0]~shadow.user=&gt; (shadow/node-repl)
[13:1]~cljs.user=&gt; :repl/quit
:repl/quit
[13:0]~shadow.user=&gt;

thheller 2017-06-15T13:02:28.873993Z

@pesterhazy starts out as CLJ, then becomes CLJS, then CLJ again

cgrand 2017-06-15T13:05:03.917496Z

if only there was a protocol which clearly tells when an upgrade occurs 😇

thheller 2017-06-15T13:05:19.922275Z

I know right? 🙂

thheller 2017-06-15T13:06:19.939451Z

any ideas how to do the upgrade process properly for cljs yet?

thheller 2017-06-15T13:06:30.942329Z

not self-hosted that is

thheller 2017-06-15T13:09:08.985145Z

still not totally on-board with unrepl yet but thats mostly due to tool support

thheller 2017-06-15T13:09:27.990698Z

guess I can’t get around nrepl for now

cgrand 2017-06-15T13:14:48.083595Z

Some ideas start to click together. The current cljs repl infrastructure is not ok but it can be remixed (that is: reuse environments and so on but recreate an upgradable infrastructure to replace https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/repl.cljc)

thheller 2017-06-15T13:16:12.108653Z

shadow-cljs doesn’t use any of that, maybe its simpler to integrate there

thheller 2017-06-15T13:16:29.113798Z

is there an unrepl client I could test this with?

cgrand 2017-06-15T13:17:12.126278Z

I dunno, ask @pesterhazy or @richiardiandrea

cgrand 2017-06-15T13:19:30.166920Z

my current idea is to consider the loop on the js-side as its own repl

cgrand 2017-06-15T13:20:21.182171Z

it starts as a framed JS repl but is upgradable

thheller 2017-06-15T13:21:30.203410Z

this is the loop for the CLJS REPL at the moment

thheller 2017-06-15T13:21:57.211700Z

it reads off *in* and prints to *out*

thheller 2017-06-15T13:22:03.213192Z

the actual JS eval is RPC

pesterhazy 2017-06-15T13:22:13.216294Z

@thheller I'd test with netcat first

thheller 2017-06-15T13:22:28.220893Z

so it should be really simple to add the upgrade

pesterhazy 2017-06-15T13:22:28.220972Z

once you have a working protocol, you can try unravel

pesterhazy 2017-06-15T13:23:30.239340Z

this is where the blob is concatenated at the moment: https://github.com/pesterhazy/unravel/blob/b687edb188aaab58b9ac0ce7a143172dc3e256a6/src/unravel/loop.cljs#L115

pesterhazy 2017-06-15T13:23:46.243926Z

it's not updated yet to use the "official" unrepl blob

cgrand 2017-06-15T13:24:09.250535Z

and the blob is only for clj

cgrand 2017-06-15T13:24:19.253794Z

bootstrap soon

pesterhazy 2017-06-15T13:24:19.253809Z

of course the blob would have to be completely replaced

thheller 2017-06-15T13:24:24.255199Z

yeah still not sold on the blob idea

thheller 2017-06-15T13:24:47.262205Z

I’m fine with just having a dependency in the server

cgrand 2017-06-15T13:25:16.271229Z

@thheller how do you handle the print part in shadow repl?

thheller 2017-06-15T13:25:42.279064Z

the client decides how to print

thheller 2017-06-15T13:26:46.298836Z

currently it just does pr-str but I could make that configurable

thheller 2017-06-15T13:27:03.304097Z

it does not send a wrapped form over the wire

thheller 2017-06-15T13:27:25.311121Z

so if you eval (js/alert "foo") the client actually just evals alert("foo") nothing else

👌 2
thheller 2017-06-15T13:28:21.328582Z

not the wrapped stuff the normal CLJS REPL sends

pesterhazy 2017-06-15T13:28:39.334318Z

@cgrand, I did a presentation on unrepl/unravel here in Berlin yesterday. Here are the slides: http://pesterhazy.karmafish.net/unravel-your-repl.pdf

cgrand 2017-06-15T13:29:16.346189Z

How was it received?

pesterhazy 2017-06-15T13:30:13.365073Z

pretty well. I had a few people express interest in contributing after the talk, which is awesome

volrath 2017-06-15T13:31:03.382052Z

^ yes, pretty well 🙂

cgrand 2017-06-15T13:33:27.428690Z

great! welcome @volrath

cgrand 2017-06-15T13:36:15.482038Z

> Rich capabilities, frugal dependencies I like this wording!

cgrand 2017-06-15T13:37:09.499714Z

bonus points for using “transclusion”

thheller 2017-06-15T13:37:17.502256Z

heheh

thheller 2017-06-15T13:37:25.505241Z

[15:1]~cljs.user=&gt; [1 2 3]
(] 3   2   1 [)
[15:1]~cljs.user=&gt; (set! shadow.cljs.devtools.client.env/repl-print-fn #(reverse (pr-str %))
)
(] " }
 ; ) ) _ P R A H S _ 5 2 6 5 4 _ _ 1 p , l l u n ( l l a c . r t s _ r p . e r o c . s j l c , l l u n ( l l a c . e s r e v e r . e r o c . s j l c   n r u t e r
 { ) _ P R A H S _ 5 2 6 5 4 _ _ 1 p (   n o i t c n u f "   n o i t c n u F [ t c e j b o #)
[15:1]~cljs.user=&gt; [1 2 3]
(] 3   2   1 [)

thheller 2017-06-15T13:37:35.508290Z

not the result I had in mind but fun 😛

pesterhazy 2017-06-15T13:37:57.515592Z

@cgrand, yup, I've learned a new word 🙂

thheller 2017-06-15T13:38:26.525034Z

[15:1]~cljs.user=&gt; (set! shadow.cljs.devtools.client.env/repl-print-fn #(clojure.string/upper-case (pr-str %)))
#OBJECT[FUNCTION "FUNCTION (P1__45626_SHARP_){
RETURN CLOJURE.STRING.UPPER_CASE.CALL(NULL,CLJS.CORE.PR_STR.CALL(NULL,P1__45626_SHARP_));
}"]
[15:1]~cljs.user=&gt; [:hello :world]
[:HELLO :WORLD]

volrath 2017-06-15T13:39:15.541570Z

cgrand: thanks! I really like the whole idea. I told @pesterhazy yesterday that I went through the documentation two nights ago, to prepare for the talk, and I think I can contribute a very small PR with some minor fixes to the README (commas, and a couple typos) and then maybe I can help with documenting more stuff (missing tags like :started-eval, and so on)

volrath 2017-06-15T13:39:29.546105Z

that would help with my understanding of the protocol as well

volrath 2017-06-15T13:39:32.547164Z

if that's ok with you

cgrand 2017-06-15T13:40:04.557836Z

that’s more than totally ok

thheller 2017-06-15T13:40:49.573391Z

is there a CLJS impl for the unrepl print style yet?

cgrand 2017-06-15T13:41:45.591849Z

Don’t hesitate pinging me (in private or on the channel)

volrath 2017-06-15T13:42:36.608529Z

thank you! will do

cgrand 2017-06-15T13:43:04.617965Z

yes there is, @plexus made one https://github.com/plexus/unrepl/blob/lumo_support/src/unrepl/print.cljc

cgrand 2017-06-15T13:43:30.626631Z

I plan to merge it when I got time

thheller 2017-06-15T13:45:12.661638Z

hmm

thheller 2017-06-15T13:45:14.662220Z

[15:1]~cljs.user=&gt; (load-file "/Users/zilence/code/shadow-cljs/src/dev/unrepl/print.cljc")
[:result {:type :repl/error, :message "cond-splice not in list", :data {:type :reader-exception, :line 15, :column 5, :file "unrepl/print.cljc"}, :causes []}]

cgrand 2017-06-15T13:47:02.699175Z

indeed, remove the @

cgrand 2017-06-15T13:47:20.705546Z

and add a do

thheller 2017-06-15T13:47:54.717485Z

another one at 170

thheller 2017-06-15T13:48:25.727789Z

ok got it

cgrand 2017-06-15T13:50:39.774974Z

reader discrpencies: LispReader is ok with that, tools.reader not

cgrand 2017-06-16T08:23:03.176043Z

I guess @plexus tested it against cljs-js-repl on lumo

plexus 2017-06-16T08:27:03.226921Z

print.cljc is completely untested. I got as far as making sure the forms evaluated without errors on Lumo. That's it. It almost certainly is incomplete, it's just a first pass addressing the most obvious differences.

cgrand 2017-06-15T13:52:08.806618Z

async-reader should be fine too

thheller 2017-06-15T13:54:08.848612Z

hmm heeh

cgrand 2017-06-15T13:54:17.851999Z

tools.reader issue?

thheller 2017-06-15T13:54:19.852915Z

it cannot print itself

thheller 2017-06-15T13:54:22.853676Z

[18:0]~shadow.user=&gt; (shadow/dev :browser)
[18:1]~cljs.user=&gt; (require 'unrepl.print)
[18:1]~cljs.user=&gt; (set! shadow.cljs.devtools.client.env/repl-print-fn unrepl.print/edn-str)
nil
[18:1]~cljs.user=&gt; {:foo "bar"}
{:foo "bar"}

thheller 2017-06-15T13:54:37.859217Z

TypeError: Cannot read property 'cljs$core$IFn$_invoke$arity$1' of undefined
    at cljs.core.MultiFn.cljs$core$IFn$_invoke$arity$1 (cljs.core.cljs:10295)
    at Function.unrepl.print.ednize.cljs$core$IFn$_invoke$arity$3 (eval at shadow$cljs$devtools$client$browser$do_js_load (shadow.cljs.devtools.client.browser.cljs:48), &lt;anonymous&gt;:457:119)
    at Function.unrepl.print.ednize.cljs$core$IFn$_invoke$arity$2 (eval at shadow$cljs$devtools$client$browser$do_js_load (shadow.cljs.devtools.client.browser.cljs:48), &lt;anonymous&gt;:425:28)
    at Object.unrepl$print$print_on [as print_on] (eval at shadow$cljs$devtools$client$browser$do_js_load (shadow.cljs.devtools.client.browser.cljs:48), &lt;anonymous&gt;:610:33)

thheller 2017-06-15T13:55:43.883839Z

doesn’t seem to work really

cgrand 2017-06-15T13:55:44.884122Z

I haven’t had time to test it, I was doing some preliminary work on the upgradable cljs repl

thheller 2017-06-15T13:56:01.890048Z

(range 0 10000) also fails

thheller 2017-06-15T13:56:30.901091Z

TypeError: Cannot read property 'cljs$core$IFn$_invoke$arity$1' of undefined
    at cljs.core.MultiFn.cljs$core$IFn$_invoke$arity$1 (cljs.core.cljs:10295)
    at Function.unrepl.print.ednize.cljs$core$IFn$_invoke$arity$3 (eval at shadow$cljs$devtools$client$browser$do_js_load (shadow.cljs.devtools.client.browser.cljs:48), &lt;anonymous&gt;:457:119)
    at Function.unrepl.print.ednize.cljs$core$IFn$_invoke$arity$2 (eval at shadow$cljs$devtools$client$browser$do_js_load (shadow.cljs.devtools.client.browser.cljs:48), &lt;anonymous&gt;:425:28)
    at unrepl$print$print_on (eval at shadow$cljs$devtools$client$browser$do_js_load (shadow.cljs.devtools.client.browser.cljs:48), &lt;anonymous&gt;:610:33)
    at Function.unrepl.print.print_vs.cljs$core$IFn$_invoke$arity$5 (eval at shadow$cljs$devtools$client$browser$do_js_load (shadow.cljs.devtools.client.browser.cljs:48), &lt;anonymous&gt;:571:113)
    at Function.unrepl.print.print_vs.cljs$core$IFn$_invoke$arity$3 (eval at shadow$cljs$devtools$client$browser$do_js_load (shadow.cljs.devtools.client.browser.cljs:48), &lt;anonymous&gt;:516:30)
    at Object.unrepl$print$print_on [as print_on] (eval at shadow$cljs$devtools$client$browser$do_js_load (shadow.cljs.devtools.client.browser.cljs:48), &lt;anonymous&gt;:653:23)
    at unrepl$print$edn_str (eval at shadow$cljs$devtools$client$browser$do_js_load (shadow.cljs.devtools.client.browser.cljs:48), &lt;anonymous&gt;:698:18)

thheller 2017-06-15T13:56:37.903721Z

damn js stack traces are ugly

thheller 2017-06-15T13:57:10.915745Z

ah wait I have a debugger for that 😉

cgrand 2017-06-15T13:57:17.918469Z

i may have an idea, in the clojure version you need to set some dynvars around it

cgrand 2017-06-15T13:57:36.925484Z

(keep calm it’s synchronous so plain binding is ok)

cgrand 2017-06-15T13:58:03.935053Z

it would explain the undefined

thheller 2017-06-15T13:58:47.952086Z

*ednize* seems unbound

cgrand 2017-06-15T14:00:25.991356Z

(defmulti default-ednize-fn class) <- no class in cljs

thheller 2017-06-15T14:01:14.011322Z

why isn’t that a protocol?

cgrand 2017-06-15T14:05:40.111682Z

trying to remember — I dislike multimethods so there must be a reason

thheller 2017-06-15T14:06:45.135149Z

Error: No method in multimethod 'unrepl.print/default-ednize-fn' for dispatch value: function Function() { [native code] }

thheller 2017-06-15T14:06:58.139962Z

just changed it to type

thheller 2017-06-15T14:07:16.146563Z

uhm (try try try try try try try try try try #unrepl/... nil) 😛

thheller 2017-06-15T14:07:20.147970Z

almost?

thheller 2017-06-15T14:07:40.155341Z

[20:1]~cljs.user=&gt; (range 0 1000)
(try try try try try try try try try try #unrepl/... nil)

cgrand 2017-06-15T14:07:48.157973Z

🙂

thheller 2017-06-15T14:08:03.163250Z

where does the try come from? 😛

cgrand 2017-06-15T14:08:43.178498Z

re: protocol, really I don’t see why anymore, maybe to have the opportunity to prefer impls in case of conflicts?

cgrand 2017-06-15T14:09:56.204797Z

there are only two “try” one in the expansion of a macro, I think it’s the one

thheller 2017-06-15T14:10:46.223895Z

ok .. I gotta do some other stuff .. will try again later

cgrand 2017-06-15T14:11:41.244406Z

on line 234 blame-seq which is a macro is called like a function (because cljs) and then its head (`try`) is used for v

thheller 2017-06-15T14:13:13.278016Z

[20:1]~cljs.user=&gt; (range 0 1000)
(0 1 2 3 4 5 6 7 8 9 #unrepl/... nil

thheller 2017-06-15T14:13:14.278828Z

indeed

thheller 2017-06-15T14:13:35.286272Z

#?(:cljs (:require-macros [unrepl.print :refer (blame-seq)])) in ns

thheller 2017-06-15T14:13:46.290205Z

#?(:clj
   (defmacro ^:private blame-seq [&amp; body]
     `(try (seq ~@body)
           (catch Throwable t#
             (list (tagged-literal 'unrepl/lazy-error t#))))))

cgrand 2017-06-15T14:14:35.308365Z

oh noes, you just broke it for self-hosted

thheller 2017-06-15T14:14:49.313661Z

hihi

cgrand 2017-06-15T14:18:29.399624Z

macrovich to the rescue!

cgrand 2017-06-15T14:40:24.912573Z

heh?

cgrand 2017-06-15T14:40:51.923328Z

(btw David applied my patch)

cgrand 2017-06-15T14:42:54.971617Z

“was wondering why $macros should it find either way” ?

richiardiandrea 2017-06-15T14:44:15.002735Z

cgrand: lol let me rephrase

richiardiandrea 2017-06-15T14:45:29.031998Z

Why did you switch to detecting core$macros instead of core

cgrand 2017-06-15T14:47:02.070009Z

because in self-hosted cljs, (find-ns 'lumo.repl) cripples access to this ns macros (open lumo, enter this find-ns and after that try to use doc)

richiardiandrea 2017-06-15T14:48:18.099968Z

Oh gotcha temporary fix before your patch is officially in

cgrand 2017-06-15T14:49:31.129138Z

and until non-patched cljs are rare enough

richiardiandrea 2017-06-15T14:50:49.160832Z

@thheller I think @plexus was writing an Emacs mode