diff --git a/src/gleam/regexp.gleam b/src/gleam/regexp.gleam index c88738e..a7a99ec 100644 --- a/src/gleam/regexp.gleam +++ b/src/gleam/regexp.gleam @@ -226,12 +226,12 @@ pub fn replace( /// /// ```gleam /// let assert Ok(re) = regexp.from_string("\\w+") -/// regexp.replace_map(re, "hello, joe!", fn(m) { string.capitalise(m.content) }) +/// regexp.match_map(re, "hello, joe!", fn(m) { string.capitalise(m.content) }) /// // -> "Hello, Joe!" /// ``` -@external(erlang, "gleam_regexp_ffi", "replace_map") -@external(javascript, "../gleam_regexp_ffi.mjs", "replace_map") -pub fn replace_map( +@external(erlang, "gleam_regexp_ffi", "match_map") +@external(javascript, "../gleam_regexp_ffi.mjs", "match_map") +pub fn match_map( each pattern: Regexp, in string: String, with substitute: fn(Match) -> String, diff --git a/src/gleam_regexp_ffi.erl b/src/gleam_regexp_ffi.erl index 07b71a5..977b3d3 100644 --- a/src/gleam_regexp_ffi.erl +++ b/src/gleam_regexp_ffi.erl @@ -1,6 +1,6 @@ -module(gleam_regexp_ffi). --export([compile/2, check/2, split/2, replace/3, scan/2, replace_map/3]). +-export([compile/2, check/2, split/2, replace/3, scan/2, match_map/3]). compile(String, Options) -> {options, Caseless, Multiline} = Options, @@ -44,9 +44,9 @@ scan(Regexp, String) -> replace(Regexp, Subject, Replacement) -> re:replace(Subject, Regexp, Replacement, [global, {return, binary}]). -replace_map(Regexp, Subject, Replacement) -> +match_map(Regexp, Subject, Replacement) -> Replacement1 = fun(Content, Submatches) -> - Submatches1 = gleam@list:map(Submatches, fun gleam@string:to_option/1), + Submatches1 = lists:map(fun gleam@string:to_option/1, Submatches), Replacement({match, Content, Submatches1}) end, re:replace(Subject, Regexp, Replacement1, [global, {return, binary}]). diff --git a/src/gleam_regexp_ffi.mjs b/src/gleam_regexp_ffi.mjs index b1e41e2..726d635 100644 --- a/src/gleam_regexp_ffi.mjs +++ b/src/gleam_regexp_ffi.mjs @@ -31,17 +31,7 @@ export function split(regex, string) { export function scan(regex, string) { const matches = Array.from(string.matchAll(regex)).map((match) => { const content = match[0]; - const submatches = []; - for (let n = match.length - 1; n > 0; n--) { - if (match[n]) { - submatches[n - 1] = new Some(match[n]); - continue; - } - if (submatches.length > 0) { - submatches[n - 1] = new None(); - } - } - return new RegexMatch(content, List.fromArray(submatches)); + return new RegexMatch(content, submatches(match.slice(1))); }); return List.fromArray(matches); } @@ -50,22 +40,26 @@ export function replace(regex, original_string, replacement) { return original_string.replaceAll(regex, replacement); } -export function replace_map(regex, original_string, replacement) { +export function match_map(regex, original_string, replacement) { let replace = (match, ...args) => { const hasNamedGroups = typeof args.at(-1) === "object"; const groups = args.slice(0, hasNamedGroups ? -3 : -2); - const submatches = []; - for (let n = 0; n < groups.length; n++) { - if (groups[n]) { - submatches[n] = new Some(groups[n]); - continue; - } - if (submatches.length > 0) { - submatches[n] = new None(); - } - } - let regexMatch = new RegexMatch(match, List.fromArray(submatches)); + let regexMatch = new RegexMatch(match, submatches(groups)); return replacement(regexMatch); }; return original_string.replaceAll(regex, replace); } + +function submatches(groups) { + const submatches = []; + for (let n = groups.length - 1; n >= 0; n--) { + if (groups[n]) { + submatches[n] = new Some(groups[n]); + continue; + } + if (submatches.length > 0) { + submatches[n] = new None(); + } + } + return List.fromArray(submatches); +} diff --git a/test/gleam_regexp_test.gleam b/test/gleam_regexp_test.gleam index 877aa42..4f02dc6 100644 --- a/test/gleam_regexp_test.gleam +++ b/test/gleam_regexp_test.gleam @@ -191,7 +191,7 @@ pub fn replace_3_test() { |> should.equal("🐕🐕 are great!") } -pub fn replace_map_0_test() { +pub fn match_map_0_test() { let replace = fn(match: Match) { case match.content { "1" -> "one" @@ -201,11 +201,11 @@ pub fn replace_map_0_test() { } } let assert Ok(re) = regexp.from_string("1|2|3") - regexp.replace_map(re, "1, 2, 3, 4", replace) + regexp.match_map(re, "1, 2, 3, 4", replace) |> should.equal("one, two, three, 4") } -pub fn replace_map_1_test() { +pub fn match_map_1_test() { let replace = fn(match: Match) { case match.submatches { [Some("1")] -> "one" @@ -215,6 +215,6 @@ pub fn replace_map_1_test() { } } let assert Ok(re) = regexp.from_string("'(1|2|3)'") - regexp.replace_map(re, "'1', '2', '3', '4'", replace) + regexp.match_map(re, "'1', '2', '3', '4'", replace) |> should.equal("one, two, three, '4'") }