lapce-plugin-rust
lapce-plugin-rust copied to clipboard
Functions to send requests and receive response from client editor
A nice way, like #8, for sending requests is desirable.
However, we run into the issue that the plugin author needs to handle any responses from the editor that they receive.
One method would be this:
fn send_request<T: Request>(params: T::Params) -> u64 {
// do some stuff for incrementing a held id, like pluginrpc does currently
// send request
// return id
}
Then, the plugin author would just hold that id
and check it against whatever they receive in handle_response
which gives you the id... but there doesn't seem to be a handle response yet?
That's one way of doing it, and does allow the plugin author to decide how to handle it.
Another potential way, which could be just be implemented on top of the previous method as a library or helper function, is callbacks. This is sort of similar to what Lapce uses internally for responses from what I remember.
type RequestCallback<T: Request> = Box<dyn FnOnce(Result<T::Result, Error>)>;
fn send_request_cb<T: Request>(params: T::Params, response_cb: impl FnOnce<Result<T::Result, Error>>) {
// Wrapper callback which takes in unparsed value and parses it before giving it to the callback
let parser_resp_cb = Box::new(|params: Result<Value, Error>| {
let params: Result<T::Result, Error> = match params {
Ok(params) => serde_json::from_value::<T::Result>(params),
Err(err) => Err(err),
};
response_cb(params);
});
// store parser_resp_cb in some `HashMap<id, Box<dyn FnOnce(Result<Value, Error>)>`, since we wanted to store it on here we had to make it non-generic
}
Then, when the code receives a response, it looks up the id in the hashmap and removes the function if it exists. Then it calls the function with the response value (or an error if the response was an error).
I think we should provide &mut State
as a parameter so that they can modify their state when they get the response, rather than relying on more annoying methods of synchronization. However, we don't know the type of their State
until later. We could put these functions to be generated by the register_plugin
macro.
I think this second option is probably what the default should be. Though we could have both, so then if they want to keep track of their callbacks in a different manner then they can.