1use std::io::{self, BufRead, Write};
4
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8#[derive(Debug, Deserialize, Serialize)]
10pub struct PluginRequest {
11 #[serde(rename = "type")]
13 pub typ: String,
14 pub snippet: Value,
16}
17
18#[derive(Debug, Serialize, Deserialize)]
20pub struct PluginResponse {
21 pub ok: bool,
23 pub lines: Vec<String>,
25 pub error: Option<String>,
27}
28
29impl PluginResponse {
30 pub fn ok(lines: Vec<String>) -> Self {
32 Self {
33 ok: true,
34 lines,
35 error: None,
36 }
37 }
38
39 pub fn error(message: impl Into<String>) -> Self {
41 Self {
42 ok: false,
43 lines: Vec::new(),
44 error: Some(message.into()),
45 }
46 }
47}
48
49pub fn plugin_loop<F>(mut handler: F) -> io::Result<()>
53where
54 F: FnMut(PluginRequest) -> PluginResponse,
55{
56 let stdin = io::stdin();
57 let mut stdout = io::BufWriter::new(io::stdout());
58 for line in stdin.lock().lines() {
59 let line = match line {
60 Ok(line) => line,
61 Err(_) => break,
62 };
63 if line.trim().is_empty() {
64 continue;
65 }
66 let req: Result<PluginRequest, _> = serde_json::from_str(&line);
67 let resp = match req {
68 Ok(req) => handler(req),
69 Err(err) => PluginResponse::error(format!("invalid request: {err}")),
70 };
71 let json = serde_json::to_string(&resp).unwrap_or_else(|_| {
72 "{\"ok\":false,\"lines\":[],\"error\":\"encode failed\"}".to_string()
73 });
74 writeln!(stdout, "{json}")?;
75 stdout.flush()?;
76 }
77 Ok(())
78}