From 44595b44c5c1e5ecea85d4aa7a3bd058b43e763f Mon Sep 17 00:00:00 2001 From: pwygab <88221256+merelymyself@users.noreply.github.com> Date: Sun, 26 Feb 2023 20:48:09 +0800 Subject: [PATCH] add case insensitive switch to starts-with and ends-with (#8221) # Description Fixes #8202 # User-Facing Changes `str starts-with` and `str ends-with` now has a `-i` switch. # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. --- .../nu-command/src/strings/str_/ends_with.rs | 17 ++++++++++- .../src/strings/str_/starts_with.rs | 28 ++++++++++++++++--- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/crates/nu-command/src/strings/str_/ends_with.rs b/crates/nu-command/src/strings/str_/ends_with.rs index b490a40219..1edaccb31a 100644 --- a/crates/nu-command/src/strings/str_/ends_with.rs +++ b/crates/nu-command/src/strings/str_/ends_with.rs @@ -9,6 +9,7 @@ use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShap struct Arguments { substring: String, cell_paths: Option>, + case_insensitive: bool, } impl CmdArgument for Arguments { @@ -35,6 +36,7 @@ impl Command for SubCommand { SyntaxShape::CellPath, "For a data structure input, check strings at the given cell paths, and replace with result", ) + .switch("ignore-case", "search is case insensitive", Some('i')) .category(Category::Strings) } @@ -58,6 +60,7 @@ impl Command for SubCommand { let args = Arguments { substring: call.req::(engine_state, stack, 0)?, cell_paths, + case_insensitive: call.has_flag("ignore-case"), }; operate(action, args, input, call.head, engine_state.ctrlc.clone()) } @@ -74,13 +77,25 @@ impl Command for SubCommand { example: "'my_library.rb' | str ends-with '.txt'", result: Some(Value::test_bool(false)), }, + Example { + description: "Checks if string ends with '.RB', case-insensitive", + example: "'my_library.rb' | str ends-with -i '.RB'", + result: Some(Value::test_bool(true)), + }, ] } } fn action(input: &Value, args: &Arguments, head: Span) -> Value { match input { - Value::String { val, .. } => Value::boolean(val.ends_with(&args.substring), head), + Value::String { val: s, .. } => { + let ends_with = if args.case_insensitive { + s.to_lowercase().ends_with(&args.substring.to_lowercase()) + } else { + s.ends_with(&args.substring) + }; + Value::boolean(ends_with, head) + } Value::Error { .. } => input.clone(), _ => Value::Error { error: ShellError::OnlySupportsThisInputType( diff --git a/crates/nu-command/src/strings/str_/starts_with.rs b/crates/nu-command/src/strings/str_/starts_with.rs index 4a50b967fb..bc43923d78 100644 --- a/crates/nu-command/src/strings/str_/starts_with.rs +++ b/crates/nu-command/src/strings/str_/starts_with.rs @@ -10,6 +10,7 @@ use nu_protocol::{Example, PipelineData, ShellError, Signature, Span, SyntaxShap struct Arguments { substring: String, cell_paths: Option>, + case_insensitive: bool, } impl CmdArgument for Arguments { @@ -37,6 +38,7 @@ impl Command for SubCommand { SyntaxShape::CellPath, "For a data structure input, check strings at the given cell paths, and replace with result", ) + .switch("ignore-case", "search is case insensitive", Some('i')) .category(Category::Strings) } @@ -61,6 +63,7 @@ impl Command for SubCommand { let args = Arguments { substring: substring.item, cell_paths, + case_insensitive: call.has_flag("ignore-case"), }; operate(action, args, input, call.head, engine_state.ctrlc.clone()) } @@ -73,23 +76,40 @@ impl Command for SubCommand { result: Some(Value::test_bool(true)), }, Example { - description: "Checks if input string starts with 'my'", + description: "Checks if input string starts with 'Car'", example: "'Cargo.toml' | str starts-with 'Car'", result: Some(Value::test_bool(true)), }, Example { - description: "Checks if input string starts with 'my'", + description: "Checks if input string starts with '.toml'", example: "'Cargo.toml' | str starts-with '.toml'", result: Some(Value::test_bool(false)), }, + Example { + description: "Checks if input string starts with 'cargo', case-insensitive", + example: "'Cargo.toml' | str starts-with -i 'cargo'", + result: Some(Value::test_bool(true)), + }, ] } } -fn action(input: &Value, Arguments { substring, .. }: &Arguments, head: Span) -> Value { +fn action( + input: &Value, + Arguments { + substring, + case_insensitive, + .. + }: &Arguments, + head: Span, +) -> Value { match input { Value::String { val: s, .. } => { - let starts_with = s.starts_with(substring); + let starts_with = if *case_insensitive { + s.to_lowercase().starts_with(&substring.to_lowercase()) + } else { + s.starts_with(substring) + }; Value::boolean(starts_with, head) } Value::Error { .. } => input.clone(),