diff --git a/Cargo.toml b/Cargo.toml index 4ec79ea426..e91b6d15b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -154,14 +154,6 @@ path = "src/plugins/average.rs" name = "nu_plugin_embed" path = "src/plugins/embed.rs" -[[bin]] -name = "nu_plugin_insert" -path = "src/plugins/insert.rs" - -[[bin]] -name = "nu_plugin_edit" -path = "src/plugins/edit.rs" - [[bin]] name = "nu_plugin_format" path = "src/plugins/format.rs" diff --git a/src/cli.rs b/src/cli.rs index 0677634321..0daed4e1fd 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -288,6 +288,8 @@ pub async fn cli() -> Result<(), Box> { per_item_command(Post), per_item_command(Where), per_item_command(Echo), + per_item_command(Edit), + per_item_command(Insert), whole_stream_command(Config), whole_stream_command(Compact), whole_stream_command(Default), diff --git a/src/commands.rs b/src/commands.rs index 899ac967c0..5e7b3814f8 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -19,6 +19,7 @@ pub(crate) mod date; pub(crate) mod debug; pub(crate) mod default; pub(crate) mod echo; +pub(crate) mod edit; pub(crate) mod enter; pub(crate) mod env; #[allow(unused)] @@ -43,6 +44,7 @@ pub(crate) mod group_by; pub(crate) mod help; pub(crate) mod histogram; pub(crate) mod history; +pub(crate) mod insert; pub(crate) mod last; pub(crate) mod lines; pub(crate) mod ls; @@ -108,6 +110,7 @@ pub(crate) use date::Date; pub(crate) use debug::Debug; pub(crate) use default::Default; pub(crate) use echo::Echo; +pub(crate) use edit::Edit; pub(crate) use enter::Enter; pub(crate) use env::Env; #[allow(unused)] @@ -134,6 +137,7 @@ pub(crate) use group_by::GroupBy; pub(crate) use help::Help; pub(crate) use histogram::Histogram; pub(crate) use history::History; +pub(crate) use insert::Insert; pub(crate) use last::Last; pub(crate) use lines::Lines; pub(crate) use ls::LS; diff --git a/src/commands/edit.rs b/src/commands/edit.rs new file mode 100644 index 0000000000..f9ae988f68 --- /dev/null +++ b/src/commands/edit.rs @@ -0,0 +1,174 @@ +use crate::commands::PerItemCommand; +use crate::context::CommandRegistry; +use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{CallInfo, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; + +pub struct Edit; + +impl PerItemCommand for Edit { + fn name(&self) -> &str { + "edit" + } + + fn signature(&self) -> Signature { + Signature::build("edit") + .required( + "Field", + SyntaxShape::ColumnPath, + "the name of the column to edit", + ) + .required( + "Value", + SyntaxShape::String, + "the new value to give the cell(s)", + ) + } + + fn usage(&self) -> &str { + "Edit an existing column to have a new value." + } + + fn run( + &self, + call_info: &CallInfo, + _registry: &CommandRegistry, + _raw_args: &RawCommandArgs, + value: Value, + ) -> Result { + let value_tag = value.tag(); + let field = call_info.args.expect_nth(0)?.as_column_path().unwrap(); + let replacement = call_info.args.expect_nth(1)?.tagged_unknown(); + + let stream = match value { + obj @ Value { + value: UntaggedValue::Row(_), + .. + } => match obj.replace_data_at_column_path(&field, replacement.item.clone()) { + Some(v) => VecDeque::from(vec![Ok(ReturnSuccess::Value(v))]), + None => { + return Err(ShellError::labeled_error( + "edit could not find place to insert column", + "column name", + &field.tag, + )) + } + }, + + _ => { + return Err(ShellError::labeled_error( + "Unrecognized type in stream", + "original value", + value_tag, + )) + } + }; + + Ok(stream.to_output_stream()) + } +} + +/* +use nu::{serve_plugin, Plugin, ValueExt}; +use nu_errors::ShellError; +use nu_protocol::{ + CallInfo, ColumnPath, Primitive, ReturnSuccess, ReturnValue, Signature, SpannedTypeName, + SyntaxShape, UntaggedValue, Value, +}; +use nu_source::Tagged; + +struct Edit { + field: Option>, + value: Option, +} +impl Edit { + fn new() -> Edit { + Edit { + field: None, + value: None, + } + } + + fn edit(&self, value: Value) -> Result { + let value_tag = value.tag(); + match (value, self.value.clone()) { + ( + obj @ Value { + value: UntaggedValue::Row(_), + .. + }, + Some(v), + ) => match &self.field { + Some(f) => { + match obj.replace_data_at_column_path(&f, v.clone().into_untagged_value()) { + Some(v) => return Ok(v), + None => { + return Err(ShellError::labeled_error( + "edit could not find place to insert column", + "column name", + &f.tag, + )) + } + } + } + None => Err(ShellError::untagged_runtime_error( + "edit needs a column when changing a value in a table", + )), + }, + _ => Err(ShellError::labeled_error( + "Unrecognized type in stream", + "original value", + value_tag, + )), + } + } +} + +impl Plugin for Edit { + fn config(&mut self) -> Result { + Ok(Signature::build("edit") + .desc("Edit an existing column to have a new value.") + .required( + "Field", + SyntaxShape::ColumnPath, + "the name of the column to edit", + ) + .required( + "Value", + SyntaxShape::String, + "the new value to give the cell(s)", + ) + .filter()) + } + + fn begin_filter(&mut self, call_info: CallInfo) -> Result, ShellError> { + if let Some(args) = call_info.args.positional { + match &args[0] { + table @ Value { + value: UntaggedValue::Primitive(Primitive::ColumnPath(_)), + .. + } => { + self.field = Some(table.as_column_path()?); + } + value => return Err(ShellError::type_error("table", value.spanned_type_name())), + } + + match &args[1] { + Value { value: v, .. } => { + self.value = Some(v.clone()); + } + } + } + + Ok(vec![]) + } + + fn filter(&mut self, input: Value) -> Result, ShellError> { + Ok(vec![ReturnSuccess::value(self.edit(input)?)]) + } +} + +fn main() { + serve_plugin(&mut Edit::new()); +} +*/ diff --git a/src/plugins/edit.rs b/src/commands/insert.rs similarity index 63% rename from src/plugins/edit.rs rename to src/commands/insert.rs index 91e6ee5437..dfbe7ccdb3 100644 --- a/src/plugins/edit.rs +++ b/src/commands/insert.rs @@ -1,3 +1,68 @@ +use crate::commands::PerItemCommand; +use crate::context::CommandRegistry; +use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{CallInfo, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; + +pub struct Insert; + +impl PerItemCommand for Insert { + fn name(&self) -> &str { + "insert" + } + + fn signature(&self) -> Signature { + Signature::build("insert") + .required( + "column", + SyntaxShape::ColumnPath, + "the column name to insert", + ) + .required( + "value", + SyntaxShape::String, + "the value to give the cell(s)", + ) + } + + fn usage(&self) -> &str { + "Edit an existing column to have a new value." + } + + fn run( + &self, + call_info: &CallInfo, + _registry: &CommandRegistry, + _raw_args: &RawCommandArgs, + value: Value, + ) -> Result { + let value_tag = value.tag(); + let field = call_info.args.expect_nth(0)?.as_column_path().unwrap(); + let replacement = call_info.args.expect_nth(1)?.tagged_unknown(); + + let stream = match value { + obj @ Value { + value: UntaggedValue::Row(_), + .. + } => match obj.insert_data_at_column_path(&field, replacement.item.clone()) { + Ok(v) => VecDeque::from(vec![Ok(ReturnSuccess::Value(v))]), + Err(err) => return Err(err), + }, + + _ => { + return Err(ShellError::labeled_error( + "Unrecognized type in stream", + "original value", + value_tag, + )) + } + }; + + Ok(stream.to_output_stream()) + } +} + +/* use nu::{serve_plugin, Plugin, ValueExt}; use nu_errors::ShellError; use nu_protocol::{ @@ -100,3 +165,4 @@ impl Plugin for Edit { fn main() { serve_plugin(&mut Edit::new()); } +*/ diff --git a/src/plugins/insert.rs b/src/plugins/insert.rs deleted file mode 100644 index 9f99bcfb15..0000000000 --- a/src/plugins/insert.rs +++ /dev/null @@ -1,84 +0,0 @@ -use nu::{serve_plugin, Plugin, ValueExt}; -use nu_errors::ShellError; -use nu_protocol::{ - CallInfo, ColumnPath, Primitive, ReturnSuccess, ReturnValue, ShellTypeName, Signature, - SpannedTypeName, SyntaxShape, UntaggedValue, Value, -}; -use nu_source::SpannedItem; - -struct Insert { - field: Option, - value: Option, -} -impl Insert { - fn new() -> Insert { - Insert { - field: None, - value: None, - } - } - - fn insert(&self, value: Value) -> Result { - let value_tag = value.tag(); - - match (&value, &self.value, &self.field) { - ( - obj @ Value { - value: UntaggedValue::Row(_), - .. - }, - Some(v), - Some(field), - ) => obj.clone().insert_data_at_column_path(field, v.clone()), - (value, ..) => Err(ShellError::type_error( - "row", - value.type_name().spanned(value_tag), - )), - } - } -} - -impl Plugin for Insert { - fn config(&mut self) -> Result { - Ok(Signature::build("insert") - .desc("Insert a new column to the table.") - .required( - "column", - SyntaxShape::ColumnPath, - "the column name to insert", - ) - .required( - "value", - SyntaxShape::String, - "the value to give the cell(s)", - ) - .filter()) - } - - fn begin_filter(&mut self, call_info: CallInfo) -> Result, ShellError> { - if let Some(args) = call_info.args.positional { - match &args[0] { - table @ Value { - value: UntaggedValue::Primitive(Primitive::ColumnPath(_)), - .. - } => { - self.field = Some(table.as_column_path()?.item); - } - - value => return Err(ShellError::type_error("table", value.spanned_type_name())), - } - - self.value = Some(args[1].clone()); - } - - Ok(vec![]) - } - - fn filter(&mut self, input: Value) -> Result, ShellError> { - Ok(vec![ReturnSuccess::value(self.insert(input)?)]) - } -} - -fn main() { - serve_plugin(&mut Insert::new()); -}