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(),