use navy_nvim_rs::{Handler, create, neovim::Neovim};
use rmpv::Value;
use std::sync::Arc;
use tokio::{
self,
process::{ChildStdin, Command},
spawn,
};
use tokio::sync::Mutex;
mod common;
use common::*;
#[derive(Clone)]
struct NeovimHandler {
froodle: Arc<Mutex<String>>,
}
impl Handler for NeovimHandler {
type Writer = ChildStdin;
async fn handle_request(
&self,
name: String,
args: Vec<Value>,
neovim: Neovim<ChildStdin>,
) -> Result<Value, Value> {
match name.as_ref() {
"dummy" => Ok(Value::from("o")),
"req" => {
let v = args[0].as_str().unwrap();
let neovim = neovim.clone();
match v {
"y" => {
let mut x: String = neovim
.get_vvar("progname")
.await
.unwrap()
.as_str()
.unwrap()
.into();
x.push_str(" - ");
x.push_str(neovim.get_var("oogle").await.unwrap().as_str().unwrap());
x.push_str(" - ");
x.push_str(
neovim
.eval("rpcrequest(1,'dummy')")
.await
.unwrap()
.as_str()
.unwrap(),
);
x.push_str(" - ");
x.push_str(
neovim
.eval("rpcrequest(1,'req', 'z')")
.await
.unwrap()
.as_str()
.unwrap(),
);
Ok(Value::from(x))
}
"z" => {
let x: String = neovim
.get_vvar("progname")
.await
.unwrap()
.as_str()
.unwrap()
.into();
Ok(Value::from(x))
}
&_ => Err(Value::from("wrong argument to req")),
}
}
&_ => Err(Value::from("wrong method name for request")),
}
}
async fn handle_notify(&self, name: String, args: Vec<Value>, _neovim: Neovim<ChildStdin>) {
if name.as_str() == "set_froodle" {
*self.froodle.lock().await = args[0].as_str().unwrap().to_string()
};
}
}
#[tokio::test(flavor = "current_thread")]
async fn nested_requests() {
let rs = r#"exe ":fun M(timer)
call rpcnotify(1, 'set_froodle', rpcrequest(1, 'req', 'y'))
endfun""#;
let rs2 = r#"exe ":fun N(timer)
call chanclose(1)
endfun""#;
let froodle = Arc::new(Mutex::new(String::new()));
let handler = NeovimHandler {
froodle: froodle.clone(),
};
let mut cmd = Command::new(nvim_path());
cmd.args([
"-u",
"NONE",
"--embed",
"--headless",
"-c",
rs,
"-c",
":let timer = timer_start(500, 'M')",
"-c",
rs2,
"-c",
":let timer = timer_start(1500, 'N')",
]);
let (nvim, io_handler, _child) = create::new_child_cmd(cmd, handler).unwrap();
let nv = nvim.clone();
spawn(async move { nv.set_var("oogle", Value::from("doodle")).await });
if let Err(err) = io_handler.await.unwrap()
&& !err.is_channel_closed()
{
panic!("{}", err);
}
assert_eq!(
format!("{nvim} - doodle - o - {nvim}", nvim = NVIM_BIN),
*froodle.lock().await
);
}