This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-03-09
Channels
- # beginners (22)
- # boot (80)
- # cider (6)
- # cljs-dev (5)
- # clojure (190)
- # clojure-berlin (5)
- # clojure-dev (24)
- # clojure-italy (14)
- # clojure-russia (70)
- # clojure-spec (39)
- # clojure-uk (82)
- # clojurescript (121)
- # clojurewest (1)
- # core-logic (2)
- # cursive (25)
- # datascript (186)
- # datomic (33)
- # dirac (266)
- # emacs (9)
- # gsoc (4)
- # hoplon (37)
- # immutant (34)
- # instaparse (22)
- # jobs (4)
- # juxt (6)
- # lambdaisland (2)
- # leiningen (1)
- # liberator (1)
- # luminus (5)
- # lumo (28)
- # off-topic (9)
- # om (23)
- # onyx (26)
- # other-lisps (1)
- # parinfer (39)
- # pedestal (45)
- # proton (1)
- # protorepl (10)
- # re-frame (18)
- # reagent (4)
- # ring-swagger (8)
- # rum (4)
- # specter (13)
- # test-check (14)
- # testing (1)
- # unrepl (164)
- # untangled (10)
- # yada (14)
Answers OoO to your questions: 5. No. EDN is a subset of Clojure code and Clojure code can only reprsents is a subset of values (and a value may contain a cycle). Thats’ why I have a handful of tagged literals to fill the gap.
2. yes it’s an abstraction over repl impls (a single lang may have more than one) to keep details about what to eval to do what from crippling in client code.
1. The input being free form means that eval is what you get by default. In my impl the :unrepl/hello
msg advertises the support of :interrupt
, :set-source
and :exit
.
:set-source
is described (in the msg, not in the spec) as sending ^P
followed by (set-set-file-line-col …)
:
[:unrepl/hello
{:commands
{:interrupt <#C4C63FWP5|unrepl>/raw \u0003,
:exit <#C4C63FWP5|unrepl>/raw \u0004,
:set-source <#C4C63FWP5|unrepl>/raw [\u0010
<#C4C63FWP5|unrepl>/edn (set-file-line-col
<#C4C63FWP5|unrepl>/param :unrepl/sourcename
<#C4C63FWP5|unrepl>/param :unrepl/line
<#C4C63FWP5|unrepl>/param :unrepl/col)]}}]
@cgrand Sure, I understand how the set-source command would be run, but I don’t understand how it actually works. For example, when a user sends a form from their editor to the REPL, if I don’t give that code the correct source location stack traces etc will be wrong. That’s why I do the wrapping that @thheller was complaining about - to be fair, it’s pretty awful.
Or eval-with-pos, perhaps. i.e. it needs the source position and the code to be evaled.
Sure, that’s a possibility, just trying to clarify that that is how it works. It feels somewhat icky, since you’re swapping essentially a functional interface for a stateful one, but that could work.
Sure, but trying to minimise the dependency on state in potentially racy ways is generally a good goal.
But I think that’s probably ok, just trying to clarify in my mind what you’re envisioning.
So for something like execution interruption, you would use a command like… right, :interrupt
would stop the last executed command?
The SQL thing is really an IntelliJ issue I have to deal with. But even something like Emacs will have to deal with it too, i.e. the user would probably want to switch major/minor modes depending on what they’re wanting to send.
But it illustrates the problem that the client can’t automatically know what the server is expecting.
What do you think about the possibility of the REPL advertising in its hello message a content type, or something similar?
it’s a good idea prompted by your questions (see https://clojurians.slack.com/archives/unrepl/p1489050829293403)
but if it’s the same interrupt for user-eval and command a user may interrupt a command (or you have to keep track of what is running: eval or command)
while interrupting a command may be something you want to do because it’s takiing too long
What will happen if a client sends multiple commands? The server will have to read one ahead for interruption to work, I guess.
So: • one command which interrupts only eval • one command which interrupts anyithing • two commands, one for eval, one for commands
Since by definition it will have to read the interrupt command while something is still evaluating.
So the exec loop will read a command, execute it on another thread to allow interruption, then read the following command and execute it if it’s an interruption, otherwise queue it?
and because the result of read may depend on the repl state, reading ahead is not great
Apart from that case I think I’d rather have the commands have easily-inspectable textual representations, but I think that is a good exception.
Hmmm one can imagine :secret-ns/stop
for interrupt: it works too because you only need a wider pushback window and you don’t need to use read
However (secret/stop)
would not work because it has unbounded representations (eg ( secret/stop )
)
I’m not sure - what immediately springs to mind is a content type, but perhaps just a keyword would do.
I don’t even know if content types exist for program code apart from text/clojure or something.
I connect to a socket REPL, but at that point I haven’t received anything - I still have to guess what is on the other end.
I send my unrepl code for Clojure after guessing, and I get a [:hello {:lang :clj :env :jvm}]
but it’s mostly redundant since at that point I know what it is anyway.
Then I send some code to start a CLJS REPL, and I’m still in the same situation - I’m faced with an [:upgrade nil]
and a socket, but I don’t know what’s coming.
At that point I probably do, since I started the CLJS REPL, but if the user has done it manually I don’t.
Well, no - I have to know what the remote REPL type is in order to send my unrepl init code, no?
Assuming the user runs something which starts a CLJS unrepl directly. If it starts a CLJS socket REPL I won’t get that.
It seems to me that the content advertisement comes too late to be useful in many (not all) cases.
In the case that the user is in one type of unrepl (say CLJ), and runs code to start another sort of unrepl (say CLJS) right away, then it’s useful.
But you still can’t discover from a raw socket REPL what the other side is expecting. Writing it down like that, it seems obvious.
Bootstrapping a plain repl to an unrepl one is just that a bootstrapping solution. I’d like more repls to support unrepl from the start. In this case (larger ecosystem) content advertisement will be useful.
In the mean time you have to rely on clutches (a magic “sniff platform and send upgrade blob” button)
Yes, or the user explicitly telling you what to do (convert CLJ REPL to unrepl, convert CLJS REPL to unrepl, etc)
I suspect there will always be a certain amount of user interaction here, and the user will have to have some idea of what’s actually going on.
Clojure 1.9.0-alpha14
user=> (require '[unrepl.repl])
nil
user=> (unrepl.repl/start)
[:unrepl/hello {:commands {:interrupt <#C4C63FWP5|unrepl>/raw \u0003, :exit <#C4C63FWP5|unrepl>/raw \u0004, :set-source <#C4C63FWP5|unrepl>/raw [\u0010 <#C4C63FWP5|unrepl>/edn (set-file-line-col <#C4C63FWP5|unrepl>/param :unrepl/sourcename <#C4C63FWP5|unrepl>/param :unrepl/line <#C4C63FWP5|unrepl>/param :unrepl/col)]}}][:prompt {clojure.core/*warn-on-reflection* false, clojure.core/*ns* <#C4C63FWP5|unrepl>/ns user}]
Create an image
(java.awt.image.BufferedImage. 100 200 java.awt.image.BufferedImage/TYPE_INT_RGB)
[:eval <#C4C63FWP5|unrepl>/object [#unrepl.java/class java.awt.image.BufferedImage "0x366ef90e" {:width 100, :height 200, :attachment <#C4C63FWP5|unrepl>/mime {#unrepl/... {:get <#C4C63FWP5|unrepl>/raw "\u0010(... G__219)"} <#C4C63FWP5|unrepl>/... nil}}] 1][:prompt {clojure.core/*warn-on-reflection* false, clojure.core/*ns* <#C4C63FWP5|unrepl>/ns user}]
print-level was set to low, ask for the elided part
^P(... G__219)
[:command ([:content-type “image/png”] [:get <#C4C63FWP5|unrepl>/raw "\u0010(file G__218)”)) 2][:prompt {clojure.core/*warn-on-reflection* false, clojure.core/*ns* <#C4C63FWP5|unrepl>/ns user}]
Ask for the content (it’s a :get
in a #unrepl/mime
):
^P(file G__218)
[:command "iVBORw0KGgoAAAANSUhEUgAAAGQAAADICAYAAAAePETBAAABKElEQVR42u3RIQEAAAjAsPcvDSUQiIkX+KpGrzIBiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiAwAIiBABASIgAARECACIiBABASIgAARECACIiBABASIgAARECACIiBABASIgAARECACIiBABASIgAARECACIiBABASIgAARECACIiBABASIgAARECACIiBABASIgAARECACIiBABASIgAARECACIgOACAgQAQEiIEAEBIgJQAQEiIAAERAgAgJEQAQEiIAAERAgAgJEQAQEiIAA0V0L0zPWZOcDDp8AAAAASUVORK5CYII=" 3][:prompt {clojure.core/*warn-on-reflection* false, clojure.core/*ns* <#C4C63FWP5|unrepl>/ns user}]
base64 of a black pngJust want to thank @cfleming for inviting me and say that I've read the whole conversation including the linked discussions.
One thing to note, is that a major problem is trying to treat 4 explicit streams as 2 this seems to be causing a lot of pain.
Excerpt from my outputstream:
[:out "Hi Bruce" 1][:out "\n" 1][:out "Hi Christophe" 2][:out "\n" 2][:out "Hi Bruce" 1][:out "\n" 1][:out "Hi Christophe" 2][:out "\n" 2][:out "Hi Bruce" 1][:out "\n" 1][:out "Hi Christophe" 2][:out "\n" 2][:out "Hi Bruce" 1][:out "\n" 1][:out "Hi Christophe" 2][:out "\n" 2][:out "Hi Bruce" 1][:out "\n" 1][:out "Hi Christophe" 2][:out "\n" 2][:out "Hi Bruce" 1][:out "\n" 1][:out "Hi Christophe" 2][:out "\n" 2][:out "Hi Bruce" 1][:out "\n" 1][:out "Hi Christophe" 2][:out "\n" 2][:out "Hi Bruce" 1][:out "\n" 1][:out "Hi Christophe" 2][:out "\n" 2][:out "Hi Bruce" 1][:out "\n" 1][:out "Hi Christophe" 2][:out "\n" 2][:out "Hi Bruce" 1][:out "\n" 1]
Some important updates to the spec: • section “Filling the gap” https://github.com/cgrand/unrepl#filling-the-gap • section “Message templates” https://github.com/cgrand/unrepl#message-templates
I'm playing with the repo using
rlwrap java -cp $HOME/.m2/repository/org/clojure/clojure/1.9.0-alpha14/clojure-1.9.0-alpha14.jar:src clojure.main -i src/unrepl/repl.clj -e '(unrepl.repl/start)'
1. could unrepl send "\n"s after each message? that would make interacting as a human easier
why not after each message?
Painfully if EDN. Easily if JSON. But transfer with channels can already be troublesome. sigh
I noticed that I get a Java window, I image because you import java.awt.Image
I'd tend to say that rich results like images should be opt-in to avoid such surprising side-effects
"exit" doesn't seem to work ("Type exit to exit back to the original repl.")
I mentioned exit
because it's mentioned in the readme
playing with unrepl is fun, really liking what I'm seeing already
is there a way to enter the ^C char from a terminal?
ah cool
works well (not with rlwrap though)
^Q^C
also doesn't work - seems like an issue with rlwrap
I have been following for a while now, good job folks 😉
[[:fs-updates:fs-updates [[{{:dir:dir #object[#object[java.io.File java.io.File 0x3f7d50df 0x3f7d50df ""//UUsseerrss//zziilleennccee//ccooddee//sshhaaddooww--ddeevvttoooollss//ssrrcc//mmaaiin"n"], :dir-type :classpath, :name ]", s:dir-type h:classpath, a:name d"oswh/addeovwt/odoelvst/osoelrsv/esre/rwvoerrk/ewro/rikmeprl/.icmlpj"l, .:ext c"lcj", l:ext j"", c:file l#object[java.io.File j"0x772a31be , ":file /#object[java.io.File Use0x772a31be r"s//Uzsielresn/czei/lceondcee//schoaddeo/ws-hdaedvotwo-odlesv/tsorocl/sm/asirnc//smhaaidno/ws/hdaedvotwo/odlesv/tsoeorlvse/rs/ewrovrekre/rw/oirmkpelr./cilmj"]p, l:event .:modc}l]j"], :event :mod}]]]