Repository: casey/just (rust)

Issue:
Add a replace function that supports regex
The current `replace(s, from, to)` function doesn't seem to support regex. I think it would be helpful to also have a `replace_regex(s, from, to)` for more complex replacements.

Pull request description:
Add a replace function that supports regex
Add `replace_regex(s, from, to)` that supports replacing text using regular expressions.

Closes #1389.

Patch:
diff --git a/README.md b/README.md
index 4126db5f..0196a9f5 100644
--- a/README.md
+++ b/README.md
@@ -1145,6 +1145,7 @@ The executable is at: /bin/just
 
 - `quote(s)` - Replace all single quotes with `'\''` and prepend and append single quotes to `s`. This is sufficient to escape special characters for many shells, including most Bourne shell descendants.
 - `replace(s, from, to)` - Replace all occurrences of `from` in `s` to `to`.
+- `replace_regex(s, regex, replacement)` - Replace all occurrences of `regec` in `s` to `replacement`.
 - `trim(s)` - Remove leading and trailing whitespace from `s`.
 - `trim_end(s)` - Remove trailing whitespace from `s`.
 - `trim_end_match(s, pat)` - Remove suffix of `s` matching `pat`.
diff --git a/src/function.rs b/src/function.rs
index 461384fb..18f000b2 100644
--- a/src/function.rs
+++ b/src/function.rs
@@ -43,6 +43,7 @@ lazy_static! {
     ("path_exists", Unary(path_exists)),
     ("quote", Unary(quote)),
     ("replace", Ternary(replace)),
+    ("replace_regex", Ternary(replace_regex)),
     ("sha256", Unary(sha256)),
     ("sha256_file", Unary(sha256_file)),
     ("shoutykebabcase", Unary(shoutykebabcase)),
@@ -283,6 +284,20 @@ fn replace(_context: &FunctionContext, s: &str, from: &str, to: &str) -> Result<
   Ok(s.replace(from, to))
 }
 
+fn replace_regex(
+  _context: &FunctionContext,
+  s: &str,
+  regex: &str,
+  replacement: &str,
+) -> Result<String, String> {
+  Ok(
+    Regex::new(regex)
+      .map_err(|err| err.to_string())?
+      .replace_all(s, replacement)
+      .to_string(),
+  )
+}
+
 fn sha256(_context: &FunctionContext, s: &str) -> Result<String, String> {
   use sha2::{Digest, Sha256};
   let mut hasher = Sha256::new();


Test patch:
diff --git a/tests/functions.rs b/tests/functions.rs
index 6a7ae0c5..97472b34 100644
--- a/tests/functions.rs
+++ b/tests/functions.rs
@@ -373,6 +373,34 @@ test! {
   stderr: "echo foofoofoo\n",
 }
 
+test! {
+  name: replace_regex,
+  justfile: "
+    foo:
+      echo {{ replace_regex('123bar123bar123bar', '\\d+bar', 'foo') }}
+  ",
+  stdout: "foofoofoo\n",
+  stderr: "echo foofoofoo\n",
+}
+
+test! {
+  name: invalid_replace_regex,
+  justfile: "
+    foo:
+      echo {{ replace_regex('barbarbar', 'foo\\', 'foo') }}
+  ",
+  stderr:
+"error: Call to function `replace_regex` failed: regex parse error:
+    foo\\
+       ^
+error: incomplete escape sequence, reached end of pattern prematurely
+  |
+2 |   echo {{ replace_regex('barbarbar', 'foo\\', 'foo') }}
+  |           ^^^^^^^^^^^^^
+",
+  status: EXIT_FAILURE,
+}
+
 test! {
     name: capitalize,
     justfile: "