This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-03-15
Channels
- # arachne (6)
- # aws-lambda (3)
- # beginners (14)
- # boot (56)
- # cider (8)
- # cljs-dev (5)
- # cljsrn (11)
- # clojure (240)
- # clojure-dusseldorf (3)
- # clojure-greece (165)
- # clojure-italy (5)
- # clojure-romania (1)
- # clojure-russia (24)
- # clojure-uk (30)
- # clojure-ukraine (3)
- # clojurescript (29)
- # core-async (6)
- # css (1)
- # cursive (25)
- # datascript (6)
- # datomic (61)
- # dirac (1)
- # events (3)
- # hoplon (1)
- # instaparse (3)
- # jobs (4)
- # juxt (28)
- # lein-figwheel (7)
- # leiningen (19)
- # luminus (1)
- # lumo (2)
- # nyc (1)
- # off-topic (19)
- # om (25)
- # onyx (4)
- # parinfer (2)
- # pedestal (23)
- # perun (20)
- # re-frame (44)
- # reagent (20)
- # remote-jobs (3)
- # ring (3)
- # ring-swagger (5)
- # rum (12)
- # slack-help (3)
- # spacemacs (25)
- # specter (62)
- # sql (16)
- # unrepl (313)
- # yada (4)
@cfleming I agree that most people (me included until this thread two years ago) don't see the difference between a top level interpreter and a true lisp repl. Even c2 or Wikipedia don't mention that.
@cfleming I think its a definition problem. If all you have is a terminal a REPL is exactly what you want. text in/text out. If you have a full blown IDE you can do way more like inspector windows, trace windows, dedicated windows for output
the lisp tools all seem to embed the VM into the IDE process. Giving them full access to the runtime, even running the IDE in that runtime.
I doubt they do as I couldn't even find a remote connect option in LispWorks for example
so if we started from scratch without the assumption that we must use a REPL for everything
I think lighttable came up with InstaREPL
... which isn't even remotely related to a REPL. InstaEVAL
ok ... but not even close to a REPL.
in the IntelliJ debugger you have an "Evaluate expression" that takes exactly one expression and displays the result
I want that ... just don't call it a REPL and heck even bind *in*
to nil no one can even begin to use it as such
whether or not the whole tooling stuff then gets started over a REPL in the first place or not
point is that you could ... that would be a lot harder with nREPL to the point of impossible
> But, we now have nice editors/IDEs often running on the same machine, with the ability to use sockets. Multiplexing their needs with those of a human REPL consumer over the same connection is going to make things bad for one or both of them.
Multiplexing their needs
just don't do that ... open another connection and everything is good again
@cfleming so while users don’t want a “true repl”, there may be value in having a true repl. It’s sort of an exegesis work to understand what makes a true REPL according to Rich (I’d like to find other sources). So my current interpretation is that a REPL allows: • a simple sequential evaluation model • upgrading to anything (taking over in and out) • extending it (because the components of the repl are available you can put an extended version together and “upgrade” to it)
@thheller @cfleming with unrepl I’m trying to define what a m2m-friendly repl could be. I’m not trying to provide a solution to all tooling needs.
I think the question is whether the unrepl
model of upgrading/downgrading a REPL is simpler for tools than just connecting tools to a different port than the user would?
It is. Bye can provide for example a hint that the tooling has to provide further stdin. Useful for vim.
the issue is: if you don't control *out*
precisely you are going to get into trouble
@kotarak if you just want to upgrade to an autocompletion endpoint, I wouldn’t even bother to upgrade to unrepl first
which then begs the question .. wouldn't it be easier if it was upgraded before you connected?
If the first thing you do is (set! *out* (wrapper *out*))
(and stash the original out somewhere) you can later mute all spurious outs
So yes you have to consume what’s printed, then you upgrade and part of the upgrade is muting spurious outs so once upgrade is done you have a clean connection.
having unrepl started by the process on a different port. Connecting to a plain repl to start an unrepl server. etc. are all different ways of getting to unrepl with different tradeoffs
ClojureScript Node.js REPL server listening on 58310
To quit, type: :cljs/quit
cljs.user=>
who is to say that another socket REPL doesn't also print something other than the prompt
heck if I ssh
into a server I get Last login: Mon Mar 13 13:46:10 2017 from 2a02:8109:10bf:c004:bc02...
that works until something in your bootstrap code started a thread with a rogue print
What does bootstrap do? It defines functions. The only exception there is syntax. That can be fixed statically. The upgrade is one function call. It can handle exceptions there.
Library dependencies must be localized to the tool. (for hardcore: even tool version)
Having unrepl available would make the initial bootstrap and upgrade nicer. Also the repl as in "user interface".
Vim is not about task handling. This is a job for other tools. Lein boot gradle make whatever
point is .. the user needs to run something (and make sure that something also exposes the REPL port)
You could run it automatically if that connection fails, but i wouldn't. I prefer Proper control over started processes.
so it boils down to someone called lein run -m unrepl.repl/start
.. whether that was a tool or the user doesn't matter
Yeah. Well. You need an environment. One thing I learned: implicit, hidden fairy dust is the root of all evil
point is that all this could start a unrepl at one port .. plain socket repl on another and maybe even a tool thing on another
I just do a lein repl in a terminal. Problem solved. And second repl always handy if need bem
it just leads to a bunch of "bootstrap failed because ... a message nobody understands"
It solves several problems. One having a split in the both sides which become disconnected.
Having a running socket repl is less trouble than having a lein plugin which requires additional libraries only at dev time which setup there own socket....
For cljs that might be. For clj I survived 4 years without. And reactivating that 5 year old code now seems to show it still works....
well if it fails you tell the user it failed and report to the nice benevolent maintainer
yes exactly .. the process is the same. the user is most likely going to edit their project.clj
and restart the process
bootstrap
sounds cool in theory, in practice things go wrong. I'd much rather fail to start the process altogether
instead of "hey my process works" but my REPL doesn't ... putting the burden on every tool out there
it’s no different than a connection failure or a protocol mismatch (who put SMTP on 22?)
Life is hard. The tool is a tool. It must put as low a burden on the user as possible. If the user has to care for the tools boilerplate something's wrong. In particular it must not be noticeable unless if asked something. That means no conflicts with the user project. Making life easy for toolmakers on the back of users is a no-go. My opinion.
That doesn't mean it does everything. As I said: it's not vim's job to run background processes.
@kotarak its not my point to make vim
do any of that. you are correct that it shouldn't.
it is my impression however that bootstrapping everything you want to do with a tool over an unknowing REPL is a fantasy
What's not available afterwards, eg. clojure.spec, is deactivated for this connection.
so in my view the user will start a process, if that process succeeds and displays a "Ready" message everything works
for bootstrap the process will start and appear normal .. whether or not the REPL will actually work is TBD
@thheller Why? When the bootstrapping fails the user might as well get an error message.
@kotarak yes the user will get an error message. in my view when the process starts, for bootstrap when the REPL starts
but how do you do that in the first place, given that you can't just start another REPL
doubt that anyone ever attempted that so this is just my arguably pessimistic instinct
https://github.com/thheller/shadow-devtools/blob/master/src/main/shadow/devtools/api.clj#L80-L110
and FWIW I have https://github.com/thheller/shadow-devtools/blob/master/src/main/shadow/devtools/embedded.clj
(embed/repl :my-build)
which I can quit any time without stopping the CLJS build worker in the background
but thats about process mangement again, sometimes I just want the build running with auto reloading
Ok. @kotarak @thheller either it's the headache talking or you won. I'm considering ditching escaping in favor of a second connection dedicated to process control.
go relax and come back without the headache, all this needs more hammock-time I feel
the second connection isn't perfect either .. now that I implemented some of the language server protocol I already hate it
well its too early to call it hate, its the versioning thing Rich talked about recently
so I used v3 as a reference .. and couldn't figure out why things didn't work in vscode
I think it would be better if the clients just sends a set of methods (their names as strings)
in theory, nREPL doesn't seem to have a standard to differentiate requests from notifications
but now onto my first goal on textDocument/didSave
process the file and report diagnostics (warnings, errors) back to the editor
but the problem isn't actually in the build process ... its that no tool expects this information
oh and I should mention .. I can now fully embed this server into a REPL. all it needs is *in*
and *out*
what I haven't figured out is how the client would know when the protocol starts, given the user=>
prompt issue I talked about earlier
Re: escaping. The problem with framing/escaping etc. Is that at some point you have a buffer or a queue. And forms waiting to be evaluated may block interruption for example. You can push the boundaries and create separate queues etc. But it gets complex fast.
Right now I'm thinking of advertising in :hello a form to eval in another repl to turn it into a remote control.
Yeah that's why I would need to .read
ahead and just scan for the esc or sequence. I've come up with `"\uE5CA\n[)\"[)" as an escape sequence with low probability of buffering and not being valid input.
Sadly no. \0 is valid in strings. And it has been reiterated in EDN. No general escape mechanism.
Copy pasting can bring a lot of surprising characters. Even when copying from the output.
So I’m having trouble following all of this, I come in each morning to a wall of text 🙂
And I’m not down in the weeds enough at the moment since I’m busy on other things. I’m hoping to start on REPL stuff next week.
the above screenshot is just there to demonstrate what is possible with a independent language server connection
but I think we agree that this connection connection should no longer be treated as a REPL if it was upgraded
@cfleming I would love this as a first step https://github.com/cursive-ide/cursive/issues/1672
Rather, you can use it for TypeScript if you choose to (which everyone does these days, I think).
all of this is the language server of course, but the port you would connect to there is the Socket REPL
alternative would be to cljs/eval {:code "(prn :foo)"}
-> {:result "nil" :out ":foo\n"}
Ok, like I say, I don’t have enough room in my head for all this right now. I’m planning to look at your shadow stuff next week when I start on all this.
I follow the language server protocol for now but I could make all that work over nREPL as well
so if you have nREPL infra already (and most tools do) it might be better for us to stick to that
The problem with nREPL is that you can’t access the protocol from user code, you have to use middleware.
however again: if you assume the language server model the nrepl protocol is flexible enough to use that
My problem is that I don’t want to create two parallel tooling implementations, one over nREPL and one that is not.
how much of nREPL are you using in Cursive? you don't use that for stuff like autocomplete right?
In the REPL editor I do autocomplete using the REPL connection, but it’s not using nREPL middleware, just eval
we could just mirror these methods https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md#messages-overview
I'm just saying to re-use the nREPL protocol for the tool stuff since you already have that (as does every other tool)
{:warning :invalid-arithmetic, :line 7, :column 1, :msg "cljs.core/+, all arguments must be numbers, got [string number] instead.", :extra {:js-op cljs.core/+, :types [string number]}}
can't properly underline code based on that info