Introduce the HowMany type to simplify API
This commit is contained in:
parent
d47407ef15
commit
f0f84cbb54
2 changed files with 59 additions and 75 deletions
|
@ -15,7 +15,7 @@ Elm.Native.Regex.make = function(elm) {
|
||||||
function caseInsensitive(re) {
|
function caseInsensitive(re) {
|
||||||
return new RegExp(re.source, 'gi');
|
return new RegExp(re.source, 'gi');
|
||||||
}
|
}
|
||||||
function pattern(raw) {
|
function regex(raw) {
|
||||||
return new RegExp(raw, 'g');
|
return new RegExp(raw, 'g');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,10 +23,8 @@ Elm.Native.Regex.make = function(elm) {
|
||||||
return re.test(JS.fromString(string));
|
return re.test(JS.fromString(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
function findAll(re, string) {
|
|
||||||
return find(Infinity, re, string);
|
|
||||||
}
|
|
||||||
function find(n, re, str) {
|
function find(n, re, str) {
|
||||||
|
n = n.ctor === "All" ? Infinity : n._0;
|
||||||
var out = [];
|
var out = [];
|
||||||
var number = 0;
|
var number = 0;
|
||||||
var string = JS.fromString(str);
|
var string = JS.fromString(str);
|
||||||
|
@ -51,10 +49,8 @@ Elm.Native.Regex.make = function(elm) {
|
||||||
return JS.toList(out);
|
return JS.toList(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
function replaceAll(re, replacer, string) {
|
|
||||||
return replace(Infinity, re, replacer, string);
|
|
||||||
}
|
|
||||||
function replace(n, re, replacer, string) {
|
function replace(n, re, replacer, string) {
|
||||||
|
n = n.ctor === "All" ? Infinity : n._0;
|
||||||
var count = 0;
|
var count = 0;
|
||||||
function jsReplacer(match) {
|
function jsReplacer(match) {
|
||||||
if (count++ > n) return match;
|
if (count++ > n) return match;
|
||||||
|
@ -77,10 +73,10 @@ Elm.Native.Regex.make = function(elm) {
|
||||||
return string.replace(re, jsReplacer);
|
return string.replace(re, jsReplacer);
|
||||||
}
|
}
|
||||||
|
|
||||||
function split(re, string) {
|
function split(n, re, str) {
|
||||||
return JS.toList(JS.fromString(string).split(re));
|
if (n === Infinity) {
|
||||||
}
|
return JS.toList(JS.fromString(string).split(re));
|
||||||
function splitN(n, re, str) {
|
}
|
||||||
var string = JS.fromString(str);
|
var string = JS.fromString(str);
|
||||||
var result;
|
var result;
|
||||||
var out = [];
|
var out = [];
|
||||||
|
@ -95,18 +91,13 @@ Elm.Native.Regex.make = function(elm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return Elm.Native.Regex.values = {
|
return Elm.Native.Regex.values = {
|
||||||
pattern: pattern,
|
regex: regex,
|
||||||
caseInsensitive: caseInsensitive,
|
caseInsensitive: caseInsensitive,
|
||||||
escape: escape,
|
escape: escape,
|
||||||
|
|
||||||
contains: F2(contains),
|
contains: F2(contains),
|
||||||
findAll: F2(findAll),
|
|
||||||
find: F3(find),
|
find: F3(find),
|
||||||
|
|
||||||
replaceAll: F3(replaceAll),
|
|
||||||
replace: F4(replace),
|
replace: F4(replace),
|
||||||
|
split: F3(split),
|
||||||
split: F2(split),
|
|
||||||
splitN: F3(splitN),
|
|
||||||
};
|
};
|
||||||
};
|
};
|
|
@ -3,16 +3,17 @@ module Regex where
|
||||||
same kind of regular expressions accepted by JavaScript](https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions).
|
same kind of regular expressions accepted by JavaScript](https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions).
|
||||||
|
|
||||||
# Create
|
# Create
|
||||||
@docs pattern, caseInsensitive, escape
|
@docs regex, escape, caseInsensitive
|
||||||
|
|
||||||
# Match
|
# Helpful Data Structures
|
||||||
@docs Match
|
|
||||||
|
|
||||||
# Find and Replace
|
These data structures are needed to help define functions like [`find`](#find)
|
||||||
@docs contains, find, findAll, replace, replaceAll
|
and [`replace`](#replace).
|
||||||
|
|
||||||
# Split
|
@docs HowMany, Match
|
||||||
@docs split, splitN
|
|
||||||
|
# Use
|
||||||
|
@docs contains, find, replace, split
|
||||||
|
|
||||||
-}
|
-}
|
||||||
|
|
||||||
|
@ -21,31 +22,35 @@ import Native.Regex
|
||||||
|
|
||||||
data Regex = Regex
|
data Regex = Regex
|
||||||
|
|
||||||
{-| Escape all special characters. So `pattern (escape "$$$")`
|
{-| Escape strings to be regular expressions, making all special characters
|
||||||
will match exactly `"$$$"` even though `$` is a special character.
|
safe. So `regex (escape "^a+")` will match exactly `"^a+"` instead of a series
|
||||||
|
of `a`’s that start at the beginning of the line.
|
||||||
-}
|
-}
|
||||||
escape : String -> String
|
escape : String -> String
|
||||||
escape = Native.Regex.escape
|
escape = Native.Regex.escape
|
||||||
|
|
||||||
{-| Create a Regex that matches patterns [as specified in JavaScript](https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions#Writing_a_Regular_Expression_Pattern).
|
{-| Create a Regex that matches patterns [as specified in JavaScript](https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions#Writing_a_Regular_Expression_Pattern).
|
||||||
Be careful to escape backslashes properly!
|
|
||||||
|
Be careful to escape backslashes properly! For example, `"\w"` is escaping the
|
||||||
|
letter `w` which is probably not what you want. You probably want `"\\w"`
|
||||||
|
instead, which escapes the backslash.
|
||||||
-}
|
-}
|
||||||
pattern : String -> Regex
|
regex : String -> Regex
|
||||||
pattern = Native.Regex.pattern
|
regex = Native.Regex.regex
|
||||||
|
|
||||||
|
|
||||||
{-| Make a pattern case insensitive -}
|
{-| Make a regex case insensitive -}
|
||||||
caseInsensitive : Regex -> Regex
|
caseInsensitive : Regex -> Regex
|
||||||
caseInsensitive = Native.Regex.caseInsensitive
|
caseInsensitive = Native.Regex.caseInsensitive
|
||||||
|
|
||||||
{-| Check to see if a Regex is contained in a string.
|
{-| Check to see if a Regex is contained in a string.
|
||||||
|
|
||||||
```haskell
|
```haskell
|
||||||
contains (pattern "123") "12345" == True
|
contains (regex "123") "12345" == True
|
||||||
contains (pattern "b+") "aabbcc" == True
|
contains (regex "b+") "aabbcc" == True
|
||||||
|
|
||||||
contains (pattern "789") "12345" == False
|
contains (regex "789") "12345" == False
|
||||||
contains (pattern "z+") "aabbcc" == False
|
contains (regex "z+") "aabbcc" == False
|
||||||
```
|
```
|
||||||
-}
|
-}
|
||||||
contains : Regex -> String -> Bool
|
contains : Regex -> String -> Bool
|
||||||
|
@ -55,79 +60,67 @@ contains = Native.Regex.contains
|
||||||
Here are details on each field:
|
Here are details on each field:
|
||||||
|
|
||||||
* `match` — the full string of the match.
|
* `match` — the full string of the match.
|
||||||
* `submatches` — a pattern might have [subpatterns, surrounded by
|
* `submatches` — a regex might have [subpatterns, surrounded by
|
||||||
parentheses](https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions#Using_Parenthesized_Substring_Matches).
|
parentheses](https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions#Using_Parenthesized_Substring_Matches).
|
||||||
If there are N subpatterns, there will be N elements in the `submatches` list.
|
If there are N subpatterns, there will be N elements in the `submatches` list.
|
||||||
Each submatch in this list is a `Maybe` because not all subpatterns may trigger.
|
Each submatch in this list is a `Maybe` because not all subpatterns may trigger.
|
||||||
For example, `(pattern "(a+)|(b+)")` will either match many `a`’s or
|
For example, `(regex "(a+)|(b+)")` will either match many `a`’s or
|
||||||
many `b`’s, but never both.
|
many `b`’s, but never both.
|
||||||
* `index` — the index of the match in the original string.
|
* `index` — the index of the match in the original string.
|
||||||
* `number` — if you find many matches, you can think of each one
|
* `number` — if you find many matches, you can think of each one
|
||||||
as being labeled with a `number` starting at one. So the first time you
|
as being labeled with a `number` starting at one. So the first time you
|
||||||
find a match, that is match `number` one. Second time is match `number` two.
|
find a match, that is match `number` one. Second time is match `number` two.
|
||||||
This is useful when paired with `replaceAll` if replacement is dependent on how
|
This is useful when paired with `replace All` if replacement is dependent on how
|
||||||
many times a pattern has appeared before.
|
many times a pattern has appeared before.
|
||||||
-}
|
-}
|
||||||
type Match = { match : String, submatches : [Maybe String], index : Int, number : Int }
|
type Match = { match : String, submatches : [Maybe String], index : Int, number : Int }
|
||||||
|
|
||||||
{-| Find all of the matches in a string:
|
{-| `HowMany` is used to specify how many matches you want to make. So
|
||||||
|
`replace All` would replace every match, but `replace (AtMost 2)` would
|
||||||
|
replace at most two matches (i.e. zero, one, two, but never three or more).
|
||||||
|
-}
|
||||||
|
data HowMany = All | AtMost Int
|
||||||
|
|
||||||
|
{-| Find matches in a string:
|
||||||
|
|
||||||
```haskell
|
```haskell
|
||||||
words = findAll (pattern "\\w+") "hello world"
|
findTwoCommas = find (AtMost 2) (regex ",")
|
||||||
|
|
||||||
map .match words == ["hello","world"]
|
-- map .index (findTwoCommas "a,b,c,d,e") == [1,3]
|
||||||
map .index words == [0,6]
|
-- map .index (findTwoCommas "a b c d e") == []
|
||||||
|
|
||||||
places = findAll (pattern "[oi]n a (\\w+)") "I am on a boat in a lake."
|
places = find All (regex "[oi]n a (\\w+)") "I am on a boat in a lake."
|
||||||
|
|
||||||
map .match places== ["on a boat", "in a lake"]
|
-- map .match places == ["on a boat", "in a lake"]
|
||||||
map .submatches places == [ [Just "boat"], [Just "lake"] ]
|
-- map .submatches places == [ [Just "boat"], [Just "lake"] ]
|
||||||
```
|
```
|
||||||
-}
|
-}
|
||||||
findAll : Regex -> String -> [Match]
|
find : HowMany -> Regex -> String -> [Match]
|
||||||
findAll = Native.Regex.findAll
|
|
||||||
|
|
||||||
{-| Same as `findAll`, but `find` will quit searching after the *n<sup>th</sup>* match.
|
|
||||||
That means the resulting list has maximum length N, but *it can be shorter*
|
|
||||||
if there are not that many matches in the given string.
|
|
||||||
-}
|
|
||||||
find : Int -> Regex -> String -> [Match]
|
|
||||||
find = Native.Regex.find
|
find = Native.Regex.find
|
||||||
|
|
||||||
{-| Replace all matches. The function from `Match` to `String` lets
|
{-| Replace matches. The function from `Match` to `String` lets
|
||||||
you use the details of a specific match when making replacements.
|
you use the details of a specific match when making replacements.
|
||||||
|
|
||||||
```haskell
|
```haskell
|
||||||
devowel = replaceAll (pattern "[aeiou]") (\_ -> "")
|
devowel = replace All (regex "[aeiou]") (\_ -> "")
|
||||||
|
|
||||||
devowel "The quick brown fox" == "Th qck brwn fx"
|
-- devowel "The quick brown fox" == "Th qck brwn fx"
|
||||||
|
|
||||||
reverseWords = replaceAll (pattern "\\w+") (\{match} -> String.reverse match)
|
reverseWords = replace All (regex "\\w+") (\{match} -> String.reverse match)
|
||||||
|
|
||||||
reverseWords "deliver mined parts" == "reviled denim strap"
|
-- reverseWords "deliver mined parts" == "reviled denim strap"
|
||||||
```
|
```
|
||||||
-}
|
-}
|
||||||
replaceAll : Regex -> (Match -> String) -> String -> String
|
replace : HowMany -> Regex -> (Match -> String) -> String -> String
|
||||||
replaceAll = Native.Regex.replaceAll
|
|
||||||
|
|
||||||
{-| Same as `replaceAll`, but `replace` will quit after the *n<sup>th</sup>* match.-}
|
|
||||||
replace : Int -> Regex -> (Match -> String) -> String -> String
|
|
||||||
replace = Native.Regex.replace
|
replace = Native.Regex.replace
|
||||||
|
|
||||||
{-| Split a string, using the regex as the separator.
|
{-| Split a string, using the regex as the separator.
|
||||||
|
|
||||||
```haskell
|
```haskell
|
||||||
split (pattern " *, *") "a ,b, c,d" == ["a","b","c","d"]
|
split (AtMost 1) (regex ",") "tom,99,90,85" == ["tom","99,90,85"]
|
||||||
|
|
||||||
|
split All (regex ",") "a,b,c,d" == ["a","b","c","d"]
|
||||||
```
|
```
|
||||||
-}
|
-}
|
||||||
split : Regex -> String -> [String]
|
split : HowMany -> Regex -> String -> [String]
|
||||||
split = Native.Regex.split
|
split = Native.Regex.split
|
||||||
|
|
||||||
{-| Same as `split` but stops after the *n<sup>th</sup>* match.
|
|
||||||
|
|
||||||
```haskell
|
|
||||||
splitN 1 (pattern ": *") "tom: 99,90,85" == ["tom","99,90,85"]
|
|
||||||
```
|
|
||||||
-}
|
|
||||||
splitN : Int -> Regex -> String -> [String]
|
|
||||||
splitN = Native.Regex.splitN
|
|
||||||
|
|
Loading…
Reference in a new issue