@dominicm that is a very interesting question and I am not a lawyer but it seems like we are not reditributing/copying things but taking and running the files only
@dominicm do you mean we should bundle the license with the blob?
@pesterhazy potentially yesyes. This is what JavaScript minifiers do (see most cljs advanced builds contain the react license)
I think that would make sense
I am thinking of repackaging https://github.com/Lambda-X/boot-pack-source, maybe a rename to boot-sources
makes sense but naming is hard
suggestions? 😄
the lib contains a couple of packages for moving (source) files within the fileset
like pack-source
takes deps and moves the sources files to a custom folder
and this will include an unrepl-blob
task for making the blob like so boot pack-source unrepl-blob
what would be the advantages over what @cgrand has already built?
I like the names: uglifyclj, replpack and replify, named after their js counterparts 😛
@pesterhazy how do you mean? did you see the snipped above? I am basically blobifying/concatenating arbitrary deps
@richiardiandrea so this is for building a blob that includes, e.g. compliment?
yep
sorry I'm being a bit slow today
no no problem, I thought I was missing some point 😉
have you tried sending it to the repl?
e.g. using netcat
not yet, today's goal
(cat unrepl-blob.clj compliment-blob.clj - ) | java -jar clojure.jar -m clojure.main)
uhm first attempt is weird:
cat target/unrepl/blob.clj | java -cp "$CLOJURE_EXT" clojure.main
Clojure 1.8.0
user=> #'compliment.core/documentation
user=>
$ ...exited to shell...
it is evaluated correctly though, because the printed var is the last var of compliment.core
Oh I need the -
wow...bash magic
$ cat target/unrepl/blob.clj - | java -Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}" -cp "$CLOJURE_EXT" clojure.main
Clojure 1.8.0
user=> #'compliment.core/documentation
user=> (compliment.core/completions "def")
({:candidate "def", :type :special-form} {:candidate "defn", :type :macro, :ns "clojure.core"} {:candidate "defn-", :type :macro, :ns "clojure.core"} {:candidate "defonce", :type :macro, :ns "clojure.core"} {:candidate "deftype", :type :macro, :ns "clojure.core"} {:candidate "defmacro", :type :macro, :ns "clojure.core"} {:candidate "defmulti", :type :macro, :ns "clojure.core"} {:candidate "definline", :type :macro, :ns "clojure.core"} {:candidate "defmethod", :type :macro, :ns "clojure.core"} {:candidate "defrecord", :type :macro, :ns "clojure.core"} {:candidate "defstruct", :type :macro, :ns "clojure.core"} {:candidate "defprotocol", :type :macro, :ns "clojure.core"} {:candidate "definterface", :type :macro, :ns "clojure.core"} {:candidate "default-data-readers", :type :var, :ns "clojure.core"})
user=>
this is awesome 😉
Was the decision made to not to ns munging of some kind?
no well this is my own trial and error, no decision has been taken
ah, okay. just checking.
just so you know, beer and champagne doesn't mix well
it should be pretty easy to swap this in in unravel https://github.com/pesterhazy/unravel/blob/master/src/unravel/loop.cljs#L77
to add another blob you could add it here: https://github.com/pesterhazy/unravel/blob/7d4f48c033fe6da2f87d20764d614321e421fd52/src/unravel/loop.cljs#L123
@pesterhazy do you vendor the blob? or you build it programmatically on release
I yes I see it is just vendored
correct, there's also scripts/update-unrepl
oh well, that will come later...I guess at this point what will go in the blob will only depend on the client
the script can change in order to use boot
for building it
uhm I tried and [:connect true]
is the only output I get unfortunately
hmm
could you put up a branch?
sure, on my fork? or you can give me access wink wink nudge nudge 😄
so just to be sure I did:
cat ~/git/unravel/resources/unrepl/blob.clj - | java -Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}" -cp "$CLOJURE_EXT" clojure.main
and it works.looking at it now
how did you create the blob?
could you add the compliment blob as a separate file to the repo, rather than pre-concatenating?
just a sec a bit busy now 😉 basically this is the core of it:
(let [code (->> blob-files (mapv slurp) str/join)]
(butil/trace* "Blob:\n%s\n" (butil/pp-str code))
(io/make-parents output-file)
(butil/dbug "Writing blob to %s...\n" (.getName output-file))
(spit output-file
(prn-str
`(let [prefix# (name (gensym))
code# (.replaceAll ~code "unrepl\\.(?:repl|print)" (str "$0" prefix#))
rdr# (-> code# java.io.StringReader. clojure.lang.LineNumberingPushbackReader.)]
(try
(binding [*ns* *ns*]
(loop [ret# nil]
(let [form# (read rdr# false 'eof#)]
(if (= 'eof# form#)
ret#
(recur (eval form#))))))
(catch Throwable t#
(println "[:unrepl.upgrade/failed]")
(throw t#)))))))
haven't really check the code that was in the blob, so maybe there is something else to do there (for example I see a replaceAll
now
oh well, of course it does not work 🤦
there are no unrepl
specific blobs
./scripts/run localhost 5555
Unravel 0.2.2 connected to localhost:5555
Type ^O for full docs of symbol under cursor, ^D to quit
Enter #__help for help
user=> (compliment.core/completions "def")
({:candidate "def", :type :special-form} {:candidate "defn", :type :macro, :ns "clojure.core"} {:candidate "defn-", :type :macro, :ns "clojure.core"} {:candidate "defonce", :type :macro, :ns "clojure.core"} {:candidate "deftype", :type :macro, :ns "clojure.core"} {:candidate "defmacro", :type :macro, :ns "clojure.core"} {:candidate "defmulti", :type :macro, :ns "clojure.core"} {:candidate "definline", :type :macro, :ns "clojure.core"} {:candidate "defmethod", :type :macro, :ns "clojure.core"} {:candidate "defrecord", :type :macro, :ns "clojure.core"} #__1)
user=> (print
print printf println print-dup print-str print-ctor println-str
print-method print-simple
user=> (print
compliment is super cool, I added the option as comment in the code, neat stuff can be achieved (like complete locals, but the surrounding form needs to be sent)
cmd-complete
could actually accept the same options that we just forward to compliment
@bbrinck has also a very cool library for error parsing that we could make use of in unravel
: https://github.com/bhb/expound
this opens the door to some interesting question, how to send blobs conditionally? Expound makes sense only when clojure.spec
is loaded server side
Side loading requires a dedicated connection (and client code for this connection). This is the price.
I don't understand the dedicated connection requirement.
I think that for solving the particular problem above, the blob that contains expound
for instance, could refuse to eval itself if it does not find its requirements (`(find-ns 'clojure.spec.alpha)` for instance)
Also the number of blob combinations is potentially infinite and we might want to share them (example, the compliment one)...this actually makes the new off topic 🙂tools.deps.alpha
a good candidate for fetching things
or generally pomegranate, no?
@dominicm loading can occur anywhere even in the middle of a read so it can't share the same input stream
@cgrand gotcha, so unravel would be forced to maintain a separate (or multiplexed) connection in order to support this feature (if it wanted to)
@richiardiandrea I'm under the impression we are slightly talking past each other.
This does somewhat open up the desire for a multiplexer again I suppose. I know it was canned for complexity, but just raising the point that it would remove the scary of maintaining a dedicated connection.
@dominicm multiplexing was not canned for complexity but for not being core. It's one way to create multiple connections. So it's rather orthogonal and clients willing to use it should add it to their blobs.
So not necessarily a dedicated connection then
@dominicm it's still a connection (it needs to be handled separately by the client after demux)
in particular I say I so so like unravel
as client but I want to be able to send some additional blob apart from the ones unravel
provides. Maybe unravel
can expose an option for this use case? This way the user controls what to send (in case she is using clojure alpha-1.9.0-alpha17
) to some extent
Uhm or maybe a simple series of load-file
might suffice once the repl is up
ah ! maybe I missed this one, you folks have thought about everything 😄 What is side-loading? Server side, client side? 😄
Side-loading is an idea that has been floating around for quite a while (at some point I even had an implementation). Basically it's a way for the server to request a resource from the client. (In java it hooks up the classloading mechanism)
ok it is that inversion of control we were talking about yes, I just did not know the name then 😉
did those messages send? they're all grey?
Looks like no
What were the objections to the side loading?
https://giphy.com/gifs/nNksEd1ZGdqGk/html5 feels appropriate
About the whole blob thing: maybe we make reasoning and problem solving harder by complecting blob generation and namespaces isolation (gensyms etc.)
For now I am going to publish a task that does the following things: resolves the deps (already part of boot-sources), sorts in dep order the files, concatenates. One step at the time. We can refine things once problems come up.