Summary: When we are using `.*` patterns, this causes an infinite loop. What happens is we are adding text to the end and then replacing that. Its only when we are matching the end of the output string. We can detect this when the starting point is the same as the end point and the match is "" (an empty string). If we hit this condition we can get out and return the output that has been replaced. Test Plan: Test in CI
67 lines
1.9 KiB
Rust
67 lines
1.9 KiB
Rust
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 = match Regex::new(&format!("(?i){search}")) {
|
|
Ok(pattern) => pattern,
|
|
Err(_) => return output,
|
|
};
|
|
|
|
while let Some(search_match) = search_pattern.find_at(&output, index) {
|
|
let start = search_match.start();
|
|
let end = search_match.end();
|
|
|
|
// Prevent an infinite loop. If we hit this condition we will keep adding a new replacement
|
|
// to the end.
|
|
if start == end {
|
|
break;
|
|
}
|
|
|
|
let mut replacement = String::new();
|
|
match search_pattern.captures(&output[start..end]) {
|
|
Some(captures) => {
|
|
captures.expand(&replace, &mut replacement);
|
|
}
|
|
None => {
|
|
replacement.push_str(&replace);
|
|
}
|
|
};
|
|
|
|
let converted_replacement = concert_replacement(&output[start..end], &replacement);
|
|
output.replace_range(start..end, &converted_replacement);
|
|
|
|
index = start + converted_replacement.len();
|
|
}
|
|
|
|
output
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
#[test]
|
|
fn runs_the_search_and_replace() {
|
|
assert_eq!(
|
|
String::from("foo foo"),
|
|
super::replace(
|
|
&String::from(r"\b\w+\b"),
|
|
String::from("foo"),
|
|
String::from("bar baz")
|
|
),
|
|
);
|
|
}
|
|
}
|