From 772f8598dde95d5da3d4a1b9e15b97d735af6311 Mon Sep 17 00:00:00 2001 From: Fernando Herrera Date: Thu, 23 Sep 2021 20:03:08 +0100 Subject: [PATCH] lines command --- crates/nu-command/src/default_context.rs | 4 +- crates/nu-command/src/lib.rs | 2 + crates/nu-command/src/lines.rs | 83 ++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 crates/nu-command/src/lines.rs diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index 91c13590f6..5890d791cb 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -7,7 +7,7 @@ use nu_protocol::{ use crate::{ where_::Where, Alias, Benchmark, BuildString, Def, Do, Each, External, For, Git, GitCheckout, - If, Length, Let, LetEnv, ListGitBranches, Ls, Table, + If, Length, Let, LetEnv, Lines, ListGitBranches, Ls, Table, }; pub fn create_default_context() -> Rc> { @@ -50,6 +50,8 @@ pub fn create_default_context() -> Rc> { working_set.add_decl(Box::new(External)); + working_set.add_decl(Box::new(Lines)); + // This is a WIP proof of concept working_set.add_decl(Box::new(ListGitBranches)); working_set.add_decl(Box::new(Git)); diff --git a/crates/nu-command/src/lib.rs b/crates/nu-command/src/lib.rs index 96f0839fb3..1f150c2c65 100644 --- a/crates/nu-command/src/lib.rs +++ b/crates/nu-command/src/lib.rs @@ -12,6 +12,7 @@ mod if_; mod length; mod let_; mod let_env; +mod lines; mod list_git_branches; mod ls; mod run_external; @@ -32,6 +33,7 @@ pub use if_::If; pub use length::Length; pub use let_::Let; pub use let_env::LetEnv; +pub use lines::Lines; pub use list_git_branches::ListGitBranches; pub use ls::Ls; pub use run_external::External; diff --git a/crates/nu-command/src/lines.rs b/crates/nu-command/src/lines.rs new file mode 100644 index 0000000000..a8cbdea64d --- /dev/null +++ b/crates/nu-command/src/lines.rs @@ -0,0 +1,83 @@ +use std::cell::RefCell; +use std::rc::Rc; + +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::{Signature, Span, Value, ValueStream}; + +pub struct Lines; + +const SPLIT_CHAR: char = '\n'; + +impl Command for Lines { + fn name(&self) -> &str { + "lines" + } + + fn usage(&self) -> &str { + "Converts input to lines" + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("lines") + } + + fn run( + &self, + _context: &EvaluationContext, + _call: &Call, + input: Value, + ) -> Result { + let value = match input { + Value::String { val, span } => { + let iter = val + .split(SPLIT_CHAR) + .map(|s| Value::String { + val: s.into(), + span, + }) + .collect::>(); // <----- how to avoid collecting? + + Value::Stream { + stream: ValueStream(Rc::new(RefCell::new(iter.into_iter()))), + span: Span::unknown(), + } + } + Value::Stream { stream, span: _ } => { + let iter = stream + .into_iter() + .filter_map(|value| { + if let Value::String { val, span } = value { + let inner = val + .split(SPLIT_CHAR) + .filter_map(|s| { + if !s.is_empty() { + Some(Value::String { + val: s.into(), + span, + }) + } else { + None + } + }) + .collect::>(); + + Some(inner) + } else { + None + } + }) + .flatten() + .collect::>(); // <----- how to avoid collecting? + + Value::Stream { + stream: ValueStream(Rc::new(RefCell::new(iter.into_iter()))), + span: Span::unknown(), + } + } + _ => unimplemented!(), + }; + + Ok(value) + } +}