diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index f7a49007c0..626a7ab32a 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -43,6 +43,7 @@ pub fn create_default_context() -> EngineState { IntoBinary, IntoFilesize, IntoInt, + Last, Length, Let, LetEnv, diff --git a/crates/nu-command/src/filters/last.rs b/crates/nu-command/src/filters/last.rs new file mode 100644 index 0000000000..a878076801 --- /dev/null +++ b/crates/nu-command/src/filters/last.rs @@ -0,0 +1,85 @@ +use nu_engine::CallExt; + +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{ + Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, +}; +use std::convert::TryInto; + +#[derive(Clone)] +pub struct Last; + +impl Command for Last { + fn name(&self) -> &str { + "last" + } + + fn signature(&self) -> Signature { + Signature::build("last").optional( + "rows", + SyntaxShape::Int, + "starting from the back, the number of rows to return", + ) + } + + fn usage(&self) -> &str { + "Show only the last number of rows." + } + + fn examples(&self) -> Vec { + vec![Example { + example: "[1,2,3] | last 2", + description: "Get the last 2 items", + result: Some(Value::List { + vals: vec![Value::test_int(2), Value::test_int(3)], + 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 beginning_rows_to_skip = rows_to_skip(vlen, rows); + + let iter = v + .into_iter() + .skip(beginning_rows_to_skip.try_into().unwrap()); + + Ok(iter.into_pipeline_data()) + } +} + +fn rows_to_skip(count: i64, rows: Option) -> i64 { + let end_rows_desired = if let Some(quantity) = rows { + quantity + } else { + 1 + }; + + if end_rows_desired < count { + count - end_rows_desired + } else { + 0 + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(Last {}) + } +} diff --git a/crates/nu-command/src/filters/mod.rs b/crates/nu-command/src/filters/mod.rs index bb87c7944b..595fe396cd 100644 --- a/crates/nu-command/src/filters/mod.rs +++ b/crates/nu-command/src/filters/mod.rs @@ -1,5 +1,6 @@ mod each; mod get; +mod last; mod length; mod lines; mod par_each; @@ -9,6 +10,7 @@ mod wrap; pub use each::Each; pub use get::Get; +pub use last::Last; pub use length::Length; pub use lines::Lines; pub use par_each::ParEach;