From 47628946b6ebbfe5ef7615a4fd226aad213f2499 Mon Sep 17 00:00:00 2001 From: JT <547158+jntrnr@users.noreply.github.com> Date: Tue, 9 Nov 2021 14:59:44 +1300 Subject: [PATCH] Add `str collect` (#311) * Add str collect * Oops, missing file --- crates/nu-command/src/default_context.rs | 12 ++- crates/nu-command/src/example_test.rs | 4 +- .../src/strings/str_/case/command.rs | 10 +- .../nu-command/src/strings/str_/case/mod.rs | 12 +-- crates/nu-command/src/strings/str_/collect.rs | 95 +++++++++++++++++++ crates/nu-command/src/strings/str_/mod.rs | 2 + 6 files changed, 117 insertions(+), 18 deletions(-) create mode 100644 crates/nu-command/src/strings/str_/collect.rs diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index 900457641d..2d65bb5e86 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -25,7 +25,6 @@ pub fn create_default_context() -> EngineState { Alias, Benchmark, BuildString, - CamelCase, Cd, Collect, Cp, @@ -49,7 +48,6 @@ pub fn create_default_context() -> EngineState { FromJson, Get, Griddle, - KebabCase, Help, Hide, If, @@ -83,7 +81,6 @@ pub fn create_default_context() -> EngineState { Mkdir, Module, Mv, - PascalCase, ParEach, Ps, Range, @@ -92,12 +89,17 @@ pub fn create_default_context() -> EngineState { Select, Shuffle, Size, - ScreamingSnakeCase, - SnakeCase, Split, SplitChars, SplitColumn, SplitRow, + Str, + StrCamelCase, + StrCollect, + StrKebabCase, + StrPascalCase, + StrScreamingSnakeCase, + StrSnakeCase, Sys, Table, To, diff --git a/crates/nu-command/src/example_test.rs b/crates/nu-command/src/example_test.rs index d11ada8a0e..7e1f39069f 100644 --- a/crates/nu-command/src/example_test.rs +++ b/crates/nu-command/src/example_test.rs @@ -7,7 +7,7 @@ use nu_protocol::{ use crate::To; -use super::{Case, Date, From, Into, Math, Split}; +use super::{Date, From, Into, Math, Split, Str}; pub fn test_examples(cmd: impl Command + 'static) { let examples = cmd.examples(); @@ -17,7 +17,7 @@ pub fn test_examples(cmd: impl Command + 'static) { // Base functions that are needed for testing // Try to keep this working set small to keep tests running as fast as possible let mut working_set = StateWorkingSet::new(&*engine_state); - working_set.add_decl(Box::new(Case)); + working_set.add_decl(Box::new(Str)); working_set.add_decl(Box::new(From)); working_set.add_decl(Box::new(To)); working_set.add_decl(Box::new(Into)); diff --git a/crates/nu-command/src/strings/str_/case/command.rs b/crates/nu-command/src/strings/str_/case/command.rs index 80714cbd77..40c038c7a3 100644 --- a/crates/nu-command/src/strings/str_/case/command.rs +++ b/crates/nu-command/src/strings/str_/case/command.rs @@ -6,9 +6,9 @@ use nu_protocol::{ }; #[derive(Clone)] -pub struct Case; +pub struct Str; -impl Command for Case { +impl Command for Str { fn name(&self) -> &str { "str" } @@ -18,7 +18,7 @@ impl Command for Case { } fn usage(&self) -> &str { - "Converts strings into different kind of cases: camel, kebab, pascal, snake, and screaming snake." + "Various commands for working with string data." } fn run( @@ -29,7 +29,7 @@ impl Command for Case { _input: PipelineData, ) -> Result { Ok(Value::String { - val: get_full_help(&Case.signature(), &Case.examples(), engine_state), + val: get_full_help(&Str.signature(), &Str.examples(), engine_state), span: call.head, } .into_pipeline_data()) @@ -44,6 +44,6 @@ mod test { fn test_examples() { use crate::test_examples; - test_examples(Case {}) + test_examples(Str {}) } } diff --git a/crates/nu-command/src/strings/str_/case/mod.rs b/crates/nu-command/src/strings/str_/case/mod.rs index 129674fe3e..0d26d6c2ee 100644 --- a/crates/nu-command/src/strings/str_/case/mod.rs +++ b/crates/nu-command/src/strings/str_/case/mod.rs @@ -5,12 +5,12 @@ pub mod pascal_case; pub mod screaming_snake_case; pub mod snake_case; -pub use camel_case::SubCommand as CamelCase; -pub use command::Case; -pub use kebab_case::SubCommand as KebabCase; -pub use pascal_case::SubCommand as PascalCase; -pub use screaming_snake_case::SubCommand as ScreamingSnakeCase; -pub use snake_case::SubCommand as SnakeCase; +pub use camel_case::SubCommand as StrCamelCase; +pub use command::Str; +pub use kebab_case::SubCommand as StrKebabCase; +pub use pascal_case::SubCommand as StrPascalCase; +pub use screaming_snake_case::SubCommand as StrScreamingSnakeCase; +pub use snake_case::SubCommand as StrSnakeCase; use nu_engine::CallExt; diff --git a/crates/nu-command/src/strings/str_/collect.rs b/crates/nu-command/src/strings/str_/collect.rs new file mode 100644 index 0000000000..156c49fe72 --- /dev/null +++ b/crates/nu-command/src/strings/str_/collect.rs @@ -0,0 +1,95 @@ +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, +}; + +#[derive(Clone)] +pub struct StrCollect; + +impl Command for StrCollect { + fn name(&self) -> &str { + "str collect" + } + + fn signature(&self) -> Signature { + Signature::build("str collect").optional( + "separator", + SyntaxShape::String, + "optional separator to use when creating string", + ) + } + + fn usage(&self) -> &str { + "creates a string from the input, optionally using a separator" + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let separator: Option = call.opt(engine_state, stack, 0)?; + + #[allow(clippy::needless_collect)] + let strings: Vec> = + input.into_iter().map(|value| value.as_string()).collect(); + let strings: Result, _> = strings.into_iter().collect::>(); + + match strings { + Ok(strings) => { + let output = if let Some(separator) = separator { + strings.join(&separator) + } else { + strings.join("") + }; + + Ok(Value::String { + val: output, + span: call.head, + } + .into_pipeline_data()) + } + _ => Err(ShellError::CantConvert( + "string".into(), + "non-string input".into(), + call.head, + )), + } + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Create a string from input", + example: "['nu', 'shell'] | str collect", + result: Some(Value::String { + val: "nushell".to_string(), + span: Span::unknown(), + }), + }, + Example { + description: "Create a string from input with a separator", + example: "['nu', 'shell'] | str collect '-'", + result: Some(Value::String { + val: "nu-shell".to_string(), + span: Span::unknown(), + }), + }, + ] + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(StrCollect {}) + } +} diff --git a/crates/nu-command/src/strings/str_/mod.rs b/crates/nu-command/src/strings/str_/mod.rs index a8f9c53892..ee1f107861 100644 --- a/crates/nu-command/src/strings/str_/mod.rs +++ b/crates/nu-command/src/strings/str_/mod.rs @@ -1,3 +1,5 @@ mod case; +mod collect; pub use case::*; +pub use collect::*;