diff --git a/jscomp/others/.depend b/jscomp/others/.depend index 30f49d67c1..d85e05e330 100644 --- a/jscomp/others/.depend +++ b/jscomp/others/.depend @@ -55,6 +55,7 @@ belt_SetDict.cmj : belt_internalAVLset.cmj belt_Id.cmj belt_Array.cmj \ belt_SetDict.cmi belt_Map.cmj : belt_MapString.cmj belt_MapInt.cmj belt_MapDict.cmj \ belt_Id.cmj belt_Array.cmj belt_Map.cmi +belt_String.cmj : belt_internalMapInt.cmj : belt_internalAVLtree.cmj belt_SortArray.cmj \ belt_Array.cmj belt_internalMapString.cmj : belt_internalAVLtree.cmj belt_SortArray.cmj \ diff --git a/jscomp/others/belt.ml b/jscomp/others/belt.ml index ae9f1ec8e2..974bcdef1d 100644 --- a/jscomp/others/belt.ml +++ b/jscomp/others/belt.ml @@ -266,6 +266,14 @@ module Int = Belt_Int module Float = Belt_Float +(** {!Belt.String} + + Utilities for String. +*) + +module String = Belt_String + + (** {!Belt.Debug} Utilities for set up debugging diff --git a/jscomp/others/belt_String.ml b/jscomp/others/belt_String.ml new file mode 100644 index 0000000000..c0a18da67c --- /dev/null +++ b/jscomp/others/belt_String.ml @@ -0,0 +1,82 @@ +(* Copyright (C) 2018 Authors of BuckleScript + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * In addition to the permissions granted to you by the LGPL, you may combine + * or link a "work that uses the Library" with a publicly distributed version + * of this file to produce a combined library or application, then distribute + * that combined work under the terms of your choosing, with no requirement + * to comply with the obligations normally placed on you by section 4 of the + * LGPL version 3 (or the corresponding section of a later version of the LGPL + * should you choose to use a later version). + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) + +(** String API *) + +type t = string + +external length : t -> int = "length" [@@bs.get] + +external get : t -> int -> t option = "%array_unsafe_get" + +external concat : t -> t -> t = "concat" [@@bs.send] + +external concatMany : t -> t array -> t = "concat" [@@bs.send] [@@bs.variadic] + +external endsWith : t -> t -> bool = "endsWith" [@@bs.send] + +external indexOf : t -> t -> int = "indexOf" [@@bs.send] + +let indexOf s searchValue = + match indexOf s searchValue with + | -1 -> None + | value -> (Some value) + +external includes : t -> t -> bool = "includes" [@@bs.send] (** ES2015 *) + +external repeat : t -> int -> t = "repeat" [@@bs.send] (** ES2015 *) + +external replace : t -> old:t -> by:t -> t = "replace" [@@bs.send] + +external replaceRegex : t -> old:Js_re.t -> by:t -> t = "replace" [@@bs.send] + +external matchRegex : string -> Js_re.t -> t array option = "match" [@@bs.send] [@@bs.return {null_to_opt}] + +external split : t -> t -> t array = "split" [@@bs.send] + +external splitAtMost: t -> t -> int -> t array = "split" [@@bs.send] + +external startsWith : t -> t -> bool = "startsWith" [@@bs.send] + +external substr : t -> from:int -> len:int -> t = "substr" [@@bs.send] + +external substrToEnd : t -> from:int -> t = "substr" [@@bs.send] + +external slice : t -> from:int -> to_:int -> t = "slice" [@@bs.send] + +external sliceToEnd : t -> from:int -> t = "slice" [@@bs.send] + +external trim : t -> t = "trim" [@@bs.send] + +external trimStart : t -> t = "trimStart" [@@bs.send] (** ES2015 *) + +external trimEnd : t -> t = "trimEnd" [@@bs.send] (** ES2015 *) + +external padStart : t -> int -> t -> t = "padStart" [@@bs.send] (** ES2015 *) + +external padEnd : t -> int -> t -> t = "padEnd" [@@bs.send] (** ES2015 *) + +external toLowerCase : t -> t = "toLowerCase" [@@bs.send] + +external toUpperCase : t -> t = "toUpperCase" [@@bs.send] diff --git a/jscomp/others/belt_String.mli b/jscomp/others/belt_String.mli new file mode 100644 index 0000000000..145a1bed2a --- /dev/null +++ b/jscomp/others/belt_String.mli @@ -0,0 +1,326 @@ +(* Copyright (C) 2018 Authors of BuckleScript + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * In addition to the permissions granted to you by the LGPL, you may combine + * or link a "work that uses the Library" with a publicly distributed version + * of this file to produce a combined library or application, then distribute + * that combined work under the terms of your choosing, with no requirement + * to comply with the obligations normally placed on you by section 4 of the + * LGPL version 3 (or the corresponding section of a later version of the LGPL + * should you choose to use a later version). + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) + +(** JavaScript String API *) + +type t = string + +(** [length str] returns the length of the string. + +@example {[ + length "abc" = 3;; +]} +*) +external length : t -> int = "length" [@@bs.get] + +(** [get str index] returns the string at [index]. + +@example {[ + get "abc" 1 = Some("b");; +]} +*) +external get : t -> int -> t option = "%array_unsafe_get" + +(** [concat append original] returns a new string with [append] added after [original]. + +@example {[ + concat "a" "b" = "ab";; +]} +*) +external concat : t -> t -> t = "concat" [@@bs.send] + +(** [concat arr original] returns a new string consisting of each item of an array of strings added to the [original] string. + +@example {[ + concatMany "1st" [|"2nd"; "3rd"; "4th"|] = "1st2nd3rd4th";; +]} +*) +external concatMany : t -> t array -> t = "concat" [@@bs.send] [@@bs.splice] + +(** ES2015: + [endsWith substr str] returns [true] if the [str] ends with [substr], [false] otherwise. + +@example {[ + endsWith "BuckleScript" "Script" = true;; + endsWith "BuckleShoes" "Script" = false;; +]} +*) +external endsWith : t -> t -> bool = "endsWith" [@@bs.send] + + +(** + [indexOf s searchValue ] returns an option containing the index of [searchValue] in [s] if found. + +@example {[ + indexOf "programmer" "gram" = Some(3);; + indexOf "programmer" "er" = Some(8);; + indexOf "programmer" "pro" = Some(0);; + indexOf "programmer" "xyz" = None;; +]} +*) +val indexOf: string -> string -> int option + +(** + [includes s searchValue ] returns [true] if [searchValue] is found anywhere within [s], [false] otherwise. + +@example {[ + includes "programmer" "gram" = true;; + includes "programmer" "er" = true;; + includes "programmer" "pro" = true;; + includes "programmer" "xyz" = false;; +]} +*) +external includes : t -> t -> bool = "includes" [@@bs.send] (** ES2015 *) + + + +(** + [repeat n s] returns a string that consists of [n] repetitions of [s]. Raises [RangeError] if [n] is negative. + +@example {[ + repeat "ha" 3 = "hahaha" + repeat "empty" 0 = "" +]} +*) +external repeat : t -> int -> t = "repeat" [@@bs.send] (** ES2015 *) + +(** [replace string substr newSubstr ] returns a new string which is +identical to [string] except with the first matching instance of [substr] +replaced by [newSubstr]. + +[substr] is treated as a verbatim string to match, not a regular +expression. + +@example {[ + replace "old string" ~old="old" ~by="new" = "new string" + replace "the cat and the dog" ~old="the" ~by="this" = "this cat and the dog" +]} +*) +external replace : t -> old:t -> by:t -> t = "replace" [@@bs.send] + +(** [replaceRegex string ~old=regex ~by=replacement] returns a new string where occurrences matching [regex] +have been replaced by [replacement]. + +@example {[ + replaceRegex ~old=[%re "/[aeiou]/g"] ~by="x" "vowels be gone" = "vxwxls bx gxnx" + replaceRegex ~old=[%re "/(\\w+) (\\w+)/"] ~by="$2, $1" "Juan Fulano" = "Fulano, Juan" +]} +*) +external replaceRegex : t -> old:Js_re.t -> by:t -> t = "replace" [@@bs.send] + + +(** + [matchRegex str regexp] matches a string against the given [regexp]. If there is no match, it returns [None]. + For regular expressions without the [g] modifier, if there is a match, the return value is [Some array] where the array contains: + + {ul + {- The entire matched string} + {- Any capture groups if the [regexp] had parentheses} + } + + For regular expressions with the [g] modifier, a matched expression returns [Some array] with all the matched substrings and no capture groups. + +@example {[ + matchRegex "The better bats" [%re "/b[aeiou]t/"] = Some [|"bet"|] + matchRegex "The better bats" [%re "/b[aeiou]t/g"] = Some [|"bet";"bat"|] + matchRegex "Today is 2018-04-05." [%re "/(\\d+)-(\\d+)-(\\d+)/"] = + Some [|"2018-04-05"; "2018"; "04"; "05"|] + matchRegex "The large container." [%re "/b[aeiou]g/"] = None +]} + +*) +external matchRegex : string -> Js_re.t -> t array option = "match" [@@bs.send] [@@bs.return {null_to_opt}] + +(** + [split delimiter str] splits the given [str] at every occurrence of [delimiter] and returns an + array of the resulting substrings. + +@example {[ + split "2018-01-02" "-" = [|"2018"; "01"; "02"|];; + split "a,b,,c" "," = [|"a"; "b"; ""; "c"|];; + split "good::bad as great::awful" "::" = [|"good"; "bad as great"; "awful"|];; + split "has-no-delimiter" ";" = [|"has-no-delimiter"|];; +]}; +*) +external split : t -> t -> t array = "split" [@@bs.send] + +(** + [splitAtMost str delimiter n] splits the given [str] at every occurrence of [delimiter] and + returns an array of the first [n] resulting substrings. If [n] is negative or greater than the + number of substrings, the array will contain all the substrings. + +@example {[ + splitAtMost "ant/bee/cat/dog/elk" "/" 3 = [|"ant"; "bee"; "cat"|];; + splitAtMost "ant/bee/cat/dog/elk" "/" 0 = [| |];; + splitAtMost "ant/bee/cat/dog/elk" "/" 9 = [|"ant"; "bee"; "cat"; "dog"; "elk"|];; +]} +*) +external splitAtMost: t -> t -> int -> t array = "split" [@@bs.send] + + +(** ES2015: + [startsWith str substr] returns [true] if the [str] starts with [substr], [false] otherwise. + +@example {[ + startsWith "BuckleScript" "Buckle" = true;; + startsWith "BuckleScript" "" = true;; + startsWith "JavaScript" "Buckle" = false;; +]} +*) +external startsWith : t -> t -> bool = "startsWith" [@@bs.send] + + +(** + [substr str ~from: n] returns the substring of [str] from position [n] to the end of the string. + + If [n] is less than zero, the starting position is the length of [str] - [n]. + + If [n] is greater than or equal to the length of [str], returns the empty string. + +@example {[ + substr "abcdefghij" ~from: 3 ~len: 2 = "de" + substr "abcdefghij" ~from: (-3) ~len: 3 = "hij" + substr "abcdefghij" ~from: 12 ~len: 2= "" +]} +*) +external substr : t -> from:int -> len:int -> t = "substr" [@@bs.send] + +(** + [substrToEnd str ~from: n] returns the substring of [str] from position [n] to the end of the string. + + If [n] is less than zero, the starting position is the length of [str] - [n]. + + If [n] is greater than or equal to the length of [str], returns the empty string. + +@example {[ + substrToEnd "abcdefghij" ~from: 3 = "defghij" + substrToEnd "abcdefghij" ~from: (-3) = "hij" + substrToEnd "abcdefghij" ~from: 12 = "" +]} +*) +external substrToEnd : t -> from:int -> t = "substr" [@@bs.send] + +(** [slice from:n1 to_:n2 str] returns the substring of [str] starting at character [n1] up to but not including [n2] + +If either [n1] or [n2] is negative, then it is evaluated as [length str - n1] (or [length str - n2]. + +If [n2] is greater than the length of [str], then it is treated as [length str]. + +If [n1] is greater than [n2], [slice] returns the empty string. + +@example {[ + slice "abcdefg" ~from:2 ~to_:5 == "cde";; + slice "abcdefg" ~from:2 ~to_:9 == "cdefg";; + slice "abcdefg" ~from:(-4) ~to_:(-2) == "de";; + slice "abcdefg" ~from:5 ~to_:1 == "";; +]} +*) +external slice : t -> from:int -> to_:int -> t = "slice" [@@bs.send] + +(** [sliceToEnd from: n str] returns the substring of [str] starting at character [n] to the end of the string + +If [n] is negative, then it is evaluated as [length str - n]. + +If [n] is greater than the length of [str], then [sliceToEnd] returns the empty string. + +@example {[ + sliceToEnd "abcdefg" ~from: 4 == "efg";; + sliceToEnd "abcdefg" ~from: (-2) == "fg";; + sliceToEnd "abcdefg" ~from: 7 == "";; +]} +*) +external sliceToEnd : t -> from:int -> t = "slice" [@@bs.send] + +(** + [trim str] returns a string that is [str] with whitespace stripped from both ends. Internal whitespace is not removed. + +@example {[ + trim " abc def " = "abc def" + trim "\n\r\t abc def \n\n\t\r " = "abc def" +]} +*) +external trim : t -> t = "trim" [@@bs.send] + +(** + [trimStart str] returns a string that is [str] with whitespace stripped from the start. Internal whitespace is not removed. + +@example {[ + trimStart " abc def " = "abc def " + trimStart "\n\r\t abc def \n\n\t\r " = "abc def \n\n\t\r" +]} +*) +external trimStart : t -> t = "trimStart" [@@bs.send] (** ES2015 *) + +(** + [trimEnd str] returns a string that is [str] with whitespace stripped from the end. Internal whitespace is not removed. + +@example {[ + trimEnd " abc def " = " abc def" + trimEnd "\n\r\t abc def \n\n\t\r " = "\n\r\t abc def" +]} +*) +external trimEnd : t -> t = "trimEnd" [@@bs.send] (** ES2015 *) + + +(** + [padStart str int padStr] returns a string that is [str] padded to the left with padStr. + +@example {[ + padStart "4" 3 "0" = "004" + padStart "444" 3 "0" = "444" +]} +*) +external padStart : t -> int -> t -> t = "padStart" [@@bs.send] (** ES2015 *) + +(** + [padEnd str int padStr] returns a string that is [str] padded to the right with padStr. + +@example {[ + padEnd "4" 3 "0" = "400" + padEnd "444" 3 "0" = "444" +]} +*) +external padEnd : t -> int -> t -> t = "padEnd" [@@bs.send] (** ES2015 *) + +(** + [toLowerCase str] converts [str] to lower case using the locale-insensitive case mappings in the Unicode Character Database. Notice that the conversion can give different results depending upon context, for example with the Greek letter sigma, which has two different lower case forms when it is the last character in a string or not. + +@example {[ + toLowerCase "ABC" = "abc";; + toLowerCase {js|ΣΠ|js} = {js|σπ|js};; + toLowerCase {js|ΠΣ|js} = {js|πς|js};; +]} +*) +external toLowerCase : t -> t = "toLowerCase" [@@bs.send] + +(** + [toUpperCase str] converts [str] to upper case using the locale-insensitive case mappings in the Unicode Character Database. Notice that the conversion can expand the number of letters in the result; for example the German [ß] capitalizes to two [S]es in a row. + +@example {[ + toUpperCase "abc" = "ABC";; + toUpperCase {js|Straße|js} = {js|STRASSE|js};; + toLowerCase {js|πς|js} = {js|ΠΣ|js};; +]} +*) +external toUpperCase : t -> t = "toUpperCase" [@@bs.send] diff --git a/jscomp/others/release.ninja b/jscomp/others/release.ninja index d93fea811a..af75ba31c4 100644 --- a/jscomp/others/release.ninja +++ b/jscomp/others/release.ninja @@ -118,6 +118,8 @@ build others/belt_SortArrayInt.cmj : cc others/belt_SortArrayInt.ml | others/bel build others/belt_SortArrayInt.cmi : cc others/belt_SortArrayInt.mli | runtime build others/belt_SortArrayString.cmj : cc others/belt_SortArrayString.ml | others/belt.cmi others/belt_Array.cmj others/belt_SortArrayString.cmi js_pkg runtime build others/belt_SortArrayString.cmi : cc others/belt_SortArrayString.mli | runtime +build others/belt_String.cmj : cc others/belt_String.ml | others/belt.cmi others/belt_String.cmi others/js_re.cmi js_pkg runtime +build others/belt_String.cmi : cc others/belt_String.mli | others/belt.cmi others/js_re.cmi js_pkg runtime build others/belt_internalAVLset.cmj : cc others/belt_internalAVLset.ml | others/belt.cmi others/belt_Array.cmj others/belt_Id.cmj others/belt_SortArray.cmj others/belt_internalAVLset.cmi js_pkg runtime build others/belt_internalAVLset.cmi : cc others/belt_internalAVLset.mli | others/belt.cmi others/belt_Id.cmi js_pkg runtime build others/belt_internalAVLtree.cmj : cc others/belt_internalAVLtree.ml | others/belt.cmi others/belt_Array.cmj others/belt_Id.cmj others/belt_SortArray.cmj others/belt_internalAVLtree.cmi js_pkg runtime @@ -142,4 +144,4 @@ build others/node_module.cmi others/node_module.cmj : cc others/node_module.ml | build others/node_path.cmi others/node_path.cmj : cc others/node_path.ml | runtime build others/node_process.cmj : cc others/node_process.ml | others/js_dict.cmj others/node.cmi others/node_process.cmi js_pkg runtime build others/node_process.cmi : cc others/node_process.mli | others/js_dict.cmi others/node.cmi js_pkg runtime -build others : phony others/belt_Array.cmi others/belt_Array.cmj others/belt_Debug.cmi others/belt_Debug.cmj others/belt_Float.cmi others/belt_Float.cmj others/belt_HashMap.cmi others/belt_HashMap.cmj others/belt_HashMapInt.cmi others/belt_HashMapInt.cmj others/belt_HashMapString.cmi others/belt_HashMapString.cmj others/belt_HashSet.cmi others/belt_HashSet.cmj others/belt_HashSetInt.cmi others/belt_HashSetInt.cmj others/belt_HashSetString.cmi others/belt_HashSetString.cmj others/belt_Id.cmi others/belt_Id.cmj others/belt_Int.cmi others/belt_Int.cmj others/belt_List.cmi others/belt_List.cmj others/belt_Map.cmi others/belt_Map.cmj others/belt_MapDict.cmi others/belt_MapDict.cmj others/belt_MapInt.cmi others/belt_MapInt.cmj others/belt_MapString.cmi others/belt_MapString.cmj others/belt_MutableMap.cmi others/belt_MutableMap.cmj others/belt_MutableMapInt.cmi others/belt_MutableMapInt.cmj others/belt_MutableMapString.cmi others/belt_MutableMapString.cmj others/belt_MutableQueue.cmi others/belt_MutableQueue.cmj others/belt_MutableSet.cmi others/belt_MutableSet.cmj others/belt_MutableSetInt.cmi others/belt_MutableSetInt.cmj others/belt_MutableSetString.cmi others/belt_MutableSetString.cmj others/belt_MutableStack.cmi others/belt_MutableStack.cmj others/belt_Option.cmi others/belt_Option.cmj others/belt_Range.cmi others/belt_Range.cmj others/belt_Result.cmi others/belt_Result.cmj others/belt_Set.cmi others/belt_Set.cmj others/belt_SetDict.cmi others/belt_SetDict.cmj others/belt_SetInt.cmi others/belt_SetInt.cmj others/belt_SetString.cmi others/belt_SetString.cmj others/belt_SortArray.cmi others/belt_SortArray.cmj others/belt_SortArrayInt.cmi others/belt_SortArrayInt.cmj others/belt_SortArrayString.cmi others/belt_SortArrayString.cmj others/belt_internalAVLset.cmi others/belt_internalAVLset.cmj others/belt_internalAVLtree.cmi others/belt_internalAVLtree.cmj others/belt_internalBuckets.cmi others/belt_internalBuckets.cmj others/belt_internalBucketsType.cmi others/belt_internalBucketsType.cmj others/belt_internalMapInt.cmi others/belt_internalMapInt.cmj others/belt_internalMapString.cmi others/belt_internalMapString.cmj others/belt_internalSetBuckets.cmi others/belt_internalSetBuckets.cmj others/belt_internalSetInt.cmi others/belt_internalSetInt.cmj others/belt_internalSetString.cmi others/belt_internalSetString.cmj others/dom.cmi others/dom_storage.cmi others/dom_storage2.cmi others/node_buffer.cmi others/node_buffer.cmj others/node_child_process.cmi others/node_child_process.cmj others/node_fs.cmi others/node_fs.cmj others/node_module.cmi others/node_module.cmj others/node_path.cmi others/node_path.cmj others/node_process.cmi others/node_process.cmj +build others : phony others/belt_Array.cmi others/belt_Array.cmj others/belt_Debug.cmi others/belt_Debug.cmj others/belt_Float.cmi others/belt_Float.cmj others/belt_HashMap.cmi others/belt_HashMap.cmj others/belt_HashMapInt.cmi others/belt_HashMapInt.cmj others/belt_HashMapString.cmi others/belt_HashMapString.cmj others/belt_HashSet.cmi others/belt_HashSet.cmj others/belt_HashSetInt.cmi others/belt_HashSetInt.cmj others/belt_HashSetString.cmi others/belt_HashSetString.cmj others/belt_Id.cmi others/belt_Id.cmj others/belt_Int.cmi others/belt_Int.cmj others/belt_List.cmi others/belt_List.cmj others/belt_Map.cmi others/belt_Map.cmj others/belt_MapDict.cmi others/belt_MapDict.cmj others/belt_MapInt.cmi others/belt_MapInt.cmj others/belt_MapString.cmi others/belt_MapString.cmj others/belt_MutableMap.cmi others/belt_MutableMap.cmj others/belt_MutableMapInt.cmi others/belt_MutableMapInt.cmj others/belt_MutableMapString.cmi others/belt_MutableMapString.cmj others/belt_MutableQueue.cmi others/belt_MutableQueue.cmj others/belt_MutableSet.cmi others/belt_MutableSet.cmj others/belt_MutableSetInt.cmi others/belt_MutableSetInt.cmj others/belt_MutableSetString.cmi others/belt_MutableSetString.cmj others/belt_MutableStack.cmi others/belt_MutableStack.cmj others/belt_Option.cmi others/belt_Option.cmj others/belt_Range.cmi others/belt_Range.cmj others/belt_Result.cmi others/belt_Result.cmj others/belt_Set.cmi others/belt_Set.cmj others/belt_SetDict.cmi others/belt_SetDict.cmj others/belt_SetInt.cmi others/belt_SetInt.cmj others/belt_SetString.cmi others/belt_SetString.cmj others/belt_SortArray.cmi others/belt_SortArray.cmj others/belt_SortArrayInt.cmi others/belt_SortArrayInt.cmj others/belt_SortArrayString.cmi others/belt_SortArrayString.cmj others/belt_String.cmi others/belt_String.cmj others/belt_internalAVLset.cmi others/belt_internalAVLset.cmj others/belt_internalAVLtree.cmi others/belt_internalAVLtree.cmj others/belt_internalBuckets.cmi others/belt_internalBuckets.cmj others/belt_internalBucketsType.cmi others/belt_internalBucketsType.cmj others/belt_internalMapInt.cmi others/belt_internalMapInt.cmj others/belt_internalMapString.cmi others/belt_internalMapString.cmj others/belt_internalSetBuckets.cmi others/belt_internalSetBuckets.cmj others/belt_internalSetInt.cmi others/belt_internalSetInt.cmj others/belt_internalSetString.cmi others/belt_internalSetString.cmj others/dom.cmi others/dom_storage.cmi others/dom_storage2.cmi others/node_buffer.cmi others/node_buffer.cmj others/node_child_process.cmi others/node_child_process.cmj others/node_fs.cmi others/node_fs.cmj others/node_module.cmi others/node_module.cmj others/node_path.cmi others/node_path.cmj others/node_process.cmi others/node_process.cmj diff --git a/jscomp/outcome_printer/outcome_printer_ns.ml b/jscomp/outcome_printer/outcome_printer_ns.ml index 7c16757ff4..c499c173f0 100644 --- a/jscomp/outcome_printer/outcome_printer_ns.ml +++ b/jscomp/outcome_printer/outcome_printer_ns.ml @@ -81,6 +81,7 @@ let out_ident ppf s = | "Belt_MutableQueue" -> "Belt.MutableQueue" | "Belt_MutableStack" -> "Belt.MutableStack" + | "Belt_String" -> "Belt.String" | "Belt_List" -> "Belt.List" | "Belt_Range" -> "Belt.Range" diff --git a/jscomp/test/bs_string_test.js b/jscomp/test/bs_string_test.js index 022adcf6dc..a6d7c35f4b 100644 --- a/jscomp/test/bs_string_test.js +++ b/jscomp/test/bs_string_test.js @@ -2,6 +2,10 @@ var Mt = require("./mt.js"); var Block = require("../../lib/js/block.js"); +var Belt_Array = require("../../lib/js/belt_Array.js"); +var Belt_Option = require("../../lib/js/belt_Option.js"); +var Belt_String = require("../../lib/js/belt_String.js"); +var Caml_option = require("../../lib/js/caml_option.js"); var suites = /* record */[/* contents : [] */0]; @@ -28,9 +32,125 @@ eq("File \"bs_string_test.ml\", line 11, characters 5-12", "ghso ghso g".split(" return x + ("-" + y); }), ""), "-ghso-ghso-g"); -Mt.from_pair_suites("Bs_string_test", suites[0]); +eq("File \"bs_string_test.ml\", line 18, characters 5-12", "foo".length, 3); + +eq("File \"bs_string_test.ml\", line 19, characters 5-12", "".length, 0); + +eq("File \"bs_string_test.ml\", line 22, characters 5-12", "foo"[1], "o"); + +eq("File \"bs_string_test.ml\", line 23, characters 5-12", "foo"[5], undefined); + +eq("File \"bs_string_test.ml\", line 26, characters 5-12", "foo".concat("bar"), "foobar"); + +eq("File \"bs_string_test.ml\", line 29, characters 5-12", "foo".concat("bar", "baz"), "foobarbaz"); + +var array = /* array */[ + "bar", + "baz" +]; + +eq("File \"bs_string_test.ml\", line 31, characters 7-14", Block.spliceObjApply("foo", "concat", [array]), "foobarbaz"); + +eq("File \"bs_string_test.ml\", line 32, characters 5-12", "".concat(), ""); + +eq("File \"bs_string_test.ml\", line 35, characters 5-12", "foo".endsWith("oo"), true); + +eq("File \"bs_string_test.ml\", line 36, characters 5-12", "foo".endsWith("a"), false); + +eq("File \"bs_string_test.ml\", line 39, characters 5-12", Belt_String.indexOf("foo", "oo"), 1); + +eq("File \"bs_string_test.ml\", line 40, characters 5-12", Belt_String.indexOf("foo", "a"), undefined); + +eq("File \"bs_string_test.ml\", line 43, characters 5-12", "foo".includes("oo"), true); + +eq("File \"bs_string_test.ml\", line 44, characters 5-12", "foo".includes("a"), false); + +eq("File \"bs_string_test.ml\", line 47, characters 5-12", "a".repeat(3), "aaa"); + +eq("File \"bs_string_test.ml\", line 48, characters 5-12", "a".repeat(0), ""); + +eq("File \"bs_string_test.ml\", line 51, characters 5-12", "hello world".replace("world", "you"), "hello you"); + +eq("File \"bs_string_test.ml\", line 52, characters 5-12", "hello world".replace("foo", "you"), "hello world"); + +eq("File \"bs_string_test.ml\", line 55, characters 5-12", "hello world".replace((/world/), "you"), "hello you"); + +eq("File \"bs_string_test.ml\", line 56, characters 5-12", "hello world world".replace((/world/g), "you"), "hello you you"); + +eq("File \"bs_string_test.ml\", line 57, characters 5-12", "hello world".replace((/foo/g), "you"), "hello world"); + +eq("File \"bs_string_test.ml\", line 61, characters 5-12", Caml_option.null_to_opt("hello world".match((/world/))) !== undefined, true); + +eq("File \"bs_string_test.ml\", line 62, characters 5-12", Belt_Option.map(Caml_option.null_to_opt("hello world".match((/world/))), (function (x) { + return x.length; + })), 1); + +eq("File \"bs_string_test.ml\", line 63, characters 5-12", Belt_Option.flatMap(Caml_option.null_to_opt("hello world".match((/world/))), (function (x) { + return Belt_Array.get(x, 0); + })), "world"); + +eq("File \"bs_string_test.ml\", line 64, characters 5-12", Caml_option.null_to_opt("hello world".match((/notfound/))), undefined); + +eq("File \"bs_string_test.ml\", line 67, characters 5-12", "hello world foo".split(" "), /* array */[ + "hello", + "world", + "foo" + ]); + +eq("File \"bs_string_test.ml\", line 70, characters 5-12", "hello world foo".split(" ", 1), /* array */["hello"]); + +eq("File \"bs_string_test.ml\", line 73, characters 5-12", "hello world".startsWith("hello"), true); + +eq("File \"bs_string_test.ml\", line 74, characters 5-12", "hello world".startsWith("world"), false); + +eq("File \"bs_string_test.ml\", line 77, characters 5-12", "hello world".substr(1, 3), "ell"); + +eq("File \"bs_string_test.ml\", line 80, characters 5-12", "hello world".substr(1), "ello world"); + +eq("File \"bs_string_test.ml\", line 81, characters 5-12", "hello world".substr(11), ""); + +eq("File \"bs_string_test.ml\", line 84, characters 5-12", "hello world".slice(1, 3), "el"); + +eq("File \"bs_string_test.ml\", line 85, characters 5-12", "hello world".slice(11, 12), ""); + +eq("File \"bs_string_test.ml\", line 88, characters 5-12", "hello world".slice(1), "ello world"); + +eq("File \"bs_string_test.ml\", line 89, characters 5-12", "hello world".slice(11), ""); + +eq("File \"bs_string_test.ml\", line 92, characters 5-12", " hello world ".trim(), "hello world"); + +eq("File \"bs_string_test.ml\", line 93, characters 5-12", "\n\r\t hello world\n\r\t ".trim(), "hello world"); + +eq("File \"bs_string_test.ml\", line 96, characters 5-12", " hello world ".trimStart(), "hello world "); + +eq("File \"bs_string_test.ml\", line 97, characters 5-12", "\n\r\t hello world\n\r\t ".trimStart(), "hello world\n\r\t "); + +eq("File \"bs_string_test.ml\", line 100, characters 5-12", " hello world ".trimEnd(), " hello world"); + +eq("File \"bs_string_test.ml\", line 101, characters 5-12", "\n\r\t hello world\n\r\t ".trimEnd(), "\n\r\t hello world"); + +eq("File \"bs_string_test.ml\", line 104, characters 5-12", "4".padStart(4, "x"), "xxx4"); + +eq("File \"bs_string_test.ml\", line 105, characters 5-12", "4444".padStart(4, "x"), "4444"); + +eq("File \"bs_string_test.ml\", line 106, characters 5-12", "4".padStart(4, "xy"), "xyx4"); + +eq("File \"bs_string_test.ml\", line 109, characters 5-12", "4".padEnd(4, "x"), "4xxx"); + +eq("File \"bs_string_test.ml\", line 110, characters 5-12", "4444".padEnd(4, "x"), "4444"); + +eq("File \"bs_string_test.ml\", line 111, characters 5-12", "4".padEnd(4, "xy"), "4xyx"); + +eq("File \"bs_string_test.ml\", line 114, characters 5-12", "HeLLo WorLd".toLowerCase(), "hello world"); + +eq("File \"bs_string_test.ml\", line 117, characters 5-12", "HeLLo WorLd".toUpperCase(), "HELLO WORLD"); + +Mt.from_pair_suites("bs_string_test.ml", suites[0]); + +var S = 0; exports.suites = suites; exports.test_id = test_id; exports.eq = eq; +exports.S = S; /* Not a pure module */ diff --git a/jscomp/test/bs_string_test.ml b/jscomp/test/bs_string_test.ml index a31910d936..8ef1ef14c6 100644 --- a/jscomp/test/bs_string_test.ml +++ b/jscomp/test/bs_string_test.ml @@ -5,7 +5,7 @@ let eq loc x y = suites := (loc ^" id " ^ (string_of_int !test_id), (fun _ -> Mt.Eq(x,y))) :: !suites - +module S = Belt.String let () = eq __LOC__ @@ -14,6 +14,106 @@ let () = |. Js.Array2.reduce (fun x y -> x ^ "-" ^ y) "" ) "-ghso-ghso-g" +let () = + eq __LOC__ (S.length "foo") 3; + eq __LOC__ (S.length "") 0 + +let () = + eq __LOC__ (S.get "foo" 1) (Some "o"); + eq __LOC__ (S.get "foo" 5) None +let () = + eq __LOC__ (S.concat "foo" "bar") "foobar" + +let () = + eq __LOC__ (S.concatMany "foo" [|"bar"; "baz"|]) "foobarbaz"; + let array = [|"bar"; "baz"|] in + eq __LOC__ (S.concatMany "foo" array) "foobarbaz"; + eq __LOC__ (S.concatMany "" [||]) "" + +let () = + eq __LOC__ (S.endsWith "foo" "oo") true; + eq __LOC__ (S.endsWith "foo" "a") false + +let () = + eq __LOC__ (S.indexOf "foo" "oo") (Some 1); + eq __LOC__ (S.indexOf "foo" "a") None + +let () = + eq __LOC__ (S.includes "foo" "oo") true; + eq __LOC__ (S.includes "foo" "a") false + +let () = + eq __LOC__ (S.repeat "a" 3) "aaa"; + eq __LOC__ (S.repeat "a" 0) "" + +let () = + eq __LOC__ (S.replace "hello world" ~old: "world" ~by: "you") "hello you"; + eq __LOC__ (S.replace "hello world" ~old: "foo" ~by: "you") "hello world" + +let () = + eq __LOC__ (S.replaceRegex "hello world" ~old: [%re "/world/"] ~by: "you") "hello you"; + eq __LOC__ (S.replaceRegex "hello world world" ~old: [%re "/world/g"] ~by: "you") "hello you you"; + eq __LOC__ (S.replaceRegex "hello world" ~old: [%re "/foo/g"] ~by: "you") "hello world" + +let () = + (* the following test is broken down because the deepEqual fails as JS adds properties to the array *) + eq __LOC__ (Belt.Option.isSome (S.matchRegex "hello world" [%re "/world/"])) true; + eq __LOC__ (Belt.Option.map (S.matchRegex "hello world" [%re "/world/"]) (fun x -> Belt.Array.length x)) (Some 1); + eq __LOC__ (Belt.Option.flatMap (S.matchRegex "hello world" [%re "/world/"]) (fun x -> Belt.Array.get x 0)) (Some "world"); + eq __LOC__ (S.matchRegex "hello world" [%re "/notfound/"]) None + +let () = + eq __LOC__ (S.split "hello world foo" " ") [|"hello"; "world"; "foo"|] + +let () = + eq __LOC__ (S.splitAtMost "hello world foo" " " 1) [|"hello"|] + +let () = + eq __LOC__ (S.startsWith "hello world" "hello") true; + eq __LOC__ (S.startsWith "hello world" "world") false + +let () = + eq __LOC__ (S.substr "hello world" ~from: 1 ~len: 3) "ell" + +let () = + eq __LOC__ (S.substrToEnd "hello world" ~from: 1) "ello world"; + eq __LOC__ (S.substrToEnd "hello world" ~from: 11) "" + +let () = + eq __LOC__ (S.slice "hello world" ~from: 1 ~to_: 3) "el"; + eq __LOC__ (S.slice "hello world" ~from: 11 ~to_: 12) "" + +let () = + eq __LOC__ (S.sliceToEnd "hello world" ~from: 1) "ello world"; + eq __LOC__ (S.sliceToEnd "hello world" ~from: 11) "" + +let () = + eq __LOC__ (S.trim " hello world ") "hello world"; + eq __LOC__ (S.trim "\n\r\t hello world\n\r\t ") "hello world" + +let () = + eq __LOC__ (S.trimStart " hello world ") "hello world "; + eq __LOC__ (S.trimStart "\n\r\t hello world\n\r\t ") "hello world\n\r\t " + +let () = + eq __LOC__ (S.trimEnd " hello world ") " hello world"; + eq __LOC__ (S.trimEnd "\n\r\t hello world\n\r\t ") "\n\r\t hello world" + +let () = + eq __LOC__ (S.padStart "4" 4 "x") "xxx4"; + eq __LOC__ (S.padStart "4444" 4 "x") "4444"; + eq __LOC__ (S.padStart "4" 4 "xy") "xyx4" + +let () = + eq __LOC__ (S.padEnd "4" 4 "x") "4xxx"; + eq __LOC__ (S.padEnd "4444" 4 "x") "4444"; + eq __LOC__ (S.padEnd "4" 4 "xy") "4xyx" + +let () = + eq __LOC__ (S.toLowerCase "HeLLo WorLd") "hello world" + +let () = + eq __LOC__ (S.toUpperCase "HeLLo WorLd") "HELLO WORLD" -let () = Mt.from_pair_suites __MODULE__ !suites \ No newline at end of file +let () = Mt.from_pair_suites __FILE__ !suites diff --git a/lib/4.02.3/whole_compiler.ml b/lib/4.02.3/whole_compiler.ml index 628b15924e..077b1a02d2 100644 --- a/lib/4.02.3/whole_compiler.ml +++ b/lib/4.02.3/whole_compiler.ml @@ -120545,6 +120545,7 @@ let out_ident ppf s = | "Belt_MutableQueue" -> "Belt.MutableQueue" | "Belt_MutableStack" -> "Belt.MutableStack" + | "Belt_String" -> "Belt.String" | "Belt_List" -> "Belt.List" | "Belt_Range" -> "Belt.Range" diff --git a/lib/js/belt.js b/lib/js/belt.js index 5bfd498848..feccdc04f0 100644 --- a/lib/js/belt.js +++ b/lib/js/belt.js @@ -35,6 +35,8 @@ var Int = 0; var Float = 0; +var $$String = 0; + var Debug = 0; exports.Id = Id; @@ -54,5 +56,6 @@ exports.$$Option = $$Option; exports.Result = Result; exports.Int = Int; exports.Float = Float; +exports.$$String = $$String; exports.Debug = Debug; /* No side effect */ diff --git a/lib/js/belt_String.js b/lib/js/belt_String.js new file mode 100644 index 0000000000..aca6c50e8b --- /dev/null +++ b/lib/js/belt_String.js @@ -0,0 +1,13 @@ +'use strict'; + + +function indexOf(s, searchValue) { + var value = s.indexOf(searchValue); + if (value !== -1) { + return value; + } + +} + +exports.indexOf = indexOf; +/* No side effect */