From 8390cc97e1b8f0f5144468795c3f8b0634604490 Mon Sep 17 00:00:00 2001 From: Sebastian Jung Date: Mon, 2 Dec 2019 20:15:14 +0100 Subject: [PATCH 1/4] add range command --- src/cli.rs | 1 + src/commands.rs | 2 + src/commands/range.rs | 87 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 src/commands/range.rs diff --git a/src/cli.rs b/src/cli.rs index 386d16734f..557b187932 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -332,6 +332,7 @@ pub async fn cli() -> Result<(), Box> { whole_stream_command(What), whole_stream_command(Which), whole_stream_command(Debug), + whole_stream_command(Range), ]); cfg_if::cfg_if! { diff --git a/src/commands.rs b/src/commands.rs index 705deb1d56..c6c252dded 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -61,6 +61,7 @@ pub(crate) mod prepend; pub(crate) mod prev; pub(crate) mod pwd; #[allow(unused)] +pub(crate) mod range; pub(crate) mod reduce_by; pub(crate) mod reject; pub(crate) mod reverse; @@ -151,6 +152,7 @@ pub(crate) use prepend::Prepend; pub(crate) use prev::Previous; pub(crate) use pwd::PWD; #[allow(unused)] +pub(crate) use range::Range; pub(crate) use reduce_by::ReduceBy; pub(crate) use reject::Reject; pub(crate) use reverse::Reverse; diff --git a/src/commands/range.rs b/src/commands/range.rs new file mode 100644 index 0000000000..e71f731f78 --- /dev/null +++ b/src/commands/range.rs @@ -0,0 +1,87 @@ +use crate::commands::WholeStreamCommand; +use crate::errors::ShellError; +use crate::context::CommandRegistry; +use crate::prelude::*; +use nu_source::Tagged; + +#[derive(Deserialize)] +struct RangeArgs { + area: Tagged, +} + +pub struct Range; + +impl WholeStreamCommand for Range { + fn name(&self) -> &str { + "range" + } + + fn signature(&self) -> Signature { + Signature::build("range").required( + "rows ", + SyntaxShape::Any, + "range of rows to return: Eg) 4..7 (=> from 4 to 7)", + ) + } + + fn usage(&self) -> &str { + "Return only the selected rows" + } + + fn run( + &self, + args: CommandArgs, + registry: &CommandRegistry, + ) -> Result { + args.process(registry, range)?.run() + } +} + +fn range( + RangeArgs { area: rows }: RangeArgs, + RunnableContext { input, name, .. }: RunnableContext, +) -> Result { + match rows.item.find(".") { + Some(value) => { + let (first, last) = rows.item.split_at(value); + let first = match first.parse::() { + Ok(postion) => postion, + Err(_) => { + if first == "" { + 0 + } else { + return Err(ShellError::labeled_error( + "no correct start of range", + "'from' needs to be an Integer or empty", + name, + )); + } + }, + }; + let last = match last.trim_start_matches(".").parse::() { + Ok(postion) => postion, + Err(_) => { + if last == ".." { + std::u64::MAX + } else { + return Err(ShellError::labeled_error( + "no correct end of range", + "'to' needs to be an Integer or empty", + name, + )); + } + }, + }; + return Ok(OutputStream::from_input( + input.values.skip(first).take(last-first+1), + )); + }, + None => { + return Err(ShellError::labeled_error( + "No correct formated range found", + "format: ..", + name, + )); + } + } +} \ No newline at end of file From 201506a5ad400630a811f49643878710c164792e Mon Sep 17 00:00:00 2001 From: Sebastian Jung Date: Tue, 3 Dec 2019 08:24:49 +0100 Subject: [PATCH 2/4] add tests for range + run rustfmt --- src/commands/range.rs | 18 +++++------ tests/commands_test.rs | 68 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 9 deletions(-) diff --git a/src/commands/range.rs b/src/commands/range.rs index e71f731f78..8a31c1c0e2 100644 --- a/src/commands/range.rs +++ b/src/commands/range.rs @@ -1,6 +1,6 @@ use crate::commands::WholeStreamCommand; -use crate::errors::ShellError; use crate::context::CommandRegistry; +use crate::errors::ShellError; use crate::prelude::*; use nu_source::Tagged; @@ -40,7 +40,7 @@ impl WholeStreamCommand for Range { fn range( RangeArgs { area: rows }: RangeArgs, RunnableContext { input, name, .. }: RunnableContext, -) -> Result { +) -> Result { match rows.item.find(".") { Some(value) => { let (first, last) = rows.item.split_at(value); @@ -56,13 +56,13 @@ fn range( name, )); } - }, + } }; let last = match last.trim_start_matches(".").parse::() { Ok(postion) => postion, Err(_) => { if last == ".." { - std::u64::MAX + std::u64::MAX - 1 } else { return Err(ShellError::labeled_error( "no correct end of range", @@ -70,18 +70,18 @@ fn range( name, )); } - }, + } }; return Ok(OutputStream::from_input( - input.values.skip(first).take(last-first+1), + input.values.skip(first).take(last - first + 1), )); - }, + } None => { return Err(ShellError::labeled_error( - "No correct formated range found", + "No correct formatted range found", "format: ..", name, )); } } -} \ No newline at end of file +} diff --git a/tests/commands_test.rs b/tests/commands_test.rs index 89ab430b36..776998e633 100644 --- a/tests/commands_test.rs +++ b/tests/commands_test.rs @@ -204,6 +204,74 @@ fn group_by_errors_if_unknown_column_name() { }) } +#[test] +fn range_selects_a_row() { + Playground::setup("range_test_1", |dirs, sandbox| { + sandbox.with_files(vec![EmptyFile("notes.txt"), EmptyFile("tests.txt")]); + + let actual = nu!( + cwd: dirs.test(), h::pipeline( + r#" + ls + | sort-by name + | range 0..0 + | get name + | echo $it + "# + )); + + assert_eq!(actual, "notes.txt"); + }); +} + +#[test] +fn range_selects_some_rows() { + Playground::setup("range_test_2", |dirs, sandbox| { + sandbox.with_files(vec![ + EmptyFile("notes.txt"), + EmptyFile("tests.txt"), + EmptyFile("persons.txt"), + ]); + + let actual = nu!( + cwd: dirs.test(), h::pipeline( + r#" + ls + | get name + | range 1..2 + | count + | echo $it + "# + )); + + assert_eq!(actual, "2"); + }); +} + +#[test] +fn range_selects_all_rows() { + Playground::setup("range_test_3", |dirs, sandbox| { + sandbox.with_files(vec![ + EmptyFile("notes.txt"), + EmptyFile("tests.txt"), + EmptyFile("persons.txt"), + ]); + + let actual = nu!( + cwd: dirs.test(), h::pipeline( + r#" + ls + | get name + | range .. + | count + | echo $it + "# + )); + + assert_eq!(actual, "3"); + }); +} + #[test] fn split_by() { Playground::setup("split_by_test_1", |dirs, sandbox| { From ecebe1314a2a46789062beaa5d0a4398b0d47174 Mon Sep 17 00:00:00 2001 From: Sebastian Jung Date: Tue, 3 Dec 2019 20:56:39 +0100 Subject: [PATCH 3/4] update to new crates structure --- src/commands/range.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/commands/range.rs b/src/commands/range.rs index 8a31c1c0e2..c110e21fac 100644 --- a/src/commands/range.rs +++ b/src/commands/range.rs @@ -1,7 +1,8 @@ use crate::commands::WholeStreamCommand; use crate::context::CommandRegistry; -use crate::errors::ShellError; use crate::prelude::*; +use nu_errors::ShellError; +use nu_protocol::{Signature, SyntaxShape}; use nu_source::Tagged; #[derive(Deserialize)] From 59510a85d14855e718678d7c56c2dbbb33a094ef Mon Sep 17 00:00:00 2001 From: Sebastian Jung Date: Wed, 4 Dec 2019 17:13:21 +0100 Subject: [PATCH 4/4] fix build warnings --- src/commands.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands.rs b/src/commands.rs index c46862bed7..899ac967c0 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -60,8 +60,8 @@ pub(crate) mod post; pub(crate) mod prepend; pub(crate) mod prev; pub(crate) mod pwd; -#[allow(unused)] pub(crate) mod range; +#[allow(unused)] pub(crate) mod reduce_by; pub(crate) mod reject; pub(crate) mod reverse; @@ -150,8 +150,8 @@ pub(crate) use post::Post; pub(crate) use prepend::Prepend; pub(crate) use prev::Previous; pub(crate) use pwd::PWD; -#[allow(unused)] pub(crate) use range::Range; +#[allow(unused)] pub(crate) use reduce_by::ReduceBy; pub(crate) use reject::Reject; pub(crate) use reverse::Reverse;