Add end_plugin and sum

This commit is contained in:
Jonathan Turner 2019-07-27 06:40:00 +12:00
parent f326544dd2
commit e4797f8895
7 changed files with 174 additions and 6 deletions

View File

@ -91,6 +91,10 @@ path = "src/lib.rs"
name = "nu_plugin_inc" name = "nu_plugin_inc"
path = "src/plugins/inc.rs" path = "src/plugins/inc.rs"
[[bin]]
name = "nu_plugin_sum"
path = "src/plugins/sum.rs"
[[bin]] [[bin]]
name = "nu_plugin_add" name = "nu_plugin_add"
path = "src/plugins/add.rs" path = "src/plugins/add.rs"

View File

@ -125,12 +125,51 @@ pub fn filter_plugin(path: String, args: CommandArgs) -> Result<OutputStream, Sh
let stdin = child.stdin.as_mut().expect("Failed to open stdin"); let stdin = child.stdin.as_mut().expect("Failed to open stdin");
let stdout = child.stdout.as_mut().expect("Failed to open stdout"); let stdout = child.stdout.as_mut().expect("Failed to open stdout");
let _ = BufReader::new(stdout); let mut reader = BufReader::new(stdout);
let request: JsonRpc<std::vec::Vec<Value>> = JsonRpc::new("quit", vec![]);
let request: JsonRpc<std::vec::Vec<Value>> = JsonRpc::new("end_filter", vec![]);
let request_raw = serde_json::to_string(&request).unwrap(); let request_raw = serde_json::to_string(&request).unwrap();
let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); // TODO: Handle error let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); // TODO: Handle error
VecDeque::new() let mut input = String::new();
match reader.read_line(&mut input) {
Ok(_) => {
let response = serde_json::from_str::<NuResult>(&input);
match response {
Ok(NuResult::response { params }) => match params {
Ok(params) => {
let request: JsonRpc<std::vec::Vec<Value>> =
JsonRpc::new("quit", vec![]);
let request_raw = serde_json::to_string(&request).unwrap();
let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); // TODO: Handle error
params
}
Err(e) => {
let mut result = VecDeque::new();
result.push_back(ReturnValue::Err(e));
result
}
},
Err(e) => {
let mut result = VecDeque::new();
result.push_back(Err(ShellError::string(format!(
"Error while processing input: {:?} {}",
e, input
))));
result
}
}
}
Err(e) => {
let mut result = VecDeque::new();
result.push_back(Err(ShellError::string(format!(
"Error while processing input: {:?}",
e
))));
result
}
}
} }
_ => { _ => {
let stdin = child.stdin.as_mut().expect("Failed to open stdin"); let stdin = child.stdin.as_mut().expect("Failed to open stdin");

View File

@ -15,6 +15,10 @@ pub trait Plugin {
Err(ShellError::string("`filter` not implemented in plugin")) Err(ShellError::string("`filter` not implemented in plugin"))
} }
#[allow(unused)] #[allow(unused)]
fn end_filter(&mut self) -> Result<Vec<ReturnValue>, ShellError> {
Ok(vec![])
}
#[allow(unused)]
fn sink(&mut self, call_info: CallInfo, input: Vec<Spanned<Value>>) {} fn sink(&mut self, call_info: CallInfo, input: Vec<Spanned<Value>>) {}
fn quit(&mut self) { fn quit(&mut self) {
@ -42,6 +46,10 @@ pub fn serve_plugin(plugin: &mut dyn Plugin) {
Ok(NuCommand::filter { params }) => { Ok(NuCommand::filter { params }) => {
send_response(plugin.filter(params)); send_response(plugin.filter(params));
} }
Ok(NuCommand::end_filter) => {
send_response(plugin.end_filter());
}
Ok(NuCommand::sink { params }) => { Ok(NuCommand::sink { params }) => {
plugin.sink(params.0, params.1); plugin.sink(params.0, params.1);
return; return;
@ -79,6 +87,9 @@ pub fn serve_plugin(plugin: &mut dyn Plugin) {
Ok(NuCommand::filter { params }) => { Ok(NuCommand::filter { params }) => {
send_response(plugin.filter(params)); send_response(plugin.filter(params));
} }
Ok(NuCommand::end_filter) => {
send_response(plugin.end_filter());
}
Ok(NuCommand::sink { params }) => { Ok(NuCommand::sink { params }) => {
plugin.sink(params.0, params.1); plugin.sink(params.0, params.1);
break; break;
@ -140,6 +151,7 @@ pub enum NuCommand {
filter { filter {
params: Spanned<Value>, params: Spanned<Value>,
}, },
end_filter,
sink { sink {
params: (CallInfo, Vec<Spanned<Value>>), params: (CallInfo, Vec<Spanned<Value>>),
}, },

99
src/plugins/sum.rs Normal file
View File

@ -0,0 +1,99 @@
use indexmap::IndexMap;
use nu::{
serve_plugin, CallInfo, CommandConfig, Plugin, Primitive, ReturnSuccess, ReturnValue,
ShellError, Spanned, Value,
};
struct Sum {
total: Option<Spanned<Value>>,
}
impl Sum {
fn new() -> Sum {
Sum { total: None }
}
fn sum(&mut self, value: Spanned<Value>) -> Result<(), ShellError> {
match value.item {
Value::Primitive(Primitive::Int(i)) => {
match self.total {
Some(Spanned {
item: Value::Primitive(Primitive::Int(j)),
span,
}) => {
//TODO: handle overflow
self.total = Some(Spanned {
item: Value::int(i + j),
span,
});
Ok(())
}
None => {
self.total = Some(value);
Ok(())
}
_ => Err(ShellError::string(format!(
"Could not sum non-integer or unrelated types"
))),
}
}
Value::Primitive(Primitive::Bytes(b)) => {
match self.total {
Some(Spanned {
item: Value::Primitive(Primitive::Bytes(j)),
span,
}) => {
//TODO: handle overflow
self.total = Some(Spanned {
item: Value::bytes(b + j),
span,
});
Ok(())
}
None => {
self.total = Some(value);
Ok(())
}
_ => Err(ShellError::string(format!(
"Could not sum non-integer or unrelated types"
))),
}
}
x => Err(ShellError::string(format!(
"Unrecognized type in stream: {:?}",
x
))),
}
}
}
impl Plugin for Sum {
fn config(&mut self) -> Result<CommandConfig, ShellError> {
Ok(CommandConfig {
name: "sum".to_string(),
positional: vec![],
is_filter: true,
is_sink: false,
named: IndexMap::new(),
rest_positional: true,
})
}
fn begin_filter(&mut self, _: CallInfo) -> Result<(), ShellError> {
Ok(())
}
fn filter(&mut self, input: Spanned<Value>) -> Result<Vec<ReturnValue>, ShellError> {
self.sum(input)?;
Ok(vec![])
}
fn end_filter(&mut self) -> Result<Vec<ReturnValue>, ShellError> {
match self.total {
None => Ok(vec![]),
Some(ref v) => Ok(vec![ReturnSuccess::value(v.clone())]),
}
}
}
fn main() {
serve_plugin(&mut Sum::new());
}

View File

@ -2,10 +2,10 @@ mod helpers;
use helpers::in_directory as cwd; use helpers::in_directory as cwd;
#[test] #[test]
fn can_convert_table_to_csv_text_and_from_csv_text_back_into_table() { fn can_convert_table_to_csv_text_and_from_csv_text_back_into_table() {
nu!(output, nu!(
output,
cwd("tests/fixtures/formats"), cwd("tests/fixtures/formats"),
"open caco3_plastics.csv | to-csv | from-csv | first 1 | get origin | echo $it" "open caco3_plastics.csv | to-csv | from-csv | first 1 | get origin | echo $it"
); );
@ -87,6 +87,16 @@ fn can_inc_field() {
assert_eq!(output, "2019"); assert_eq!(output, "2019");
} }
#[test]
fn can_sum() {
nu!(
output,
cwd("tests/fixtures/formats"),
"open sgml_description.json | get glossary.GlossDiv.GlossList.GlossEntry.Sections | sum | echo $it"
);
assert_eq!(output, "203")
}
#[test] #[test]
fn can_filter_by_unit_size_comparison() { fn can_filter_by_unit_size_comparison() {
nu!( nu!(

View File

@ -10,7 +10,7 @@ string2 = "Case 2"
; comment line ; comment line
key = new value key = new value
integer = 1234 integer = 5678
real = 3.14 real = 3.14
string1 = 'Case 1' string1 = 'Case 1'
string2 = "Case 2" string2 = "Case 2"

View File

@ -18,6 +18,10 @@
"XML" "XML"
] ]
}, },
"Sections": [
101,
102
],
"GlossSee": "markup" "GlossSee": "markup"
} }
} }