packages feed

lens-regex-pcre 0.1.1.0 → 0.2.0.0

raw patch · 5 files changed

+257/−247 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Control.Lens.Regex: grouped :: Traversal' Match [Text]
- Control.Lens.Regex: igroups :: IndexedTraversal' Int Match Text
- Control.Lens.Regex: groups :: Traversal' Match Text
+ Control.Lens.Regex: groups :: Traversal' Match [Text]

Files

ChangeLog.md view
@@ -1,5 +1,8 @@ # Changelog for lens-regex-pcre +# 2.0.0 +Unify `grouped`, `groups`, and `igroups` into just `groups` with optional traversal+ # 1.1.0  Adds `grouped` and `matchAndGroups` 
README.md view
@@ -1,6 +1,8 @@ # lens-regex-pcre -* NOTE: I don't promise that this is __fast__ yet;+[Hackage and Docs](http://hackage.haskell.org/package/lens-regex-pcre)++* NOTE: I don't promise that this is __fast__ yet, nor do I have any benchmarks; * NOTE: currently only supports `Text` but should be generalizable to more string-likes; open an issue if you need it  Based on `pcre-heavy`; so it should support any regexes which it supports.@@ -13,48 +15,45 @@ and alter zero or more matches; traversals can even carry indexes so you know which match or group you're working on. --Note that all traversals in this library are not techically lawful; the break the 'multi-set'-idempotence law; in reality this isn't usually a problem; but consider yourself warned. Test your code.+Note that all traversals in this library are not techically lawful, as the semantics of regular expressions don't allow for it;+They break the 'multi-set' idempotence law of traversals (same one broken by `filtered` from `lens`); in reality this isn't usually a problem (I've literally never encountered an issue with it); but consider yourself warned. Test your code.  Here are a few examples:  ```haskell--- Getting all matches:-> "one _two_ three _four_" ^.. regex [rx|_\w+_|] . match-["_two_","_four_"]---- Regex replace/mutation-> "one _two_ three _four_" & regex [rx|_\w+_|] . match %~ T.toUpper-"one _TWO_ three _FOUR_"---- Getting groups with their index.-> "1/2 and 3/4" ^.. regex [rx|(\d+)/(\d+)|] . igroups . withIndex-[(0,"1"),(1,"2"),(0,"3"),(1,"4")]+txt :: Text+txt = "raindrops on roses and whiskers on kittens" --- Check for any matches:-> has (regex [rx|ne+dle|]) "a needle in a haystack"+-- Search+λ> has (regex [rx|whisk|]) txt True --- Check for matches which also match a predicate:-> has (regex [rx|\w+|] . match . filtered ((> 7) . T.length)) "one word here is loooooooong"-True+-- Get matches+λ> txt ^.. regex [rx|\br\w+|] . match+["raindrops","roses"] --- Get the third match->  "alpha beta charlie delta" ^? (iregex [rx|\w+|] . index 2 . match)-Just "charlie"+-- Edit matches+λ> txt & regex [rx|\br\w+|] . match %~ T.intersperse '-' . T.toUpper+"R-A-I-N-D-R-O-P-S on R-O-S-E-S and whiskers on kittens" --- Replace the third match-> "alpha beta charlie delta" & (iregex [rx|\w+|] . index 2 . match) .~ "GAMMA"-"alpha beta GAMMA delta"+-- Get Groups+λ> txt ^.. regex [rx|(\w+) on (\w+)|] . groups+[["raindrops","roses"],["whiskers","kittens"]] --- Sort all matches alphabetically in place-> "*charlie* beta = _alpha_ delta" & partsOf (iregex [rx|[a-z]+|] . match) %~ sort-"*alpha* beta = _charlie_ delta"+-- Edit Groups+λ> txt & regex [rx|(\w+) on (\w+)|] . groups %~ reverse+"roses on raindrops and kittens on whiskers" --- Match integers, 'Read' them into ints, then sort each match in-place-> "Monday: 29, Tuesday: 99, Wednesday: 3" & partsOf' (iregex [rx|\d+|] . match . unpacked . _Show @Int) %~ sort+-- Get the third match+λ> txt ^? iregex [rx|\w+|] . index 2 . match+Just "roses"++-- Match integers, 'Read' them into ints, then sort them in-place+-- dumping them back into the source text afterwards.+λ> "Monday: 29, Tuesday: 99, Wednesday: 3" +   & partsOf (iregex [rx|\d+|] . match . unpacked . _Show @Int) %~ sort "Monday: 3, Tuesday: 29, Wednesday: 99"+ ```  Basically anything you want to do is possible somehow.@@ -62,133 +61,122 @@ Expected behaviour (and examples) can be found in the test suite:  ```haskell-import Control.Lens-import Control.Lens.Regex+describe "regex" $ do+    describe "match" $ do+        describe "getting" $ do+            it "should find one match" $ do+                "abc" ^.. regex [rx|b|] . match+                `shouldBe` ["b"] -describe "regex" $ do                                                                                            -    describe "match" $ do                                                                                        -        describe "getting" $ do                                                                                  -            it "should find one match" $ do                                                                      -                "abc" ^.. regex [rx|b|] . match                                                                  -                `shouldBe` ["b"]                                                                                 -                                                                                                                 -            it "should find many matches" $ do                                                                   -                "a b c" ^.. regex [rx|\w|] . match                                                               -                `shouldBe` ["a", "b", "c"]                                                                       -                                                                                                                 -            it "should fold" $ do                                                                                -                "a b c" ^. regex [rx|\w|] . match                                                                -                `shouldBe` "abc"                                                                                 -                                                                                                                 -            it "should match with a group" $ do                                                                  -                "a b c" ^.. regex [rx|(\w)|] . match                                                             -                `shouldBe` ["a", "b", "c"]                                                                       -                                                                                                                 -            it "should match with many groups" $ do                                                              -                "a b c" ^.. regex [rx|(\w) (\w)|] . match                                                        -                `shouldBe` ["a b"]                                                                               -                                                                                                                 -            it "should be greedy when overlapping" $ do                                                          -                "abc" ^.. regex [rx|\w+|] . match                                                                -                `shouldBe`["abc"]                                                                                -                                                                                                                 -            it "should respect lazy modifiers" $ do                                                              -                "abc" ^.. regex [rx|\w+?|] . match                                                               -                `shouldBe`["a", "b", "c"]                                                                        -                                                                                                                 -        describe "setting" $ do                                                                                  -            it "should allow setting" $ do                                                                       -                ("one two three" & regex [rx|two|] . match .~ "new")                                             -                `shouldBe` "one new three"                                                                       -                                                                                                                 -            it "should allow setting many" $ do                                                                  -                ("one <two> three" & regex [rx|\w+|] . match .~ "new")                                           -                `shouldBe` "new <new> new"                                                                       -                                                                                                                 -            it "should allow mutating" $ do                                                                      -                ("one two three" & regex [rx|two|] . match %~ (<> "!!"). T.toUpper)                              -                `shouldBe` "one TWO!! three"                                                                     -                                                                                                                 -            it "should allow mutating many" $ do                                                                 -                ("one two three" & regex [rx|two|] . match %~ T.toUpper)                                         -                `shouldBe` "one TWO three"                                                                       -                                                                                                                 -    describe "groups" $ do                                                                                       -        describe "getting" $ do                                                                                  -            it "should get a group" $ do                                                                         -                "a b c" ^.. regex [rx|(\w)|] . groups                                                            -                `shouldBe` ["a", "b", "c"]                                                                       -                                                                                                                 -            it "should get many groups" $ do                                                                     -                "one two three" ^.. regex [rx|(\w+) (\w+)|] . groups                                             -                `shouldBe` ["one", "two"]                                                                        -                                                                                                                 -        describe "setting" $ do                                                                                  -            it "should allow setting" $ do                                                                       -                ("one two three" & regex [rx|(\w+) (\w+)|] . groups .~ "new")                                    -                `shouldBe` "new new three"                                                                       -                                                                                                                 -            it "should allow setting many" $ do                                                                  -                ("one two three four" & regex [rx|(\w+) (\w+)|] . groups .~ "new")                               -                `shouldBe` "new new new new"                                                                     -                                                                                                                 -            it "should allow mutating" $ do                                                                      -                ("one two three four" & regex [rx|one (two) three|] . groups %~ (<> "!!") . T.toUpper)           -                `shouldBe` "one TWO!! three four"                                                                -                                                                                                                 -            it "should allow mutating" $ do                                                                      -                ("one two three four" & regex [rx|one (two) (three)|] . groups %~ (<> "!!") . T.toUpper)         -                `shouldBe` "one TWO!! THREE!! four"                                                              -                                                                                                                 -describe "iregex" $ do                                                                                           -    describe "match" $ do                                                                                        -        it "should allow folding with index" $ do                                                                -            ("one two three" ^.. (iregex [rx|\w+|] <. match) . withIndex)                                        -            `shouldBe` [(0, "one"), (1, "two"), (2, "three")]                                                    -                                                                                                                 -        it "should allow getting with index" $ do                                                                -            ("one two three" ^.. iregex [rx|\w+|] . index 1 . match)                                             -            `shouldBe` ["two"]                                                                                   -                                                                                                                 -        it "should allow setting with index" $ do                                                                -            ("one two three" & iregex [rx|\w+|] <. match .@~ T.pack . show)                                      -            `shouldBe` "0 1 2"                                                                                   -                                                                                                                 -        it "should allow mutating with index" $ do                                                               -            ("one two three" & iregex [rx|\w+|] <. match %@~ \i s -> (T.pack $ show i) <> ": " <> s)             -            `shouldBe` "0: one 1: two 2: three"                                                                  -                                                                                                                 -describe "igroups" $ do                                                                                          -    it "should allow folding with index" $ do                                                                    -        ("one two three four" ^.. regex [rx|(\w+) (\w+)|] . igroups . withIndex)                                 -        `shouldBe` [(0, "one"), (1, "two"), (0, "three"), (1, "four")]                                           -                                                                                                                 -    it "should allow getting a specific index" $ do                                                              -        ("one two three four" ^.. regex [rx|(\w+) (\w+)|] . igroups . index 1)                                   -        `shouldBe` ["two", "four"]                                                                               -                                                                                                                 -    it "should allow setting with index" $ do                                                                    -        ("one two three four" & regex [rx|(\w+) (\w+)|] . igroups .@~ T.pack . show)                             -        `shouldBe` "0 1 0 1"                                                                                     -                                                                                                                 -    it "should allow mutating with index" $ do                                                                   -        ("one two three four" & regex [rx|(\w+) (\w+)|] . igroups %@~ \i s -> (T.pack $ show i) <> ": " <> s)    -        `shouldBe` "0: one 1: two 0: three 1: four"                                                              -                                                                                                                 -    it "should compose indices with matches" $ do                                                                -        ("one two three four" ^.. (iregex [rx|(\w+) (\w+)|] <.> igroups) . withIndex)                            -        `shouldBe` [((0, 0), "one"), ((0, 1), "two"), ((1, 0), "three"), ((1, 1), "four")]                       -                                                                                                                 -describe "grouped" $ do                                                                                          -    it "should get all groups in batches" $ do                                                                   -        "raindrops on roses and whiskers on kittens" ^.. regex [rx|(\w+) on (\w+)|] . grouped                    -        `shouldBe` [["raindrops","roses"],["whiskers","kittens"]]                                                -    it "should allow editing when result list is the same length" $ do                                           -        ("raindrops on roses and whiskers on kittens" & regex [rx|(\w+) on (\w+)|] . grouped %~ reverse)         -        `shouldBe` "roses on raindrops and kittens on whiskers"                                                  -                                                                                                                 -describe "matchAndGroups" $ do                                                                                   -    it "should get match and groups" $ do                                                                        -        "raindrops on roses and whiskers on kittens" ^.. regex [rx|(\w+) on (\w+)|] . matchAndGroups             -        `shouldBe` [("raindrops on roses",["raindrops","roses"]),("whiskers on kittens",["whiskers","kittens"])] +            it "should find many matches" $ do+                "a b c" ^.. regex [rx|\w|] . match+                `shouldBe` ["a", "b", "c"]++            it "should fold" $ do+                "a b c" ^. regex [rx|\w|] . match+                `shouldBe` "abc"++            it "should match with a group" $ do+                "a b c" ^.. regex [rx|(\w)|] . match+                `shouldBe` ["a", "b", "c"]++            it "should match with many groups" $ do+                "a b c" ^.. regex [rx|(\w) (\w)|] . match+                `shouldBe` ["a b"]++            it "should be greedy when overlapping" $ do+                "abc" ^.. regex [rx|\w+|] . match+                `shouldBe`["abc"]++            it "should respect lazy modifiers" $ do+                "abc" ^.. regex [rx|\w+?|] . match+                `shouldBe`["a", "b", "c"]++        describe "setting" $ do+            it "should allow setting" $ do+                ("one two three" & regex [rx|two|] . match .~ "new")+                `shouldBe` "one new three"++            it "should allow setting many" $ do+                ("one <two> three" & regex [rx|\w+|] . match .~ "new")+                `shouldBe` "new <new> new"++            it "should allow mutating" $ do+                ("one two three" & regex [rx|two|] . match %~ (<> "!!"). T.toUpper)+                `shouldBe` "one TWO!! three"++            it "should allow mutating many" $ do+                ("one two three" & regex [rx|two|] . match %~ T.toUpper)+                `shouldBe` "one TWO three"++describe "iregex" $ do+    describe "match" $ do+        it "should allow folding with index" $ do+            ("one two three" ^.. (iregex [rx|\w+|] <. match) . withIndex)+            `shouldBe` [(0, "one"), (1, "two"), (2, "three")]++        it "should allow getting with index" $ do+            ("one two three" ^.. iregex [rx|\w+|] . index 1 . match)+            `shouldBe` ["two"]++        it "should allow setting with index" $ do+            ("one two three" & iregex [rx|\w+|] <. match .@~ T.pack . show)+            `shouldBe` "0 1 2"++        it "should allow mutating with index" $ do+            ("one two three" & iregex [rx|\w+|] <. match %@~ \i s -> (T.pack $ show i) <> ": " <> s)+            `shouldBe` "0: one 1: two 2: three"++describe "groups" $ do+    describe "getting" $ do+        it "should get groups" $ do+            "a b c" ^.. regex [rx|(\w)|] . groups+            `shouldBe` [["a"], ["b"], ["c"]]++        it "should get multiple groups" $ do+            "raindrops on roses and whiskers on kittens" ^.. regex [rx|(\w+) on (\w+)|] . groups+            `shouldBe` [["raindrops","roses"],["whiskers","kittens"]]++        it "should allow getting a specific index" $ do+            ("one two three four" ^.. regex [rx|(\w+) (\w+)|] . groups . ix 1)+            `shouldBe` ["two", "four"]++    describe "setting" $ do+        it "should allow setting groups as a list" $ do+            ("one two three" & regex [rx|(\w+) (\w+)|] . groups .~ ["1", "2"])+            `shouldBe` "1 2 three"++        it "should allow editing when result list is the same length" $ do+            ("raindrops on roses and whiskers on kittens" & regex [rx|(\w+) on (\w+)|] . groups %~ reverse)+            `shouldBe` "roses on raindrops and kittens on whiskers"++    describe "traversed" $ do+        it "should allow setting all group matches" $ do+            ("one two three" & regex [rx|(\w+) (\w+)|] . groups . traversed .~ "new")+            `shouldBe` "new new three"++        it "should allow mutating" $ do+            ("one two three four" & regex [rx|one (two) (three)|] . groups . traversed %~ (<> "!!") . T.toUpper)+            `shouldBe` "one TWO!! THREE!! four"++        it "should allow folding with index" $ do+            ("one two three four" ^.. regex [rx|(\w+) (\w+)|] . groups . traversed . withIndex)+            `shouldBe` [(0, "one"), (1, "two"), (0, "three"), (1, "four")]++        it "should allow setting with index" $ do+            ("one two three four" & regex [rx|(\w+) (\w+)|] . groups . traversed .@~ T.pack . show)+            `shouldBe` "0 1 0 1"++        it "should allow mutating with index" $ do+            ("one two three four" & regex [rx|(\w+) (\w+)|] . groups . traversed %@~ \i s -> (T.pack $ show i) <> ": " <> s)+            `shouldBe` "0: one 1: two 0: three 1: four"++        it "should compose indices with matches" $ do+            ("one two three four" ^.. (iregex [rx|(\w+) (\w+)|] <.> groups . traversed) . withIndex)+            `shouldBe` [((0, 0), "one"), ((0, 1), "two"), ((1, 0), "three"), ((1, 1), "four")]++describe "matchAndGroups" $ do+    it "should get match and groups" $ do+        "raindrops on roses and whiskers on kittens" ^.. regex [rx|(\w+) on (\w+)|] . matchAndGroups+        `shouldBe` [("raindrops on roses",["raindrops","roses"]),("whiskers on kittens",["whiskers","kittens"])] ```
lens-regex-pcre.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 847ca083cc4bffe2ad8319d0811ffdd549a436724924f1106c25966743c16fc6+-- hash: db3dca892f8e99d8936c709dd07b7d1a9ac11caa9f0cc2182b9367caa96e63c1  name:           lens-regex-pcre-version:        0.1.1.0+version:        0.2.0.0 description:    Please see the README on GitHub at <https://github.com/ChrisPenner/lens-regex-pcre#readme> homepage:       https://github.com/ChrisPenner/lens-regex-pcre#readme bug-reports:    https://github.com/ChrisPenner/lens-regex-pcre/issues
src/Control/Lens/Regex.hs view
@@ -4,7 +4,7 @@ Copyright   : (c) Chris Penner, 2019 License     : BSD3 -Note that all traversals in this library are not techically lawful; the break the 'multi-set'+Note that all traversals in this library are not techically lawful; they break the 'multi-set' idempotence law; in reality this isn't usually a problem; but consider yourself warned. Test your code. -} @@ -16,16 +16,18 @@ {-# LANGUAGE TemplateHaskell #-}  module Control.Lens.Regex-    ( regex+    (+    -- * Combinators+      regex     , iregex     , match     , groups-    , igroups-    , grouped     , matchAndGroups      -- * QuasiQuoter     , rx++    -- * Types     , Match     ) where @@ -34,7 +36,9 @@ import Control.Lens hiding (re, matching) import Language.Haskell.TH.Quote --- | Match represents a whole regex match; you can drill into it using 'match' or 'groups'+-- | Match represents a whole regex match; you can drill into it using 'match' or 'groups' or+-- 'matchAndGroups'+-- Consider this to be internal; don't depend on its representation. type Match = [Either Text Text] type MatchRange = (Int, Int) type GroupRanges = [(Int, Int)]@@ -45,38 +49,36 @@ rx :: QuasiQuoter rx = re --- | 'groups' but indexed by the group number. If you traverse over many matches you will--- encounter duplicate indices.--- E.g.+-- | Access all groups of a match at once. ----- > > "a 1 b 2" ^.. regex [rx|(\w) (\d)|] . igroups . withIndex--- > [(0,"a"),(1,"1"),(0,"b"),(1,"2")]+-- Note that you can edit the groups through this traversal,+-- Changing the length of the list has behaviour similar to 'partsOf'. ----- If you want only a specific group; combine this with `index`--- E.g.+-- Get all matched groups: ----- > > "a 1 b 2" ^.. regex [rx|(\w) (\d)|] . igroups . index 0--- > ["a","b"]-igroups :: IndexedTraversal' Int Match T.Text-igroups = indexing groups---- | traverse each group within a match. See 'igroups' for selecting specific groups or--- 'grouped' for handling all groups at once.-groups :: Traversal' Match T.Text-groups = traversed . _Right---- | Access all groups of a match at once.+-- > > "raindrops on roses and whiskers on kittens" ^.. regex [rx|(\w+) on (\w+)|] . groups+-- > [["raindrops","roses"],["whiskers","kittens"]] ----- Note that this uses 'partsOf'; and is only a valid traversal if you don't--- alter the length of the list. It is valid as a Fold or Getter however.+-- You can access a specific group by combining with `ix` ----- > > "raindrops on roses and whiskers on kittens" ^.. regex [rx|(\w+) on (\w+)|] . grouped--- > [["raindrops","roses"],["whiskers","kittens"]]+-- > > "raindrops on roses and whiskers on kittens" ^.. regex [rx|(\w+) on (\w+)|] . groups .  ix 1+-- > ["roses", "kittens"] ----- > > "raindrops on roses and whiskers on kittens" & regex [rx|(\w+) on (\w+)|] . grouped %~ reverse+-- @groups@ is a traversal; you can mutate matches through it.+-- > > "raindrops on roses and whiskers on kittens" & regex [rx|(\w+) on (\w+)|] . groups .  ix 1 %~ T.toUpper+-- > "raindrops on ROSES and whiskers on KITTENS"+--+-- Editing the list rearranges groups+--+-- > > "raindrops on roses and whiskers on kittens" & regex [rx|(\w+) on (\w+)|] . groups %~ reverse -- > "roses on raindrops and kittens on whiskers"-grouped :: Traversal' Match [T.Text]-grouped = partsOf (traversed . _Right)+--+-- You can traverse the list to flatten out all groups+--+-- > > "raindrops on roses and whiskers on kittens" ^.. regex [rx|(\w+) on (\w+)|] . groups . traversed+-- > ["raindrops","roses","whiskers","kittens"]+groups :: Traversal' Match [T.Text]+groups = partsOf (traversed . _Right)  -- | Traverse each match as a whole --@@ -112,7 +114,7 @@ -- -- Getting groups with their group index. ----- > > "1/2 and 3/4" ^.. regex [rx|(\d+)/(\d+)|] . igroups . withIndex+-- > > "1/2 and 3/4" ^.. regex [rx|(\d+)/(\d+)|] . groups . traversed . withIndex -- > [(0,"1"),(1,"2"),(0,"3"),(1,"4")] -- -- Check for any matches:@@ -127,7 +129,7 @@ -- -- Get the third match ----- > >  "alpha beta charlie delta" ^? (iregex [rx|\w+|] . index 2 . match)+-- > > "alpha beta charlie delta" ^? (iregex [rx|\w+|] . index 2 . match) -- > Just "charlie" -- -- Replace the third match@@ -140,15 +142,18 @@ -- > > "Monday: 29, Tuesday: 99, Wednesday: 3" & partsOf' (iregex [rx|\d+|] . match . unpacked . _Show @Int) %~ sort -- > "Monday: 3, Tuesday: 29, Wednesday: 99" regex :: Regex -> Traversal' T.Text Match-regex pattern f txt =  collapse <$> apply (fmap splitAgain <$> splitter txt matches)+regex pattern f txt =  collapseMatch <$> apply (fmap splitAgain <$> splitter txt matches)   where     matches :: [(MatchRange, GroupRanges)]     matches = scanRanges pattern txt-    collapse :: [Either Text [Either Text Text]] -> Text-    collapse xs = xs ^. folded . beside id (traversed . chosen)+    collapseMatch :: [Either Text [Either Text Text]] -> Text+    collapseMatch xs = xs ^. folded . beside id (traversed . chosen)     -- apply :: [Either Text [Either Text Text]] -> _ [Either Text [Either Text Text]]     apply xs = xs & traversed . _Right %%~ f +matchText :: Match -> T.Text+matchText m = m ^. traversed . chosen+ -- | Collect both the match text AND all the matching groups -- -- > > "raindrops on roses and whiskers on kittens" ^.. regex [rx|(\w+) on (\w+)|] . matchAndGroups@@ -156,7 +161,29 @@ -- > , ("whiskers on kittens", ["whiskers","kittens"]) -- > ] matchAndGroups :: Getter Match (T.Text, [T.Text])-matchAndGroups = to $ \m -> (m ^. traversed . chosen, m ^. grouped)+matchAndGroups = to $ \m -> (matchText m, m ^. groups)++-- | This allows you to "stash" the match text into an index for use later in the traversal.+-- This is a slight abuse of indices; but it can sometimes be handy. This allows you to+-- have the full match in scope when editing groups using indexed combinators.+--+-- If you're viewing or folding you should probably just use 'matchAndGroups'.+--+-- > > [(["raindrops","roses"],"raindrops on roses"),(["whiskers","kittens"],"whiskers on kittens")]+-- > "raindrops on roses and whiskers on kittens" ^.. regex [rx|(\w+) on (\w+)|] . (withGroups <. match) . withIndex+withMatch :: IndexedTraversal' T.Text Match Match+withMatch p mtch = indexed p (matchText mtch) mtch++-- | This allows you to "stash" the match text into an index for use later in the traversal.+-- This is a slight abuse of indices; but it can sometimes be handy. This allows you to+-- have the full match in scope when editing groups using indexed combinators.+--+-- If you're viewing or folding you should probably just use 'matchAndGroups'.+--+-- > > "raindrops on roses and whiskers on kittens" ^.. regex [rx|(\w+) on (\w+)|] . (withMatch <. groups) . withIndex+-- > [("raindrops on roses",["raindrops","roses"]),("whiskers on kittens",["whiskers","kittens"])]+withGroups :: IndexedTraversal' [T.Text] Match Match+withGroups p mtch = indexed p (mtch ^. groups) mtch  splitter :: Text -> [(MatchRange, GroupRanges)] -> [Either T.Text (T.Text, GroupRanges)] splitter t [] | T.null t = []
test/Spec.hs view
@@ -55,33 +55,6 @@                     ("one two three" & regex [rx|two|] . match %~ T.toUpper)                     `shouldBe` "one TWO three" -        describe "groups" $ do-            describe "getting" $ do-                it "should get a group" $ do-                    "a b c" ^.. regex [rx|(\w)|] . groups-                    `shouldBe` ["a", "b", "c"]--                it "should get many groups" $ do-                    "one two three" ^.. regex [rx|(\w+) (\w+)|] . groups-                    `shouldBe` ["one", "two"]--            describe "setting" $ do-                it "should allow setting" $ do-                    ("one two three" & regex [rx|(\w+) (\w+)|] . groups .~ "new")-                    `shouldBe` "new new three"--                it "should allow setting many" $ do-                    ("one two three four" & regex [rx|(\w+) (\w+)|] . groups .~ "new")-                    `shouldBe` "new new new new"--                it "should allow mutating" $ do-                    ("one two three four" & regex [rx|one (two) three|] . groups %~ (<> "!!") . T.toUpper)-                    `shouldBe` "one TWO!! three four"--                it "should allow mutating" $ do-                    ("one two three four" & regex [rx|one (two) (three)|] . groups %~ (<> "!!") . T.toUpper)-                    `shouldBe` "one TWO!! THREE!! four"-     describe "iregex" $ do         describe "match" $ do             it "should allow folding with index" $ do@@ -100,34 +73,53 @@                 ("one two three" & iregex [rx|\w+|] <. match %@~ \i s -> (T.pack $ show i) <> ": " <> s)                 `shouldBe` "0: one 1: two 2: three" -    describe "igroups" $ do-        it "should allow folding with index" $ do-            ("one two three four" ^.. regex [rx|(\w+) (\w+)|] . igroups . withIndex)-            `shouldBe` [(0, "one"), (1, "two"), (0, "three"), (1, "four")]+    describe "groups" $ do+        describe "getting" $ do+            it "should get groups" $ do+                "a b c" ^.. regex [rx|(\w)|] . groups+                `shouldBe` [["a"], ["b"], ["c"]] -        it "should allow getting a specific index" $ do-            ("one two three four" ^.. regex [rx|(\w+) (\w+)|] . igroups . index 1)-            `shouldBe` ["two", "four"]+            it "should get multiple groups" $ do+                "raindrops on roses and whiskers on kittens" ^.. regex [rx|(\w+) on (\w+)|] . groups+                `shouldBe` [["raindrops","roses"],["whiskers","kittens"]] -        it "should allow setting with index" $ do-            ("one two three four" & regex [rx|(\w+) (\w+)|] . igroups .@~ T.pack . show)-            `shouldBe` "0 1 0 1"+            it "should allow getting a specific index" $ do+                ("one two three four" ^.. regex [rx|(\w+) (\w+)|] . groups . ix 1)+                `shouldBe` ["two", "four"] -        it "should allow mutating with index" $ do-            ("one two three four" & regex [rx|(\w+) (\w+)|] . igroups %@~ \i s -> (T.pack $ show i) <> ": " <> s)-            `shouldBe` "0: one 1: two 0: three 1: four"+        describe "setting" $ do+            it "should allow setting groups as a list" $ do+                ("one two three" & regex [rx|(\w+) (\w+)|] . groups .~ ["1", "2"])+                `shouldBe` "1 2 three" -        it "should compose indices with matches" $ do-            ("one two three four" ^.. (iregex [rx|(\w+) (\w+)|] <.> igroups) . withIndex)-            `shouldBe` [((0, 0), "one"), ((0, 1), "two"), ((1, 0), "three"), ((1, 1), "four")]+            it "should allow editing when result list is the same length" $ do+                ("raindrops on roses and whiskers on kittens" & regex [rx|(\w+) on (\w+)|] . groups %~ reverse)+                `shouldBe` "roses on raindrops and kittens on whiskers" -    describe "grouped" $ do-        it "should get all groups in batches" $ do-            "raindrops on roses and whiskers on kittens" ^.. regex [rx|(\w+) on (\w+)|] . grouped-            `shouldBe` [["raindrops","roses"],["whiskers","kittens"]]-        it "should allow editing when result list is the same length" $ do-            ("raindrops on roses and whiskers on kittens" & regex [rx|(\w+) on (\w+)|] . grouped %~ reverse)-            `shouldBe` "roses on raindrops and kittens on whiskers"+        describe "traversed" $ do+            it "should allow setting all group matches" $ do+                ("one two three" & regex [rx|(\w+) (\w+)|] . groups . traversed .~ "new")+                `shouldBe` "new new three"++            it "should allow mutating" $ do+                ("one two three four" & regex [rx|one (two) (three)|] . groups . traversed %~ (<> "!!") . T.toUpper)+                `shouldBe` "one TWO!! THREE!! four"++            it "should allow folding with index" $ do+                ("one two three four" ^.. regex [rx|(\w+) (\w+)|] . groups . traversed . withIndex)+                `shouldBe` [(0, "one"), (1, "two"), (0, "three"), (1, "four")]++            it "should allow setting with index" $ do+                ("one two three four" & regex [rx|(\w+) (\w+)|] . groups . traversed .@~ T.pack . show)+                `shouldBe` "0 1 0 1"++            it "should allow mutating with index" $ do+                ("one two three four" & regex [rx|(\w+) (\w+)|] . groups . traversed %@~ \i s -> (T.pack $ show i) <> ": " <> s)+                `shouldBe` "0: one 1: two 0: three 1: four"++            it "should compose indices with matches" $ do+                ("one two three four" ^.. (iregex [rx|(\w+) (\w+)|] <.> groups . traversed) . withIndex)+                `shouldBe` [((0, 0), "one"), ((0, 1), "two"), ((1, 0), "three"), ((1, 1), "four")]      describe "matchAndGroups" $ do         it "should get match and groups" $ do