unrepl

discussing specification of an edn-based repl and its implementations.
dominicm 2017-12-22T09:50:00.000057Z

@pesterhazy how much time should unravel spend loading compliment?

dominicm 2017-12-22T09:52:14.000189Z

I'm seeing either > 1 minute, or never (I've given up)

cgrand 2017-12-22T09:52:55.000113Z

@dominicm in a fully local setup?

dominicm 2017-12-22T09:53:11.000275Z

@cgrand What does "fully local" mean in this context?

cgrand 2017-12-22T09:53:24.000012Z

server & client on the same machine

dominicm 2017-12-22T09:53:27.000271Z

Yes.

dominicm 2017-12-22T09:56:22.000040Z

I'm now at 3 minutes.

dominicm 2017-12-22T09:59:27.000227Z

[:receive {:origin :aux} [:started-eval {:actions {:interrupt (unrepl.replG__156/interrupt! :session654 6), :background (unrepl.replG__156/background! :session654 6)}} 6]]
[:unknown-command [:started-eval {:actions {:interrupt (unrepl.replG__156/interrupt! :session654 6), :background (unrepl.replG__156/background! :session654 6)}} 6]]
[:receive {:origin :aux} [:exception {:ex #error {:cause "compliment.core", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.ClassNotFoundException: compliment.core, compiling:(unrepl-session:6:63)", :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 7010]} {:type java.lang.ClassNotFoundException, :message "compliment.core", :at [java.net.URLClassLoader findClass "URLClassLoader.java" 381]}], :trace [[java.net.URLClassLoader findClass "URLClassLoader.java" 381] [clojure.lang.DynamicClassLoader findClass "DynamicClassLoader.java" 69] [java.lang.ClassLoader loadClass "ClassLoader.java" 424] [clojure.lang.DynamicClassLoader loadClass "DynamicClassLoader.java" 77] [java.lang.ClassLoader loadClass "ClassLoader.java" 357] [java.lang.Class forName0 "Class.java" -2] [java.lang.Class forName "Class.java" 348] [clojure.lang.RT classForName "RT.java" 2204] [clojure.lang.RT classForNameNonLoading "RT.java" 2217] [clojure.lang.Compiler$HostExpr maybeClass "Compiler.java" 1041] #__1]}, :phase :eval} 6]]
[:unknown-command [:exception {:ex #error {:cause "compliment.core", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.ClassNotFoundException: compliment.core, compiling:(unrepl-session:6:63)", :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 7010]} {:type java.lang.ClassNotFoundException, :message "compliment.core", :at [java.net.URLClassLoader findClass "URLClassLoader.java" 381]}], :trace [[java.net.URLClassLoader findClass "URLClassLoader.java" 381] [clojure.lang.DynamicClassLoader findClass "DynamicClassLoader.java" 69] [java.lang.ClassLoader loadClass "ClassLoader.java" 424] [clojure.lang.DynamicClassLoader loadClass "DynamicClassLoader.java" 77] [java.lang.ClassLoader loadClass "ClassLoader.java" 357] [java.lang.Class forName0 "Class.java" -2] [java.lang.Class forName "Class.java" 348] [clojure.lang.RT classForName "RT.java" 2204] [clojure.lang.RT classForNameNonLoading "RT.java" 2217] [clojure.lang.Compiler$HostExpr maybeClass "Compiler.java" 1041] #__2]}, :phase :eval} 6]]
[:receive {:origin :aux} [:prompt {:file "unrepl-session", :line 7, :column 1, :offset 1082, clojure.core/*warn-on-reflection* false, clojure.core/*ns* #unrepl/ns user}]]
[:unknown-command [:prompt {:file "unrepl-session", :line 7, :column 1, :offset 1082, clojure.core/*warn-on-reflection* false, clojure.core/*ns* #unrepl/ns user}]]
Looks like I need to depend on compliment myself, I expected unravel to be hotloading it.

dominicm 2017-12-22T10:02:24.000380Z

Oh, actually, it might be more malignant than only that. I've added compliment as a dependency, and unless I do (require 'compliment.core) first, the completion hangs.

cgrand 2017-12-22T10:09:40.000057Z

Hi tried it and I think that unravel doesn’t require compliment.core and hasn’t it on the sideloader path

dominicm 2017-12-22T10:12:45.000046Z

@cgrand A bit of an aside, but how do you feel about vendoring depndencies in this context? Should unravel be using unravel.compliment.core, so that compliment 0.3.4 can be used by unravel, and 1.0.0 can be used by clientC?

dominicm 2017-12-22T10:14:35.000349Z

Or, perhaps more importantly, so that oldProjectA can use 0.0.1, and unravel can use 0.3.4.

cgrand 2017-12-22T10:15:31.000271Z

Yes because this last scenario breaks even in a richhickeyic world.

dominicm 2017-12-22T10:17:45.000247Z

The other option, and I'm not sure if you've thought about this, is to use clj-embed: https://github.com/RutledgePaulV/clj-embed which is an independent form of boot's pods. For something like compliment this might not make sense as it's inspecting the classpath & running state. But for other tooling needs (perhaps bundling zprint) it would be a good idea perhaps. I mention this library because I wonder if this is a problem unrepl may want to solve in this way.

dominicm 2017-12-22T10:18:27.000365Z

Maybe it should actually be further vendored than just unravel.compliment.core, but instead unravelv0_2_2.compliment.core to allow parallel clients of unravelv0_2_1 also.

dominicm 2017-12-22T10:19:05.000268Z

I also question whether it should be scoped to the client's connection altogether, with the vendoring provided by unrepl.

cgrand 2017-12-22T10:37:03.000156Z

@dominicm I thought about classloader isolation and even did a quick prototype in the early days of unrepl

cgrand 2017-12-22T10:37:44.000207Z

Like you mention, classloader isolation is strong, too strong.

cgrand 2017-12-22T10:39:55.000020Z

The “best” option if you set up a second clojure, is to have it communicate in text-based form with the user clojure.

cgrand 2017-12-22T10:40:40.000083Z

Basically you may treat it as a low-latency unrepl client.

cgrand 2017-12-22T10:42:31.000174Z

Not sure it’s a good idea.

cgrand 2017-12-22T10:43:36.000189Z

Classloader isolation has really the problem of being too strong for our purpose — and it doesn’t work in cljs (starting a second JS env in Node?)

dominicm 2017-12-22T11:02:54.000196Z

So, vendoring it is. We shall all become professional users of Mr. Anderson!

cgrand 2017-12-22T11:17:44.000203Z

With @richiardiandrea we discussed a subtler and better vendoring

dominicm 2017-12-22T11:18:57.000187Z

What was the approach considered?

cgrand 2017-12-22T11:30:25.000346Z

vendor compliment.core as vnd.sha1_XXXXX.compliment.core

dominicm 2017-12-22T11:36:20.000098Z

ah, so it works globally for namespaces which are the same, makes sense.

cgrand 2017-12-22T11:39:44.000327Z

;; assuming that (do-vendor vendorable vendored) substitutes all refs to vendored nses in the source of vendorable
;; then computes its hash, then puts the hash in ns in the source and returns the vendor-hashed ns name.

(let [deps-graph XXX]
  (loop [vendored {}]
    (if-some [vendorables (seq (filter (fn [dep] (every? #(or (white-list? %) (vendored %))  (:deps dep)))))]
      (recur (into vendored
               (map (fn [vendorable]
                      [(:name vendorable) (do-vendor vendorable vendored)]))
               vendorables))
      vendored)))

dominicm 2017-12-22T11:43:35.000167Z

I wonder if JarJar can do something similar

dominicm 2017-12-22T11:47:21.000307Z

(https://code.google.com/archive/p/jarjar/)

cgrand 2017-12-22T11:49:18.000120Z

can do or could do?

dominicm 2017-12-22T11:51:42.000019Z

I suppose either.

cgrand 2017-12-22T11:54:23.000285Z

Someone willing to implement that? 😉

cgrand 2017-12-22T11:54:36.000310Z

It would make a great xmas present to the community...

dominicm 2017-12-22T11:55:08.000356Z

A tool to vendor dependencies you mean?

bozhidar 2017-12-22T11:57:12.000030Z

All of this seems to be pretty much what Mr. Anderson does.

cgrand 2017-12-22T11:57:15.000174Z

yup, maybe a patch to mranderson

dominicm 2017-12-22T11:57:35.000086Z

@bozhidar the hashing rather than a specified prefix is the distinction I think.

bozhidar 2017-12-22T11:57:37.000131Z

Vendoring deps was one of the most painful things when building CIDER - something some basic should be easier to do.

bozhidar 2017-12-22T11:57:51.000166Z

Yeah, I get the point, but fundamentally it’s the same process.

bozhidar 2017-12-22T11:58:06.000212Z

Patching Mr. Anderson to support this would be trivial.

cgrand 2017-12-22T12:04:40.000053Z

Just looked at it and it’s not that trivial because of deps ordering, which matters for hashing

cgrand 2017-12-22T12:05:40.000062Z

if libA depends on libB, when hash-vendoring, you can’t independently hash them

dominicm 2017-12-22T12:08:42.000152Z

@cgrand I was about to ask about that for hashing.

dominicm 2017-12-22T12:09:17.000217Z

I guess a version-tied prefix is the simplest way.

cgrand 2017-12-22T12:13:33.000232Z

if libC uses libA v1 and libB v1.1 if libD uses libA v1 and libB v1.2 then we should get two different libAs

New To Clojure 2017-12-22T15:08:14.000113Z

$ unravel --version
Unravel 0.2.2 (Lumo 1.7.0)

$ lein --version
Leiningen 2.8.1 on Java 1.8.0_151 Java HotSpot(TM) 64-Bit Server VM

JVM_OPTS='-Dclojure.server.myrepl={:port,50505,:accept,clojure.core.server/repl}' lein repl

unravel localhost 50505
unravel fails with stacktrace:
$ unravel localhost 50505evalmachine.<anonymous>:22var reader = cljs.reader.push_back_reader.call(null,s); ^TypeError: Cannot read property 'call' of undefined at unravel$lisp$safe_read_string (evalmachine.<anonymous>:22:42) at Transform._transform (evalmachine.<anonymous>:56:60) at Transform._read (_stream_transform.js:186:10) at Transform._write (_stream_transform.js:174:12) at doWrite (_stream_writable.js:385:12) at writeOrBuffer (_stream_writable.js:371:5) at Transform.Writable.write (_stream_writable.js:288:11) at Transform.ondata (_stream_readable.js:642:20) at emitOne (events.js:115:13) at Transform.emit (events.js:210:7)
Any ideas what could be wrong?

New To Clojure 2017-12-22T15:08:30.000062Z

$ lumo --version
1.7.0

cgrand 2017-12-22T15:40:40.000252Z

@ghsgd2 built from Git or brew?

New To Clojure 2017-12-22T15:42:49.000018Z

@cgrand brew install bfontaine/utils/unravel

pesterhazy 2017-12-22T16:17:29.000502Z

@ghsgd2 you'll need to use latest master unfortunately because the version on brew is not compatible with lumo 1.7.0+

pesterhazy 2017-12-22T16:18:00.000251Z

@dominicm, did you solve the compliment issue?

pesterhazy 2017-12-22T16:19:34.000125Z

compliment is only used when you pass --flag compliment

dominicm 2017-12-22T16:19:51.000076Z

@pesterhazy There's a bug or 2 there, I found a workaround. Bug 1) compliment.core is used without requiring it first (makes compliment pretty much unusable without knowing to require it first, causes total lockup) Bug 2) unravel doesn't bundle a copy of compliment / it doesn't vendor compliment in order to prevent conflicts with the project.

pesterhazy 2017-12-22T16:19:52.000369Z

and that requires compliment to be on the class path

pesterhazy 2017-12-22T16:20:13.000109Z

yup both are true (oops!)

pesterhazy 2017-12-22T16:20:35.000286Z

could you file an issue?

dominicm 2017-12-22T16:21:44.000228Z

Doing for both now, there's a possible 3rd "nice to have" here, handling exceptions that happen during tab completion. (and other aux exceptions)

pesterhazy 2017-12-22T16:22:54.000293Z

yeah it's a good point. I wonder how we should catch those exceptions

New To Clojure 2017-12-22T16:24:17.000106Z

@pesterhazy Got it. However, official installation docs say that brew could be used to install unrepl on macOS. And lumo was installed by brew unrepl formulae as a dependency. Looks like brew formulae is broken and needs fixing.

pesterhazy 2017-12-22T16:26:53.000393Z

@ghsgd2 that's correct

pesterhazy 2017-12-22T16:27:27.000034Z

we want to release a new version that fixes that, and brings all the new feature in master as well

pesterhazy 2017-12-22T16:27:34.000130Z

haven't found the time lately

dominicm 2017-12-22T16:28:41.000115Z

@pesterhazy Same way you do for other exceptions? 😄 Displaying them is a little more troubling. Did the code for split screen ever go in? That would be a great place to dump it OR display a message saying "An unexpected exception has occurred, a log has been written to /tmp/unravel_xxx.log" which shows perhaps in the same place documentation would normally show?

pesterhazy 2017-12-22T16:29:24.000097Z

the split screen only works for developers (using scripts/debug)

pesterhazy 2017-12-22T16:29:37.000177Z

good idea about the log file

pesterhazy 2017-12-22T16:30:05.000323Z

the key is to continue with regular operation after the exception occurs, rather than blocking forever

dominicm 2017-12-22T16:30:46.000320Z

Yeah, that's super important. Medium level of importance is allowing you to fix bugs which bother people.

dominicm 2017-12-22T16:31:01.000366Z

(On this scale anyway)

New To Clojure 2017-12-22T16:32:02.000339Z

@pesterhazy No worries, created the issue as a reminder.

pesterhazy 2017-12-22T16:32:14.000016Z

thanks!

volrath 2017-12-22T16:45:29.000352Z

I'm actually working on this related problem in unrepl.el right now: figuring out the best way to present aux conn exceptions to users... I'm using a popup temp buffer, but would love to hear if you come up with a different UI

gcast 2017-12-22T17:11:24.000102Z

Question, If I wanted to communicate from the browser to a plain socket repl running the unrepl blob, would web sockets be the most appropriate strategy?

gcast 2017-12-22T17:13:01.000537Z

I imagine standing up some sort of web socket server to communicate with the client

cgrand 2017-12-22T18:09:19.000065Z

An error log?

dominicm 2017-12-22T19:22:03.000084Z

With parfix, is there a way to send the current line without hitting "End"? My brain went to Ctrl-Enter

cgrand 2017-12-22T19:26:03.000251Z

@gcast why not? The sad part is having to have an intermediate server.

gcast 2017-12-22T19:28:02.000154Z

Ok good. I've started down that road. I spent some time trying to see if it was possible to have a direct stream to unrepl, but my research and current understanding suggests browser security may make other approaches problematic

cgrand 2017-12-22T19:32:36.000308Z

@dominicm I wanted it to but apparently you can’t get CTRL ENTER in a term app. I don’t remember what got merged. Did you try ^J?

cgrand 2017-12-22T19:33:53.000257Z

I’m unhappy with the current behavior and @pesterhazy and I have differing opinion of what a good behavior should be.

cgrand 2017-12-22T19:34:43.000438Z

@gcast you want a real browser not a web view in a native app?

gcast 2017-12-22T19:35:49.000180Z

well I suppose if the underlying repl can live on a remote server than a native app is just fine as well

cgrand 2017-12-22T19:36:01.000280Z

I believe that sending a http request to a repl would almost work… if you found a way to not have the browser barf on the garbage.

gcast 2017-12-22T19:36:04.000179Z

the key is that the compute can happen on an arbitrary networked machine

gcast 2017-12-22T19:38:05.000225Z

hmmm, garbage-handling aside, would http-requests be slower for repl communication?

dominicm 2017-12-22T19:38:06.000300Z

@cgrand At least in my terminal, Ctrl-J didn't work

pesterhazy 2017-12-22T19:39:35.000179Z

It’s not merged yet- you can try the branch though

pesterhazy 2017-12-22T19:39:50.000275Z

It’s a PR

dominicm 2017-12-22T19:41:06.000176Z

Ah, I thought I was cutting edge using master as it is 😄

cgrand 2017-12-22T20:17:00.000287Z

The first protoclient for unrepl was electron-based

gcast 2017-12-22T21:21:53.000122Z

really? I'd never heard of electron before but just did some research and it looks pretty nice

gcast 2017-12-22T21:26:30.000126Z

how mature is the CLJS environment for electron?

cgrand 2017-12-22T21:37:18.000240Z

I don’t remember what I used. I could look it up.

cgrand 2017-12-22T21:44:17.000124Z

It worked ok. Too much reloading. I wasn’t familiar with node enough. Otherwise I would have made it expose a socket repl (well two)

gcast 2017-12-22T21:52:05.000184Z

I see. this looks quite promising because there is already an electron-based notebook-app for arbitrary jupyter-kernels https://github.com/nteract/nteract

gcast 2017-12-22T21:52:28.000271Z

Would simplify the problem to just writing a native clojure backend that support unrepl.