I spent some hammock time (ski lift time actually), brooding over unrepl.
- cleanly multiplexed output (out, err, eval, exception etc.)
- elisions (which can provide all sort of browsing navigation)
- attachments
:bye
The upgrade-plain-repl scenario should be the norm without excluding other uses (preexisting unrepl). In the last few weeks I have drifted too much from this scenario.
Most of my thoughts went to control (commands etc.).
I now believe that all the input stuff (various escaping mechanisms etc.) discussed so far is wrong.
If we stick to controls that are tightly related to a repl (interrupt, background, elision retrieval, sideloading, setting various dynvars without altering *1
, *2
, *3
),
we realize that most if not all require to happen concurrently to eval and user input (and devising when the input stream is in a state where it is correct to splice some control stuff is difficult to do in a way that's foolproof.)
That's why I believe that all control should happen through additional communication channels. How one creates a communication channel? By upgrading a plain repl (not necessarily to unrepl, it may be to a specialized endpoint).
However creating a new socket is not always possible. In such cases the initial repl must be upgraded to a multiplexed connection.
So multiplexing makes the "multiple connections" approach workable even in constrained setup, and multiple connections makes the concurrency easier to deal with.
Decomplecting concurrent inputs and unrepl is a good thing.
In such a model the only capacity that unrepl expects from the client is the ability to create new repl connections to the same process. It doesn't mandate how (setting up a new connection, or creating a new channel in a multiplexed connection).
It's possible to reconstruct a pair of in&out streams over a nrepl connection, it would be a helpful shim to gain traction.
Currently :hello
advertises commands but I begin to think that only "session-wide" commands should be there, not interrupt
for example.
Here is some pseudo log:
> (Thread/sleep 1000000)
< [:read {:offset 42 :length 22} 14]
< [:interrupt {:chan :control :action (stop "uusbdjs" 14)} 14]
< [:background {:chan :control :action (bg "uusbdjs" 14)}} 14]
Why so many indirections when the tool performs the upgrade itself? Because hopefully upgrade blobs won't be fully proprietary to each tool.
Vague hint: evalute clojure spec unform as a templating mechanism.