2019-07-13 02:07:06 +00:00
|
|
|
use crate::{Args, CommandConfig, ReturnValue, ShellError, Spanned, Value};
|
2019-07-02 07:56:20 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use std::io;
|
|
|
|
|
|
|
|
pub trait Plugin {
|
2019-07-03 17:37:09 +00:00
|
|
|
fn config(&mut self) -> Result<CommandConfig, ShellError>;
|
2019-07-02 07:56:20 +00:00
|
|
|
#[allow(unused)]
|
|
|
|
fn begin_filter(&mut self, args: Args) -> Result<(), ShellError> {
|
|
|
|
Err(ShellError::string(
|
|
|
|
"`begin_filter` not implemented in plugin",
|
|
|
|
))
|
|
|
|
}
|
|
|
|
#[allow(unused)]
|
2019-07-13 02:07:06 +00:00
|
|
|
fn filter(&mut self, input: Spanned<Value>) -> Result<Vec<ReturnValue>, ShellError> {
|
2019-07-02 07:56:20 +00:00
|
|
|
Err(ShellError::string("`filter` not implemented in plugin"))
|
|
|
|
}
|
|
|
|
#[allow(unused)]
|
2019-07-13 02:07:06 +00:00
|
|
|
fn sink(&mut self, args: Args, input: Vec<Spanned<Value>>) {}
|
2019-07-02 07:56:20 +00:00
|
|
|
|
|
|
|
fn quit(&mut self) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn serve_plugin(plugin: &mut dyn Plugin) {
|
2019-07-04 22:17:18 +00:00
|
|
|
let args = std::env::args();
|
|
|
|
if args.len() > 1 {
|
|
|
|
let input = std::fs::read_to_string(args.skip(1).next().unwrap());
|
|
|
|
if let Ok(input) = input {
|
|
|
|
let command = serde_json::from_str::<NuCommand>(&input);
|
|
|
|
match command {
|
|
|
|
Ok(NuCommand::config) => {
|
|
|
|
send_response(plugin.config());
|
|
|
|
}
|
|
|
|
Ok(NuCommand::begin_filter { params }) => {
|
2019-07-13 16:59:59 +00:00
|
|
|
send_response(
|
|
|
|
plugin
|
|
|
|
.begin_filter(params)
|
|
|
|
.map(|_| Vec::<ReturnValue>::new()),
|
|
|
|
);
|
2019-07-04 22:17:18 +00:00
|
|
|
}
|
|
|
|
Ok(NuCommand::filter { params }) => {
|
|
|
|
send_response(plugin.filter(params));
|
|
|
|
}
|
|
|
|
Ok(NuCommand::sink { params }) => {
|
|
|
|
plugin.sink(params.0, params.1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Ok(NuCommand::quit) => {
|
|
|
|
plugin.quit();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
e => {
|
|
|
|
send_response(ShellError::string(format!(
|
|
|
|
"Could not handle plugin message: {} {:?}",
|
|
|
|
input, e
|
|
|
|
)));
|
|
|
|
return;
|
2019-07-02 07:56:20 +00:00
|
|
|
}
|
|
|
|
}
|
2019-07-04 22:17:18 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
loop {
|
|
|
|
let mut input = String::new();
|
|
|
|
match io::stdin().read_line(&mut input) {
|
|
|
|
Ok(_) => {
|
|
|
|
let command = serde_json::from_str::<NuCommand>(&input);
|
|
|
|
match command {
|
|
|
|
Ok(NuCommand::config) => {
|
|
|
|
send_response(plugin.config());
|
|
|
|
}
|
|
|
|
Ok(NuCommand::begin_filter { params }) => {
|
2019-07-13 16:59:59 +00:00
|
|
|
send_response(
|
|
|
|
plugin
|
|
|
|
.begin_filter(params)
|
|
|
|
.map(|_| Vec::<ReturnValue>::new()),
|
|
|
|
);
|
2019-07-04 22:17:18 +00:00
|
|
|
}
|
|
|
|
Ok(NuCommand::filter { params }) => {
|
|
|
|
send_response(plugin.filter(params));
|
|
|
|
}
|
|
|
|
Ok(NuCommand::sink { params }) => {
|
|
|
|
plugin.sink(params.0, params.1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Ok(NuCommand::quit) => {
|
|
|
|
plugin.quit();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
e => {
|
|
|
|
send_response(ShellError::string(format!(
|
|
|
|
"Could not handle plugin message: {} {:?}",
|
|
|
|
input, e
|
|
|
|
)));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
e => {
|
|
|
|
send_response(ShellError::string(format!(
|
|
|
|
"Could not handle plugin message: {:?}",
|
|
|
|
e,
|
|
|
|
)));
|
|
|
|
break;
|
|
|
|
}
|
2019-07-02 07:56:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
pub struct JsonRpc<T> {
|
|
|
|
jsonrpc: String,
|
|
|
|
pub method: String,
|
|
|
|
pub params: T,
|
|
|
|
}
|
|
|
|
impl<T> JsonRpc<T> {
|
|
|
|
pub fn new<U: Into<String>>(method: U, params: T) -> Self {
|
|
|
|
JsonRpc {
|
|
|
|
jsonrpc: "2.0".into(),
|
|
|
|
method: method.into(),
|
|
|
|
params,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn send_response<T: Serialize>(result: T) {
|
|
|
|
let response = JsonRpc::new("response", result);
|
|
|
|
let response_raw = serde_json::to_string(&response).unwrap();
|
|
|
|
println!("{}", response_raw);
|
|
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
#[serde(tag = "method")]
|
|
|
|
#[allow(non_camel_case_types)]
|
|
|
|
pub enum NuCommand {
|
|
|
|
config,
|
|
|
|
begin_filter { params: Args },
|
2019-07-13 02:07:06 +00:00
|
|
|
filter { params: Spanned<Value> },
|
|
|
|
sink { params: (Args, Vec<Spanned<Value>>) },
|
2019-07-02 07:56:20 +00:00
|
|
|
quit,
|
|
|
|
}
|