Merge pull request #218 from jonathandturner/sum

Add end_plugin and sum
This commit is contained in:
Jonathan Turner 2019-07-27 06:56:20 +12:00 committed by GitHub
commit 8fa82ffa2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 174 additions and 6 deletions

View File

@ -91,6 +91,10 @@ path = "src/lib.rs"
name = "nu_plugin_inc"
path = "src/plugins/inc.rs"
[[bin]]
name = "nu_plugin_sum"
path = "src/plugins/sum.rs"
[[bin]]
name = "nu_plugin_add"
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 stdout = child.stdout.as_mut().expect("Failed to open stdout");
let _ = BufReader::new(stdout);
let request: JsonRpc<std::vec::Vec<Value>> = JsonRpc::new("quit", vec![]);
let mut reader = BufReader::new(stdout);
let request: JsonRpc<std::vec::Vec<Value>> = JsonRpc::new("end_filter", vec![]);
let request_raw = serde_json::to_string(&request).unwrap();
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");

View File

@ -15,6 +15,10 @@ pub trait Plugin {
Err(ShellError::string("`filter` not implemented in plugin"))
}
#[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 quit(&mut self) {
@ -42,6 +46,10 @@ pub fn serve_plugin(plugin: &mut dyn Plugin) {
Ok(NuCommand::filter { params }) => {
send_response(plugin.filter(params));
}
Ok(NuCommand::end_filter) => {
send_response(plugin.end_filter());
}
Ok(NuCommand::sink { params }) => {
plugin.sink(params.0, params.1);
return;
@ -79,6 +87,9 @@ pub fn serve_plugin(plugin: &mut dyn Plugin) {
Ok(NuCommand::filter { params }) => {
send_response(plugin.filter(params));
}
Ok(NuCommand::end_filter) => {
send_response(plugin.end_filter());
}
Ok(NuCommand::sink { params }) => {
plugin.sink(params.0, params.1);
break;
@ -140,6 +151,7 @@ pub enum NuCommand {
filter {
params: Spanned<Value>,
},
end_filter,
sink {
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;
#[test]
fn can_convert_table_to_csv_text_and_from_csv_text_back_into_table() {
nu!(output,
nu!(
output,
cwd("tests/fixtures/formats"),
"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");
}
#[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]
fn can_filter_by_unit_size_comparison() {
nu!(

View File

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

View File

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