From d799438181ecce625471a59477bd86bf17ad7654 Mon Sep 17 00:00:00 2001 From: David Sancho Moreno Date: Tue, 15 Aug 2023 11:08:52 +0200 Subject: [PATCH] Implement Js.String2.replaceByRe --- packages/js/dune | 2 +- packages/js/js.ml | 34 +++++++++++++++++++++++++++++++++- packages/js/test.ml | 14 ++++++++------ 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/packages/js/dune b/packages/js/dune index 52c8ae2fe..1c439eee2 100644 --- a/packages/js/dune +++ b/packages/js/dune @@ -12,4 +12,4 @@ (modules test) (libraries alcotest alcotest-lwt lwt server-reason-react.js) (preprocess - (pps lwt_ppx))) + (pps lwt_ppx regex_ppx))) diff --git a/packages/js/js.ml b/packages/js/js.ml index 246d7c5a6..0117ceb92 100644 --- a/packages/js/js.ml +++ b/packages/js/js.ml @@ -457,6 +457,7 @@ module Re = struct let substrings = Pcre.exec ~rex ~pos:regexp.lastIndex str in let _, lastIndex = Pcre.get_substring_ofs substrings 0 in regexp.lastIndex <- lastIndex; + print_endline @@ string_of_int regexp.lastIndex; Some { substrings } with Not_found -> None @@ -809,7 +810,38 @@ module String2 = struct repeat' str "" count let replace _ _ _ = notImplemented "Js.String2" "replace" - let replaceByRe _ _ _ = notImplemented "Js.String2" "replaceByRe" + + let replaceByRe pattern replacement str = + let rec replace_all str = + match Re.exec_ pattern str with + | None -> str + | Some result -> + Re.setLastIndex pattern 0; + let matches = Re.matches result in + let matched_str = Stdlib.Array.get matches 0 in + let prefix = Stdlib.String.sub str 0 (Re.index result) in + let suffix_start = Re.index result + String.length matched_str in + let suffix = + Stdlib.String.sub str suffix_start (String.length str - suffix_start) + in + prefix ^ replacement ^ replace_all suffix + in + let replace_first str = + match Re.exec_ pattern str with + | None -> str + | Some result -> + let matches = Re.matches result in + let matched_str = Stdlib.Array.get matches 0 in + let prefix = Stdlib.String.sub str 0 (Re.index result) in + let suffix_start = Re.index result + String.length matched_str in + let suffix = + Stdlib.String.sub str suffix_start (String.length str - suffix_start) + in + prefix ^ replacement ^ suffix + in + + if Re.global pattern then replace_all str else replace_first str + let unsafeReplaceBy0 _ _ = notImplemented "Js.String2" "unsafeReplaceBy0" let unsafeReplaceBy1 _ _ = notImplemented "Js.String2" "unsafeReplaceBy1" let unsafeReplaceBy2 _ _ = notImplemented "Js.String2" "unsafeReplaceBy2" diff --git a/packages/js/test.ml b/packages/js/test.ml index 2002054b4..9469eed81 100644 --- a/packages/js/test.ml +++ b/packages/js/test.ml @@ -231,13 +231,15 @@ let string2_tests = "this cat and the dog" *) ()); case "replaceByRe" (fun () -> + assert_string (Js.String2.replaceByRe [%re "/d/"] "x" "david") "xavid" (* assert_string - (replaceByRe [%re "/[aeiou]/g"] "x" "vowels be gone") - "vxwxls bx gxnx"; - assert_string - (replaceByRe [%re "/(\\w+) (\\w+)/"] "$2, $1" "Juan Fulano") - "Fulano, Juan" *) - ()); + (Js.String2.replaceByRe [%re "/(\\w+) (\\w+)/"] "$2, $1" + "Juan Fulano") + "Fulano, Juan" *)); + case "replaceByRe with global" (fun () -> + assert_string + (Js.String2.replaceByRe [%re "/[aeiou]/g"] "x" "vowels be gone") + "vxwxls bx gxnx"); case "unsafeReplaceBy0" (fun () -> (* let str = "beautiful vowels" in let re = [%re "/[aeiou]/g"] in