From 4dc1042c1d1e84da025e3f69d647815249ab8b18 Mon Sep 17 00:00:00 2001 From: Ade Attwood Date: Sat, 11 May 2024 10:39:22 +0100 Subject: [PATCH 1/2] test: add regex feature tests --- tests/features.rs | 2 +- tests/features/regex.feature | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 tests/features/regex.feature diff --git a/tests/features.rs b/tests/features.rs index 4b8c7bf..fb4ad95 100644 --- a/tests/features.rs +++ b/tests/features.rs @@ -24,5 +24,5 @@ fn assert_output(world: &mut TestWorld, expected: String) { } fn main() { - futures::executor::block_on(TestWorld::run("tests/features/basic.feature")); + futures::executor::block_on(TestWorld::run("tests/features")); } diff --git a/tests/features/regex.feature b/tests/features/regex.feature new file mode 100644 index 0000000..cc77786 --- /dev/null +++ b/tests/features/regex.feature @@ -0,0 +1,19 @@ +Feature: Regex search and replace + + Scenario: You can search and replace with with a regular expression + Given Search is '(\w+)' + And Replace is 'new' + And Input is 'This is a' + Then Output is 'new new new' + + Scenario: You can use a '$' to replace a match group + Given Search is 'function (\w+)\(\)' + And Replace is 'fun $1()' + And Input is 'function foo()' + Then Output is 'fun foo()' + + Scenario: You can will need to wrap the match group when the match is against another word + Given Search is 'Hello (\w+)' + And Replace is 'Hello ${1}s' + And Input is 'Hello world' + Then Output is 'Hello worlds' From bb03e0976444c1d53f7b115507c9860f5e91ec89 Mon Sep 17 00:00:00 2001 From: Ade Attwood Date: Sat, 11 May 2024 15:20:43 +0100 Subject: [PATCH 2/2] feat: add case preserving search and replace --- Cargo.lock | 11 +++++++++++ Cargo.toml | 1 + src/lib.rs | 22 +++++++++++++++++++--- tests/features/case-perserving.feature | 7 +++++++ tests/features/regex.feature | 2 +- 5 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 tests/features/case-perserving.feature diff --git a/Cargo.lock b/Cargo.lock index a7d341b..1f1de34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -196,6 +196,16 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +[[package]] +name = "cruet" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6132609543972496bc97b1e01f1ce6586768870aeb4cabeb3385f4e05b5caead" +dependencies = [ + "once_cell", + "regex", +] + [[package]] name = "cucumber" version = "0.20.2" @@ -272,6 +282,7 @@ name = "dev_case" version = "0.1.0" dependencies = [ "clap", + "cruet", "cucumber", "futures", "regex", diff --git a/Cargo.toml b/Cargo.toml index 6dcf58d..2b53e87 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] clap = { version = "4.5.4", features = ["derive"] } +cruet = "0.14.0" regex = "1.10.4" [dev-dependencies] diff --git a/src/lib.rs b/src/lib.rs index 3da331f..ee75c56 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,23 @@ use regex::Regex; +fn concert_replacement(original: &str, replacement: &str) -> String { + if cruet::is_camel_case(original) { + cruet::to_camel_case(replacement) + } else if cruet::is_kebab_case(original) { + cruet::to_kebab_case(replacement) + } else if cruet::is_pascal_case(original) { + cruet::to_pascal_case(replacement) + } else if cruet::is_snake_case(original) { + cruet::to_snake_case(replacement) + } else { + replacement.to_string() + } +} + pub fn replace(search: &String, replace: String, input: String) -> String { let mut index = 0; let mut output = input; - let search_pattern = Regex::new(search).unwrap(); + let search_pattern = Regex::new(&format!("(?i){search}")).unwrap(); while let Some(search_match) = search_pattern.find_at(&output, index) { let start = search_match.start(); @@ -19,8 +33,10 @@ pub fn replace(search: &String, replace: String, input: String) -> String { } }; - index = start + replacement.len(); - output.replace_range(start..end, &replacement); + let converted_replacement = concert_replacement(&output[start..end], &replacement); + output.replace_range(start..end, &converted_replacement); + + index = start + converted_replacement.len(); } output diff --git a/tests/features/case-perserving.feature b/tests/features/case-perserving.feature new file mode 100644 index 0000000..00a3655 --- /dev/null +++ b/tests/features/case-perserving.feature @@ -0,0 +1,7 @@ +Feature: Case preserving search and replace + + Scenario: You can search and replace with with a regular expression + Given Search is 'productid' + And Replace is 'catalogId' + And Input is 'function GetProductId(productId)' + Then Output is 'function GetCatalogId(catalogId)' diff --git a/tests/features/regex.feature b/tests/features/regex.feature index cc77786..0e07ec5 100644 --- a/tests/features/regex.feature +++ b/tests/features/regex.feature @@ -3,7 +3,7 @@ Feature: Regex search and replace Scenario: You can search and replace with with a regular expression Given Search is '(\w+)' And Replace is 'new' - And Input is 'This is a' + And Input is 'this is a' Then Output is 'new new new' Scenario: You can use a '$' to replace a match group