diff --git a/src/cli.rs b/src/cli.rs index 28fef9556..a04a6211b 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -168,6 +168,8 @@ pub async fn cli() -> Result<(), Box> { whole_stream_command(SortBy), whole_stream_command(Tags), whole_stream_command(First), + whole_stream_command(Last), + whole_stream_command(FromArray), whole_stream_command(FromArray), whole_stream_command(FromCSV), whole_stream_command(FromINI), diff --git a/src/commands.rs b/src/commands.rs index 19995ab7a..3728474f2 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -22,6 +22,7 @@ crate mod from_toml; crate mod from_xml; crate mod from_yaml; crate mod get; +crate mod last; crate mod lines; crate mod ls; crate mod mkdir; @@ -76,6 +77,7 @@ crate use from_toml::FromTOML; crate use from_xml::FromXML; crate use from_yaml::FromYAML; crate use get::Get; +crate use last::Last; crate use lines::Lines; crate use ls::LS; crate use mkdir::Mkdir; diff --git a/src/commands/last.rs b/src/commands/last.rs new file mode 100644 index 000000000..18a2da96a --- /dev/null +++ b/src/commands/last.rs @@ -0,0 +1,59 @@ +use crate::commands::WholeStreamCommand; +use crate::errors::ShellError; +use crate::parser::CommandRegistry; +use crate::prelude::*; + +pub struct Last; + +impl WholeStreamCommand for Last { + fn run( + &self, + args: CommandArgs, + registry: &CommandRegistry, + ) -> Result { + last(args, registry) + } + + fn name(&self) -> &str { + "last" + } + + fn signature(&self) -> Signature { + Signature::build("last").required("amount", SyntaxType::Literal) + } +} + +fn last(args: CommandArgs, registry: &CommandRegistry) -> Result { + let args = args.evaluate_once(registry)?; + + let amount = args.expect_nth(0)?.as_i64(); + + let amount = match amount { + Ok(o) => o, + Err(_) => { + return Err(ShellError::labeled_error( + "Value is not a number", + "expected integer", + args.expect_nth(0)?.span(), + )) + } + }; + + if amount <= 0 { + return Err(ShellError::labeled_error( + "Value is too low", + "expected a positive integer", + args.expect_nth(0)?.span(), + )) + } + + let stream = async_stream_block! { + let v: Vec<_> = args.input.into_vec().await; + let k = v.len() - (amount as usize); + for x in v[k..].iter() { + let y: Tagged = x.clone(); + yield ReturnSuccess::value(y) + } + }; + Ok(stream.to_output_stream()) +} diff --git a/tests/filters_test.rs b/tests/filters_test.rs index 20eba8050..c2678b22b 100644 --- a/tests/filters_test.rs +++ b/tests/filters_test.rs @@ -100,3 +100,14 @@ fn can_filter_by_unit_size_comparison() { assert_eq!(output, "caco3_plastics.csv"); } + +#[test] +fn can_get_last() { + nu!( + output, + cwd("tests/fixtures/formats"), + "ls | sort-by name | last 1 | get name | trim | echo $it" + ); + + assert_eq!(output, "utf16.ini"); +}