Skip to content

Commit

Permalink
Implement Js.String2.replaceByRe
Browse files Browse the repository at this point in the history
  • Loading branch information
davesnx committed Aug 15, 2023
1 parent a70e0c3 commit d799438
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 8 deletions.
2 changes: 1 addition & 1 deletion packages/js/dune
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@
(modules test)
(libraries alcotest alcotest-lwt lwt server-reason-react.js)
(preprocess
(pps lwt_ppx)))
(pps lwt_ppx regex_ppx)))
34 changes: 33 additions & 1 deletion packages/js/js.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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"
Expand Down
14 changes: 8 additions & 6 deletions packages/js/test.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit d799438

Please sign in to comment.