use std::{
error::Error,
io::{BufRead, BufReader, Write},
process::{ChildStdin, Command, Stdio},
};
use winit::event_loop::EventLoopProxy;
use crate::{
AppMessage, Rpc,
json_ui::{self, Response},
};
pub struct Kakoune {
stdin: ChildStdin,
}
impl Kakoune {
pub fn new(event_loop_proxy: EventLoopProxy<AppMessage>) -> Self {
let mut args: Vec<String> = std::env::args().collect();
args.remove(0);
args.insert(0, String::from("json"));
args.insert(0, String::from("-ui"));
let mut child = Command::new("kak")
.args(&args[..])
.stdout(Stdio::piped())
.stdin(Stdio::piped())
.spawn()
.expect("Failed to spawn Kakoune");
_ = child;
let mut stdout = BufReader::new(child.stdout.take().expect("Failed to get Kakoune stdout"));
let stdin = child.stdin.take().expect("Failed to get stdin");
std::thread::spawn(move || {
let mut buf = String::new();
loop {
buf.clear();
let Ok(read) = stdout.read_line(&mut buf) else {
break;
};
if read == 0 {
break;
}
let content: Rpc<json_ui::Request> =
serde_json::from_str(&buf).expect("Kakoune json_ui is broken");
if event_loop_proxy
.send_event(AppMessage::Kakoune(content.inner))
.is_err()
{
return;
}
}
_ = event_loop_proxy.send_event(AppMessage::Exit);
});
Self { stdin }
}
pub fn send_response(&mut self, resp: Response) -> Result<(), Box<dyn Error>> {
let resp = serde_json::to_string(&Rpc::from(resp)).unwrap();
self.stdin.write_all(resp.as_bytes())?;
self.stdin.write_all(b"\n")?;
Ok(())
}
pub fn join(self) {
std::mem::drop(self.stdin);
}
}