diff --git a/src/cli.rs b/src/cli.rs index 5da609a3f..8165c8747 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -181,14 +181,11 @@ pub async fn cli() -> Result<(), Box> { command("to-toml", Box::new(to_toml::to_toml)), command("sort-by", Box::new(sort_by::sort_by)), command("sort-by", Box::new(sort_by::sort_by)), - command("inc", |x| plugin::plugin("inc".into(), x)), - command("sum", |x| plugin::plugin("sum".into(), x)), Arc::new(Open), Arc::new(Where), Arc::new(Config), Arc::new(SkipWhile), Arc::new(Enter), - Arc::new(Skip), ]); context.add_sinks(vec![ diff --git a/src/commands.rs b/src/commands.rs index 20121eb3f..322592348 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -44,6 +44,5 @@ crate use command::command; crate use config::Config; crate use enter::Enter; crate use open::Open; -crate use skip::Skip; crate use skip_while::SkipWhile; crate use where_::Where; diff --git a/src/commands/autoview.rs b/src/commands/autoview.rs index 55b4b4292..e9f6599f8 100644 --- a/src/commands/autoview.rs +++ b/src/commands/autoview.rs @@ -5,7 +5,11 @@ use crate::prelude::*; pub fn autoview(args: SinkCommandArgs) -> Result<(), ShellError> { if args.input.len() > 0 { - if let Value::Binary(_) = args.input[0] { + if let Spanned { + item: Value::Binary(_), + .. + } = args.input[0] + { args.ctx.get_sink("binaryview").run(args)?; } else if equal_shapes(&args.input) { args.ctx.get_sink("table").run(args)?; diff --git a/src/commands/enter.rs b/src/commands/enter.rs index 7fd557f6d..9dc105324 100644 --- a/src/commands/enter.rs +++ b/src/commands/enter.rs @@ -12,8 +12,12 @@ impl Command for Enter { fn config(&self) -> CommandConfig { CommandConfig { name: self.name().to_string(), - positional: vec![PositionalType::mandatory("path", "Block")], + positional: vec![PositionalType::mandatory_block("path")], rest_positional: false, + can_load: vec![], + can_save: vec![], + is_filter: false, + is_sink: false, named: indexmap::IndexMap::new(), } } @@ -89,9 +93,15 @@ pub fn enter(args: CommandArgs) -> Result { } }; - stream.push_back(Ok(ReturnSuccess::Action(CommandAction::Enter( - parse_as_value(file_extension, contents, contents_span, span)?, - )))); + match contents { + Value::Primitive(Primitive::String(string)) => { + stream.push_back(Ok(ReturnSuccess::Action(CommandAction::Enter( + parse_as_value(file_extension, string, contents_span, span)?, + )))); + } + + other => stream.push_back(ReturnSuccess::value(other.spanned(contents_span))), + }; Ok(stream.into()) } diff --git a/src/commands/from_json.rs b/src/commands/from_json.rs index f91fa120b..e81d81e28 100644 --- a/src/commands/from_json.rs +++ b/src/commands/from_json.rs @@ -27,7 +27,7 @@ fn convert_json_value_to_nu_value(v: &serde_hjson::Value, span: impl Into) serde_hjson::Value::Object(o) => { let mut collected = SpannedDictBuilder::new(span); for (k, v) in o.iter() { - collected.add(k.clone(), convert_json_value_to_nu_value(v, span)); + collected.insert_spanned(k.clone(), convert_json_value_to_nu_value(v, span)); } collected.into_spanned_value() diff --git a/src/commands/from_toml.rs b/src/commands/from_toml.rs index a38058f5e..ffea6fd5d 100644 --- a/src/commands/from_toml.rs +++ b/src/commands/from_toml.rs @@ -25,7 +25,7 @@ fn convert_toml_value_to_nu_value(v: &toml::Value, span: impl Into) -> Spa let mut collected = SpannedDictBuilder::new(span); for (k, v) in t.iter() { - collected.add(k.clone(), convert_toml_value_to_nu_value(v, span)); + collected.insert_spanned(k.clone(), convert_toml_value_to_nu_value(v, span)); } collected.into_spanned_value() diff --git a/src/commands/from_xml.rs b/src/commands/from_xml.rs index 9741592a8..ebfce83e9 100644 --- a/src/commands/from_xml.rs +++ b/src/commands/from_xml.rs @@ -32,8 +32,8 @@ fn from_node_to_value<'a, 'd>( }) .collect(); - let mut collected = Dictionary::default(); - collected.add(name.clone(), Value::List(children_values).spanned(span)); + let mut collected = SpannedDictBuilder::new(span); + collected.insert(name.clone(), Value::List(children_values)); collected.into_spanned_value() } else if n.is_comment() { diff --git a/src/commands/from_yaml.rs b/src/commands/from_yaml.rs index 0568ddce7..3c9de7302 100644 --- a/src/commands/from_yaml.rs +++ b/src/commands/from_yaml.rs @@ -26,7 +26,8 @@ fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value, span: impl Into) for (k, v) in t.iter() { match k { serde_yaml::Value::String(k) => { - collected.add(k.clone(), convert_yaml_value_to_nu_value(v, span)); + collected + .insert_spanned(k.clone(), convert_yaml_value_to_nu_value(v, span)); } _ => unimplemented!("Unknown key type"), } diff --git a/src/commands/macros.rs b/src/commands/macros.rs index 3662378fb..1c5268b67 100644 --- a/src/commands/macros.rs +++ b/src/commands/macros.rs @@ -48,6 +48,11 @@ macro_rules! command { name: self.name().to_string(), positional: vec![$($mandatory_positional)*], rest_positional: false, + can_load: vec![], + can_save: vec![], + is_filter: false, + is_sink: false, + named: { use $crate::parser::registry::NamedType; diff --git a/src/commands/open.rs b/src/commands/open.rs index 14e253d33..f4a024628 100644 --- a/src/commands/open.rs +++ b/src/commands/open.rs @@ -61,12 +61,18 @@ command! { } }; - stream.push_back(ReturnSuccess::value(parse_as_value( - file_extension, - contents, - contents_span, - span, - )?)); + match contents { + Value::Primitive(Primitive::String(string)) => + stream.push_back(ReturnSuccess::value(parse_as_value( + file_extension, + string, + contents_span, + span, + )?) + ), + + other => stream.push_back(ReturnSuccess::value(other.spanned(span))), + }; stream } @@ -76,7 +82,7 @@ pub fn fetch( cwd: &PathBuf, location: &str, span: Span, -) -> Result<(Option, String, Span), ShellError> { +) -> Result<(Option, Value, Span), ShellError> { let mut cwd = cwd.clone(); if location.starts_with("http:") || location.starts_with("https:") { let response = reqwest::get(location); @@ -107,7 +113,7 @@ pub fn fetch( None => path_extension, }; - Ok((extension, s, span)) + Ok((extension, Value::string(s), span)) } Err(_) => { return Err(ShellError::labeled_error( @@ -132,10 +138,10 @@ pub fn fetch( Ok(s) => Ok(( cwd.extension() .map(|name| name.to_string_lossy().to_string()), - s, + Value::string(s), span, )), - Err(_) => Ok((None, Value::Binary(bytes))), + Err(_) => Ok((None, Value::Binary(bytes), span)), }, Err(_) => { return Err(ShellError::labeled_error( diff --git a/src/commands/plugin.rs b/src/commands/plugin.rs index 06cd27a45..291e1f051 100644 --- a/src/commands/plugin.rs +++ b/src/commands/plugin.rs @@ -55,6 +55,7 @@ pub fn filter_plugin(path: String, args: CommandArgs) -> Result Result params, Err(e) => { let mut result = VecDeque::new(); - result.push_back(ReturnValue::Value(Value::Error(Box::new(e)))); + result.push_back(ReturnValue::Err(e)); result } }, diff --git a/src/commands/skip_while.rs b/src/commands/skip_while.rs index ce671eb2a..eebaef83f 100644 --- a/src/commands/skip_while.rs +++ b/src/commands/skip_while.rs @@ -16,7 +16,7 @@ impl Command for SkipWhile { fn config(&self) -> CommandConfig { CommandConfig { name: self.name().to_string(), - positional: vec![PositionalType::mandatory("condition", "Block")], + positional: vec![PositionalType::mandatory_block("condition")], rest_positional: false, named: indexmap::IndexMap::new(), is_filter: true, diff --git a/src/commands/to_json.rs b/src/commands/to_json.rs index d75586c21..0a79ca48c 100644 --- a/src/commands/to_json.rs +++ b/src/commands/to_json.rs @@ -22,7 +22,6 @@ pub fn value_to_json_value(v: &Value) -> serde_json::Value { Value::List(l) => { serde_json::Value::Array(l.iter().map(|x| value_to_json_value(x)).collect()) } - Value::Error(e) => serde_json::Value::String(e.to_string()), Value::Block(_) => serde_json::Value::Null, Value::Binary(b) => serde_json::Value::Array( b.iter() diff --git a/src/commands/to_toml.rs b/src/commands/to_toml.rs index b23ca3519..87cf71ed2 100644 --- a/src/commands/to_toml.rs +++ b/src/commands/to_toml.rs @@ -16,7 +16,6 @@ pub fn value_to_toml_value(v: &Value) -> toml::Value { Value::Filesystem => toml::Value::String("".to_string()), Value::List(l) => toml::Value::Array(l.iter().map(|x| value_to_toml_value(x)).collect()), - Value::Error(e) => toml::Value::String(e.to_string()), Value::Block(_) => toml::Value::String("".to_string()), Value::Binary(b) => { toml::Value::Array(b.iter().map(|x| toml::Value::Integer(*x as i64)).collect()) @@ -38,7 +37,7 @@ pub fn to_toml(args: CommandArgs) -> Result { Ok(out .values .map(move |a| { - match toml::to_string(&a) { + match toml::to_string(&value_to_toml_value(&a)) { Ok(val) => { return ReturnSuccess::value( Value::Primitive(Primitive::String(val)).spanned(name_span), @@ -46,7 +45,7 @@ pub fn to_toml(args: CommandArgs) -> Result { } Err(err) => Err(ShellError::type_error( - "String", + "serializable to toml", format!("{:?} - {:?}", a.type_name(), err).spanned(name_span), )), // toml::Value::String(String) => { // return ReturnSuccess::value( diff --git a/src/format/generic.rs b/src/format/generic.rs index f5fdf0772..4524911da 100644 --- a/src/format/generic.rs +++ b/src/format/generic.rs @@ -36,11 +36,6 @@ impl RenderView for GenericView<'value> { Ok(()) } - Value::Error(e) => { - host.stdout(&format!("{:?}", e)); - Ok(()) - } - Value::Binary(_) => { host.stdout(""); Ok(()) diff --git a/src/object/base.rs b/src/object/base.rs index 04662972a..8b8a5a24d 100644 --- a/src/object/base.rs +++ b/src/object/base.rs @@ -299,10 +299,6 @@ impl Value { } } - crate fn debug(&'a self) -> ValueDebug<'a> { - ValueDebug { value: self } - } - pub fn data_descriptors(&self) -> Vec { match self { Value::Primitive(_) => vec![], @@ -314,7 +310,6 @@ impl Value { .collect(), Value::Block(_) => vec![], Value::List(_) => vec![], - Value::Error(_) => vec![], Value::Filesystem => vec![], Value::Binary(_) => vec![], } @@ -356,7 +351,6 @@ impl Value { Value::Object(o) => o.get_data(desc), Value::Block(_) => MaybeOwned::Owned(Value::nothing()), Value::List(_) => MaybeOwned::Owned(Value::nothing()), - Value::Error(e) => MaybeOwned::Owned(Value::string(&format!("{:#?}", e))), Value::Binary(_) => MaybeOwned::Owned(Value::nothing()), } } @@ -512,7 +506,7 @@ crate fn select_fields(obj: &Value, fields: &[String], span: impl Into) -> let descs = obj.data_descriptors(); for field in fields { - match descs.iter().find(|d| d.name.is_string(field)) { + match descs.iter().find(|d| *d == field) { None => out.insert(field, Value::nothing()), Some(desc) => out.insert(desc.clone(), obj.get_data(desc).borrow().clone()), } diff --git a/src/object/dict.rs b/src/object/dict.rs index ecad28507..e0844dda5 100644 --- a/src/object/dict.rs +++ b/src/object/dict.rs @@ -80,7 +80,7 @@ impl Dictionary { let mut out = Dictionary::default(); for (key, value) in self.entries.iter() { - out.add(key.clone(), value.copy()); + out.add(key.clone(), value.clone()); } out @@ -150,7 +150,7 @@ impl From for Spanned { #[derive(Debug)] pub struct SpannedDictBuilder { span: Span, - dict: IndexMap>, + dict: IndexMap>, } impl SpannedDictBuilder { @@ -161,16 +161,12 @@ impl SpannedDictBuilder { } } - pub fn insert(&mut self, key: impl Into, value: impl Into) { + pub fn insert(&mut self, key: impl Into, value: impl Into) { self.dict .insert(key.into(), value.into().spanned(self.span)); } - pub fn insert_spanned( - &mut self, - key: impl Into, - value: impl Into>, - ) { + pub fn insert_spanned(&mut self, key: impl Into, value: impl Into>) { self.dict.insert(key.into(), value.into()); } diff --git a/src/parser/parse/span.rs b/src/parser/parse/span.rs index fb885e0c6..3886f40e1 100644 --- a/src/parser/parse/span.rs +++ b/src/parser/parse/span.rs @@ -4,22 +4,15 @@ use getset::Getters; use serde::{Serialize, Serializer}; use serde_derive::Deserialize; -#[derive(new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Deserialize, Hash, Getters)] +#[derive( + new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash, Getters, +)] #[get = "crate"] pub struct Spanned { pub span: Span, pub item: T, } -impl Serialize for Spanned { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.item.serialize(serializer) - } -} - impl Spanned { pub fn spanned(self, span: impl Into) -> Spanned { Spanned::from_item(self.item, span.into()) diff --git a/src/parser/registry.rs b/src/parser/registry.rs index d168d9dbb..4447b496c 100644 --- a/src/parser/registry.rs +++ b/src/parser/registry.rs @@ -40,18 +40,19 @@ pub enum PositionalType { Optional(String, PositionalValue), } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub enum PositionalValue { Value, Block, } impl PositionalType { - crate fn mandatory(name: &str, kind: &str) -> PositionalType { - match kind { - "Block" => PositionalType::Mandatory(name.to_string(), PositionalValue::Block), - _ => PositionalType::Mandatory(name.to_string(), PositionalValue::Value), - } + pub fn mandatory(name: &str) -> PositionalType { + PositionalType::Mandatory(name.to_string(), PositionalValue::Value) + } + + pub fn mandatory_block(name: &str) -> PositionalType { + PositionalType::Mandatory(name.to_string(), PositionalValue::Block) } crate fn to_coerce_hint(&self) -> Option { @@ -76,7 +77,7 @@ impl PositionalType { #[get = "crate"] pub struct CommandConfig { pub name: String, - crate positional: Vec, + pub positional: Vec, pub rest_positional: bool, pub named: IndexMap, pub is_filter: bool, diff --git a/src/plugin.rs b/src/plugin.rs index fcf0addde..448912278 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -1,4 +1,4 @@ -use crate::{Args, CommandConfig, ReturnValue, ShellError, Value}; +use crate::{Args, CommandConfig, ReturnValue, ShellError, Spanned, Value}; use serde::{Deserialize, Serialize}; use std::io; @@ -11,11 +11,11 @@ pub trait Plugin { )) } #[allow(unused)] - fn filter(&mut self, input: Value) -> Result, ShellError> { + fn filter(&mut self, input: Spanned) -> Result, ShellError> { Err(ShellError::string("`filter` not implemented in plugin")) } #[allow(unused)] - fn sink(&mut self, args: Args, input: Vec) {} + fn sink(&mut self, args: Args, input: Vec>) {} fn quit(&mut self) { return; @@ -127,7 +127,7 @@ fn send_response(result: T) { pub enum NuCommand { config, begin_filter { params: Args }, - filter { params: Value }, - sink { params: (Args, Vec) }, + filter { params: Spanned }, + sink { params: (Args, Vec>) }, quit, } diff --git a/src/plugins/binaryview.rs b/src/plugins/binaryview.rs index f839d12bc..b96e0e160 100644 --- a/src/plugins/binaryview.rs +++ b/src/plugins/binaryview.rs @@ -1,6 +1,6 @@ use crossterm::{cursor, terminal, Attribute, RawScreen}; use indexmap::IndexMap; -use nu::{serve_plugin, Args, CommandConfig, Plugin, ShellError, Value}; +use nu::{serve_plugin, Args, CommandConfig, Plugin, ShellError, Spanned, Value}; use pretty_hex::*; struct BinaryView; @@ -15,8 +15,7 @@ impl Plugin for BinaryView { fn config(&mut self) -> Result { Ok(CommandConfig { name: "binaryview".to_string(), - mandatory_positional: vec![], - optional_positional: vec![], + positional: vec![], can_load: vec![], can_save: vec![], is_filter: false, @@ -26,10 +25,13 @@ impl Plugin for BinaryView { }) } - fn sink(&mut self, _args: Args, input: Vec) { + fn sink(&mut self, _args: Args, input: Vec>) { for v in input { match v { - Value::Binary(b) => { + Spanned { + item: Value::Binary(b), + .. + } => { let _ = view_binary(&b); } _ => {} diff --git a/src/plugins/inc.rs b/src/plugins/inc.rs index d301ab07e..c9257da13 100644 --- a/src/plugins/inc.rs +++ b/src/plugins/inc.rs @@ -1,11 +1,8 @@ use indexmap::IndexMap; use nu::{ - serve_plugin, Args, CommandConfig, Plugin, PositionalType, Primitive, ReturnValue, ShellError, - Spanned, Value, + serve_plugin, Args, CommandConfig, Plugin, PositionalType, Primitive, ReturnSuccess, + ReturnValue, ShellError, Spanned, SpannedItem, Value, }; -use nu::{Primitive, ReturnSuccess, ReturnValue, ShellError, Spanned, SpannedItem, Value}; -use serde::{Deserialize, Serialize}; -use std::io; struct Inc { inc_by: i64, @@ -16,87 +13,47 @@ impl Inc { } } -fn send_response(result: Vec) { - let response = JsonRpc::new("response", result); - let response_raw = serde_json::to_string(&response).unwrap(); - println!("{}", response_raw); -} - -fn send_error(error: ShellError) { - let message: ReturnValue = Err(error); - send_response(vec![message]) -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(tag = "method")] -#[allow(non_camel_case_types)] -pub enum NuCommand { - init { params: Vec> }, - filter { params: Spanned }, - quit, -} - -fn main() -> Result<(), Box> { - let mut inc_by = 1; - - loop { - let mut input = String::new(); - match io::stdin().read_line(&mut input) { - Ok(_) => { - let command = serde_json::from_str::(&input); - - match command { - Ok(NuCommand::init { params }) => { - for param in params { - match param { - Spanned { - item: Value::Primitive(Primitive::Int(i)), - .. - } => { - inc_by = i; - } - _ => { - send_error(ShellError::string("Unrecognized type in params")); - } - } - } - } - Ok(NuCommand::filter { params }) => match params { - Spanned { - item: Value::Primitive(Primitive::Int(i)), - span, - } => { - send_response(vec![ReturnSuccess::value( - Value::int(i + inc_by).spanned(span), - )]); - } - Spanned { - item: Value::Primitive(Primitive::Bytes(b)), - span, - } => { - send_response(vec![ReturnSuccess::value( - Value::bytes(b + inc_by as u128).spanned(span), - )]); - } - _ => { - send_error(ShellError::string("Unrecognized type in stream")); - } - }, - Ok(NuCommand::quit) => { - break; - } - Err(_) => { - send_error(ShellError::string("Unrecognized type in stream")); +impl Plugin for Inc { + fn config(&mut self) -> Result { + Ok(CommandConfig { + name: "inc".to_string(), + positional: vec![PositionalType::mandatory("Increment")], + can_load: vec![], + can_save: vec![], + is_filter: true, + is_sink: false, + named: IndexMap::new(), + rest_positional: true, + }) + } + fn begin_filter(&mut self, args: Args) -> Result<(), ShellError> { + if let Some(args) = args.positional { + for arg in args { + match arg { + Spanned { + item: Value::Primitive(Primitive::Int(i)), + .. + } => { + self.inc_by = i; } _ => return Err(ShellError::string("Unrecognized type in params")), } } - Err(_) => { - send_error(ShellError::string("Unrecognized type in stream")); - } - Value::Primitive(Primitive::Bytes(b)) => Ok(vec![ReturnValue::Value(Value::bytes( - b + self.inc_by as u64, - ))]), + } + + Ok(()) + } + + fn filter(&mut self, input: Spanned) -> Result, ShellError> { + let span = input.span; + + match input.item { + Value::Primitive(Primitive::Int(i)) => Ok(vec![ReturnSuccess::value( + Value::int(i + self.inc_by).spanned(span), + )]), + Value::Primitive(Primitive::Bytes(b)) => Ok(vec![ReturnSuccess::value( + Value::bytes(b + self.inc_by as u64).spanned(span), + )]), x => Err(ShellError::string(format!( "Unrecognized type in stream: {:?}", x diff --git a/src/plugins/skip.rs b/src/plugins/skip.rs index 14e3a5dee..8fc852a6b 100644 --- a/src/plugins/skip.rs +++ b/src/plugins/skip.rs @@ -1,6 +1,7 @@ use indexmap::IndexMap; use nu::{ - serve_plugin, Args, CommandConfig, Plugin, Primitive, ReturnValue, ShellError, Spanned, Value, + serve_plugin, Args, CommandConfig, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, + Spanned, Value, }; struct NewSkip { @@ -16,8 +17,7 @@ impl Plugin for NewSkip { fn config(&mut self) -> Result { Ok(CommandConfig { name: "skip".to_string(), - mandatory_positional: vec![], - optional_positional: vec![], + positional: vec![], can_load: vec![], can_save: vec![], is_filter: true, @@ -44,9 +44,9 @@ impl Plugin for NewSkip { Ok(()) } - fn filter(&mut self, input: Value) -> Result, ShellError> { + fn filter(&mut self, input: Spanned) -> Result, ShellError> { if self.skip_amount == 0 { - Ok(vec![ReturnValue::Value(input)]) + Ok(vec![ReturnSuccess::value(input)]) } else { self.skip_amount -= 1; Ok(vec![]) diff --git a/src/plugins/tree.rs b/src/plugins/tree.rs index a7a2da86a..9c3f40b8f 100644 --- a/src/plugins/tree.rs +++ b/src/plugins/tree.rs @@ -1,6 +1,6 @@ use derive_new::new; use indexmap::IndexMap; -use nu::{serve_plugin, Args, CommandConfig, Plugin, ShellError, Value}; +use nu::{serve_plugin, Args, CommandConfig, Plugin, ShellError, Spanned, Value}; use ptree::item::StringItem; use ptree::output::print_tree_with; use ptree::print_config::PrintConfig; @@ -31,7 +31,6 @@ impl TreeView { } } Value::Block(_) => {} - Value::Error(_) => {} Value::Filesystem => {} Value::Binary(_) => {} } @@ -85,8 +84,7 @@ impl Plugin for TreeViewer { fn config(&mut self) -> Result { Ok(CommandConfig { name: "tree".to_string(), - mandatory_positional: vec![], - optional_positional: vec![], + positional: vec![], can_load: vec![], can_save: vec![], is_filter: false, @@ -96,12 +94,11 @@ impl Plugin for TreeViewer { }) } - fn sink(&mut self, _args: Args, input: Vec) { + fn sink(&mut self, _args: Args, input: Vec>) { if input.len() > 0 { for i in input.iter() { let view = TreeView::from_value(&i); let _ = view.render_view(); - //handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host)); } }