From ef56d482b2c26996c2ffb59de98989838ac5f0e1 Mon Sep 17 00:00:00 2001 From: Stefan Stanciulescu Date: Sun, 31 Oct 2021 22:53:37 +0100 Subject: [PATCH 1/3] Port first command to engine-q --- crates/nu-command/src/default_context.rs | 1 + crates/nu-command/src/filters/first.rs | 86 ++++++++++++++++++++++++ crates/nu-command/src/filters/mod.rs | 2 + 3 files changed, 89 insertions(+) create mode 100644 crates/nu-command/src/filters/first.rs diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index 32cb38aa89..452c33f7c7 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -32,6 +32,7 @@ pub fn create_default_context() -> EngineState { Each, ExportDef, External, + First, For, From, FromJson, diff --git a/crates/nu-command/src/filters/first.rs b/crates/nu-command/src/filters/first.rs new file mode 100644 index 0000000000..68e121adb2 --- /dev/null +++ b/crates/nu-command/src/filters/first.rs @@ -0,0 +1,86 @@ +use nu_engine::CallExt; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{Example, IntoPipelineData, PipelineData, Signature, Span, SyntaxShape, Value}; + +#[derive(Clone)] +pub struct First; + +impl Command for First { + fn name(&self) -> &str { + "first" + } + + fn signature(&self) -> Signature { + Signature::build("first").optional( + "rows", + SyntaxShape::Int, + "starting from the front, the number of rows to return", + ) + } + + fn usage(&self) -> &str { + "Show only the first number of rows." + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + first_helper(engine_state, stack, call, input) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Return the first item of a list/table", + example: "[1 2 3] | first", + result: Some(Value::List { + vals: vec![Value::test_int(1)], + span: Span::unknown(), + }), + }, + Example { + description: "Return the first 2 items of a list/table", + example: "[1 2 3] | first 2", + result: Some(Value::List { + vals: vec![Value::test_int(1), Value::test_int(2)], + span: Span::unknown(), + }), + }, + ] + } +} + +fn first_helper( + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, +) -> Result { + let rows: Option = call.opt(engine_state, stack, 0)?; + let rows_desired: usize = match rows { + Some(x) => x as usize, + None => 1, + }; + + Ok(Value::List { + vals: input.into_iter().take(rows_desired).collect(), + span: call.head, + } + .into_pipeline_data()) +} + +#[cfg(test)] +mod test { + use super::*; + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(First {}) + } +} diff --git a/crates/nu-command/src/filters/mod.rs b/crates/nu-command/src/filters/mod.rs index f322ca3092..34796069de 100644 --- a/crates/nu-command/src/filters/mod.rs +++ b/crates/nu-command/src/filters/mod.rs @@ -1,4 +1,5 @@ mod each; +mod first; mod get; mod last; mod length; @@ -10,6 +11,7 @@ mod where_; mod wrap; pub use each::Each; +pub use first::First; pub use get::Get; pub use last::Last; pub use length::Length; From 6e49d0f84bd0495f1be3073a6c836aa47be523e3 Mon Sep 17 00:00:00 2001 From: Stefan Stanciulescu Date: Tue, 2 Nov 2021 09:05:03 +0100 Subject: [PATCH 2/3] Fix first command to display the first item not as a table --- crates/nu-command/src/filters/first.rs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/crates/nu-command/src/filters/first.rs b/crates/nu-command/src/filters/first.rs index 68e121adb2..10b778068c 100644 --- a/crates/nu-command/src/filters/first.rs +++ b/crates/nu-command/src/filters/first.rs @@ -1,7 +1,9 @@ use nu_engine::CallExt; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EngineState, Stack}; -use nu_protocol::{Example, IntoPipelineData, PipelineData, Signature, Span, SyntaxShape, Value}; +use nu_protocol::{ + Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, SyntaxShape, Value, +}; #[derive(Clone)] pub struct First; @@ -61,17 +63,26 @@ fn first_helper( call: &Call, input: PipelineData, ) -> Result { + let head = call.head; let rows: Option = call.opt(engine_state, stack, 0)?; let rows_desired: usize = match rows { Some(x) => x as usize, None => 1, }; - Ok(Value::List { - vals: input.into_iter().take(rows_desired).collect(), - span: call.head, + if rows_desired == 1 { + let mut input_peek = input.into_iter().peekable(); + match input_peek.next() { + Some(val) => Ok(val.into_pipeline_data()), + None => Err(ShellError::AccessBeyondEndOfStream(head)), + } + } else { + Ok(Value::List { + vals: input.into_iter().take(rows_desired).collect(), + span: head, + } + .into_pipeline_data()) } - .into_pipeline_data()) } #[cfg(test)] From ce54764bea9847f814017dacdfe39a46acce5cae Mon Sep 17 00:00:00 2001 From: Stefan Stanciulescu Date: Tue, 2 Nov 2021 09:06:51 +0100 Subject: [PATCH 3/3] Fix test case for first command --- crates/nu-command/src/filters/first.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/nu-command/src/filters/first.rs b/crates/nu-command/src/filters/first.rs index 10b778068c..873e07026c 100644 --- a/crates/nu-command/src/filters/first.rs +++ b/crates/nu-command/src/filters/first.rs @@ -40,10 +40,7 @@ impl Command for First { Example { description: "Return the first item of a list/table", example: "[1 2 3] | first", - result: Some(Value::List { - vals: vec![Value::test_int(1)], - span: Span::unknown(), - }), + result: Some(Value::test_int(1)), }, Example { description: "Return the first 2 items of a list/table",