diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index 99e8f9741..9121ef05d 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -40,6 +40,7 @@ pub fn create_default_context() -> EngineState { Def, Describe, Do, + Drop, Each, Echo, ExportCommand, diff --git a/crates/nu-command/src/filters/drop/command.rs b/crates/nu-command/src/filters/drop/command.rs new file mode 100644 index 000000000..78b4515f5 --- /dev/null +++ b/crates/nu-command/src/filters/drop/command.rs @@ -0,0 +1,109 @@ +use nu_engine::CallExt; + +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{ + Category, Example, IntoInterruptiblePipelineData, PipelineData, ShellError, Signature, Span, + SyntaxShape, Value, +}; +use std::convert::TryInto; + +#[derive(Clone)] +pub struct Drop; + +impl Command for Drop { + fn name(&self) -> &str { + "drop" + } + + fn signature(&self) -> Signature { + Signature::build("drop") + .optional( + "rows", + SyntaxShape::Int, + "starting from the back, the number of rows to remove", + ) + .category(Category::Filters) + } + + fn usage(&self) -> &str { + "Remove the last number of rows or columns." + } + + fn examples(&self) -> Vec { + vec![ + Example { + example: "[0,1,2,3] | drop", + description: "Remove the last item of a list/table", + result: Some(Value::List { + vals: vec![Value::test_int(0), Value::test_int(1), Value::test_int(2)], + span: Span::unknown(), + }), + }, + Example { + example: "[0,1,2,3] | drop 0", + description: "Remove zero item of a list/table", + result: Some(Value::List { + vals: vec![ + Value::test_int(0), + Value::test_int(1), + Value::test_int(2), + Value::test_int(3), + ], + span: Span::unknown(), + }), + }, + Example { + example: "[0,1,2,3] | drop 2", + description: "Remove the last two items of a list/table", + result: Some(Value::List { + vals: vec![Value::test_int(0), Value::test_int(1)], + span: Span::unknown(), + }), + }, + ] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let rows: Option = call.opt(engine_state, stack, 0)?; + let v: Vec<_> = input.into_iter().collect(); + let vlen: i64 = v.len() as i64; + + let rows_to_drop = if let Some(quantity) = rows { + quantity + } else { + 1 + }; + + if rows_to_drop == 0 { + Ok(v.into_iter().into_pipeline_data(engine_state.ctrlc.clone())) + } else { + let k = if vlen < rows_to_drop { + 0 + } else { + vlen - rows_to_drop + }; + + let iter = v.into_iter().take(k.try_into().unwrap()); + Ok(iter.into_pipeline_data(engine_state.ctrlc.clone())) + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(Drop {}) + } +} diff --git a/crates/nu-command/src/filters/drop/mod.rs b/crates/nu-command/src/filters/drop/mod.rs new file mode 100644 index 000000000..70dd1f6fa --- /dev/null +++ b/crates/nu-command/src/filters/drop/mod.rs @@ -0,0 +1,3 @@ +pub mod command; + +pub use command::Drop; diff --git a/crates/nu-command/src/filters/mod.rs b/crates/nu-command/src/filters/mod.rs index b5a21af22..aba51e488 100644 --- a/crates/nu-command/src/filters/mod.rs +++ b/crates/nu-command/src/filters/mod.rs @@ -1,5 +1,6 @@ mod append; mod collect; +mod drop; mod each; mod first; mod get; @@ -18,6 +19,7 @@ mod zip; pub use append::Append; pub use collect::Collect; +pub use drop::*; pub use each::Each; pub use first::First; pub use get::Get;