What is a good way to retrofit actions? I'm thinking about extensions to the client by third party libs. Thus far you'd have to regen the blob. Should there be some way to register actions after the fact? Once done so, they could be cached for a shaded blob.
@kotarak I wanted to ask you about porting my library replant to use vimpire :)
This is exactly the situation I had in mind. Getting the support code on the server is easy due to the sideloader. There we can hook into the search path on the client side. Proper shading is up to the library. However, the library defined actions should behave like the official ones, cf. ensure-ns. Adding locally defined actions to the client is not a problem.
Hrmmmm.... Typing that makes me wonder, whether we can do this without unrepl even bothering. A simple: make-me-an-action-of-this-form would be enough. No need to actually modify the blob at all.
That would also take away the need to actually generate a blob beyond the unrepl one. Yeah! Got rid of a compile step for the client. Shading and b64ing are still necessary, though.
ah the old open question of “should we allow dynamic registration of actions”...
at first I thought it was a must have then I came to believe that the blob was king (at the same time my understanding on what unrepl changed from “an end product” to “a tool to create not-too-sucky private protocols”)
the pendulum is swinging back (don’t worry there’s a damper somewher, each oscillation is less wide than the previous one)
I’m trying to find what pieces of unrepl to expose at runtime. I’m pretty convinced that write
is amongst them (there’s already something in unrepl.core
).
So the way to declare/patch/hook-up-into actions is certainly going to happen through write
: write a message and let the client use it.
:thinking_face: actually it doesn’t work because it’s the server we want to modify, adding actions at some points of the lifecycle and these actions would need some context to be passed in (eval if, session id etc.). A lot of things to commit to (from a design point of view) for which I don’t have a right answer yet.
That’s why the “make your own blob” is easier.
Plus dynamic registration only makes sense for actions known to the client (which is a finite set)
We really need a couple of concrete examples.
I'm confused. Actions are just functions to be called. Blessed with hypermedia fairy dust. I mostly use what they return from eval. So they could be handled completely on the client side, no?
The blob is then sort of defeated.
Client A and Client A+Lib B could share client A, but won't because of blob shading.
My aesthetics (shiver) don't approve.
But maybe I misunderstand actions.
I can’t think about this problem without examples.
I got vimpire. @dominicm got the fancify-this-code lib. He wants hook into vimpire. And I don't want to depend on his lib. So everyone has to generate a custom blob. Meh :-(
And I mean user! For their selection of extensions.
Describe how he his lib can hook up into vimpire without vimpire having provisions for it, which kind of features are we talking about?
Eg. Have form. Send it to backend. Get it rewritten. Get it back. That sort of thing. Get info for completion. Get info for dynamic highlighting. Get docs. That sort thing. That's what my actions, FWIW.
I don't want to depend on external libs, eg. for refactoring. But I can provide the infrastructure.
vimpire#RegisterAction("my-action", ...) vimpire#Action(conn, "my-action", bindings, callbacks) That's how the internal ones work.
I might be able to rely on eval for the most part.
Unlike nrepl there's less of a need for custom actions. So eval & classloader callbacks should be plenty.
All these actions seem very non-contextual (not related to a specific connection or to a specific evaluation) so eval-over-tooling like @dominicm suggests goes a long way. Also you could consider (write [:vimpire/client-eval “vimscript”])
Why would I do vimscript in unrepl? :thinking_face:
a clojure lib sending vimscript code to hook up in vimpire
not saying it’s a good idea
I see. I wonder if bi-directionality is useful. :thinking_face: I can think of some ideas.
But not sure how I would trigger initially, so uncertain.
But maybe a callback on completion would be better for async-stuff
So I can basically skip generation of the blob and just fire of required requires on initial connection. The actions are added locally without unrepl ever knowing about them. Having them helps with shading. I'm not sure what real action is then. I can only think of meta things like auxing, interruption, etc.
"Client-side actions" help keeping the infrastructure in the plugin simpler since all the interaction like read tracking and callbacking and whatnot is already handled.
I don't get where vimscript fits into the picture here. I rather not have my editor run foreign commands.
@dominicm Things come together. With now hopefully more standard names (<Plug>(vimpire_eval)) and cleaned up documentation. And also a set of small demos. Keen observers might spot that I obviously broke the completion. coughcough
However, pay attention to the correctly highlighted baz/yoyo.
It occurs to me that I might need to port it to neovim channels.
Öh. Me has no clue about neovim.
Do its channels work differently?
It only ever does ch_open, ch_setoptions (to switch callbacks) and ch_sendraw.
And a ch_close somewhere in the repl.
it does work differently, yeah
sigh Why can't we have cookies?
Very differently?
uh, quite.
I'm not sure I even want to know how..... Do you think this can be easily hidden away? Or does it require a major rewrite? I mostly use callbacks everywhere...
Ok. A completion demo is now also up.
it's callback based.
But I don't think it has networking built-in.
It uses msgpack-rpc to communicate, but I don't think that will affect you.
It says something about tcp here.
But it seems to mock around with newlines on the receiving end as far as I understood.
Seriously underwhelming.
I wonder how they distinguish "\n" from EOF. :thinking_face:
shows how much I know 🙂