diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,13 +1,16 @@
 # Changelog for lens-regex-pcre
 
-# 2.0.0 
+# 0.3.0.0 
+Unify `iregex` into `regex` as a single indexed traversal
+
+# 0.2.0.0 
 Unify `grouped`, `groups`, and `igroups` into just `groups` with optional traversal
 
-# 1.1.0 
+# 0.1.1.0 
 Adds `grouped` and `matchAndGroups`
 
-# 1.0.1 
+# 0.1.0.1 
 Doc fixes
 
-# 1.0.0 
+# 0.1.0.0 
 Initial Release
diff --git a/lens-regex-pcre.cabal b/lens-regex-pcre.cabal
--- a/lens-regex-pcre.cabal
+++ b/lens-regex-pcre.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: db3dca892f8e99d8936c709dd07b7d1a9ac11caa9f0cc2182b9367caa96e63c1
+-- hash: a626a534d16f0bea96536315430d586eea2fc04b175395c0047b63268c10fbca
 
 name:           lens-regex-pcre
-version:        0.2.0.0
+version:        0.3.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
diff --git a/src/Control/Lens/Regex.hs b/src/Control/Lens/Regex.hs
--- a/src/Control/Lens/Regex.hs
+++ b/src/Control/Lens/Regex.hs
@@ -19,23 +19,36 @@
     (
     -- * Combinators
       regex
-    , iregex
     , match
     , groups
     , matchAndGroups
 
-    -- * QuasiQuoter
+    -- * Compiling regex
     , rx
+    , mkRegexQQ
+    , compile
+    , compileM
 
     -- * Types
     , Match
+    , Regex
     ) where
 
 import Data.Text as T hiding (index)
 import Text.Regex.PCRE.Heavy
+import Text.Regex.PCRE.Light (compile)
 import Control.Lens hiding (re, matching)
+import Data.Data (Data)
+import Data.Data.Lens (biplate)
 import Language.Haskell.TH.Quote
 
+-- $setup
+-- >>> :set -XQuasiQuotes
+-- >>> :set -XOverloadedStrings
+-- >>> :set -XTypeApplications
+-- >>> import Data.Text.Lens (unpacked)
+-- >>> import Data.List (sort)
+
 -- | 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.
@@ -43,12 +56,6 @@
 type MatchRange = (Int, Int)
 type GroupRanges = [(Int, Int)]
 
--- | 'QuasiQuoter' for compiling regexes.
--- This is just 're' re-exported under a different name so as not to conflict with @re@ from
--- 'Control.Lens'
-rx :: QuasiQuoter
-rx = re
-
 -- | Access all groups of a match at once.
 --
 -- Note that you can edit the groups through this traversal,
@@ -56,93 +63,104 @@
 --
 -- Get all matched groups:
 --
--- > > "raindrops on roses and whiskers on kittens" ^.. regex [rx|(\w+) on (\w+)|] . groups
--- > [["raindrops","roses"],["whiskers","kittens"]]
+-- >>> "raindrops on roses and whiskers on kittens" ^.. regex [rx|(\w+) on (\w+)|] . groups
+-- [["raindrops","roses"],["whiskers","kittens"]]
 --
 -- You can access a specific group by combining with `ix`
 --
--- > > "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+)|] . groups .  ix 1
+-- ["roses","kittens"]
 --
 -- @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"
 --
+-- >>> "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"
+-- >>> "raindrops on roses and whiskers on kittens" & regex [rx|(\w+) on (\w+)|] . groups %~ Prelude.reverse
+-- "roses on raindrops and kittens on whiskers"
 --
 -- 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"]
+-- >>> "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
+-- | Traverse each match
 --
--- Use with 'regex' or 'iregex'
+--  Get a match if one exists:
 --
--- > > "one _two_ three _four_" ^.. regex [rx|_\w+_|] . match
--- > ["_two_","_four_"]
+-- >>> "find a needle in a haystack" ^? regex [rx|n..dle|] . match
+-- Just "needle"
 --
+--  Collect all matches
+--
+-- >>> "one _two_ three _four_" ^.. regex [rx|_\w+_|] . match
+-- ["_two_","_four_"]
+--
 -- You can edit the traversal to perform a regex replace/substitution
 --
--- > > "one _two_ three _four_" & regex [rx|_\w+_|] . match %~ T.toUpper
--- > "one _TWO_ three _FOUR_"
+-- >>> "one _two_ three _four_" & regex [rx|_\w+_|] . match %~ T.toUpper
+-- "one _TWO_ three _FOUR_"
 match :: Traversal' Match T.Text
 match f grps = (:[]) . Right <$> f (grps ^. traversed . chosen)
 
--- | Indexed version of 'regex'.
-iregex :: Regex -> IndexedTraversal' Int T.Text Match
-iregex pattern = indexing (regex pattern)
-
 -- | The base combinator for doing regex searches.
 -- It's a traversal which selects 'Match'es; you can compose it with 'match' or 'groups'
 -- to get the relevant parts of your match.
 --
--- Getting all matches:
+-- >>> txt = "raindrops on roses and whiskers on kittens" :: Text
 --
--- > > "one _two_ three _four_" ^.. regex [rx|_\w+_|] . match
--- > ["_two_","_four_"]
+-- Search
 --
--- Regex replace/mutation
+-- >>> has (regex [rx|whisk|]) txt
+-- True
 --
--- > > "one _two_ three _four_" & regex [rx|_\w+_|] . match %~ T.toUpper
--- > "one _TWO_ three _FOUR_"
+-- Get matches
 --
--- Getting groups with their group index.
+-- >>> txt ^.. regex [rx|\br\w+|] . match
+-- ["raindrops","roses"]
 --
--- > > "1/2 and 3/4" ^.. regex [rx|(\d+)/(\d+)|] . groups . traversed . withIndex
--- > [(0,"1"),(1,"2"),(0,"3"),(1,"4")]
+-- Edit matches
 --
--- Check for any 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"
 --
--- > > has (regex [rx|ne+dle|]) "a needle in a haystack"
--- > True
+-- Get Groups
 --
--- Check for matches which also match a predicate:
+-- >>> txt ^.. regex [rx|(\w+) on (\w+)|] . groups
+-- [["raindrops","roses"],["whiskers","kittens"]]
 --
--- > > has (regex [rx|\w+|] . match . filtered ((> 7) . T.length)) "one word here is loooooooong"
--- > True
+-- Edit Groups
 --
--- Get the third match
+-- >>> txt & regex [rx|(\w+) on (\w+)|] . groups %~ Prelude.reverse
+-- "roses on raindrops and kittens on whiskers"
 --
--- > > "alpha beta charlie delta" ^? (iregex [rx|\w+|] . index 2 . match)
--- > Just "charlie"
+-- Get the third match
 --
--- Replace the third match
+-- >>> txt ^? regex [rx|\w+|] . index 2 . match
+-- Just "roses"
 --
--- > > "alpha beta charlie delta" & (iregex [rx|\w+|] . index 2 . match) .~ "GAMMA"
--- > "alpha beta GAMMA delta"
+-- Match integers, 'Read' them into ints, then sort them in-place
+-- dumping them back into the source text afterwards.
 --
--- Match integers, 'Read' them into ints, then sort each match in-place
+-- >>> "Monday: 29, Tuesday: 99, Wednesday: 3" & partsOf (regex [rx|\d+|] . match . unpacked . _Show @Int) %~ sort
+-- "Monday: 3, Tuesday: 29, Wednesday: 99"
 --
--- > > "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 =  collapseMatch <$> apply (fmap splitAgain <$> splitter txt matches)
+-- To alter behaviour of the regex you may wish to pass 'PCREOption's when compiling it.
+-- The default behaviour may seem strange in certain cases; e.g. it operates in 'single-line'
+-- mode. You can 'compile' the 'Regex' separately and add any options you like, then pass the resulting
+-- 'Regex' into 'regex';
+-- Alternatively can make your own version of the QuasiQuoter with any options you want embedded
+-- by using 'mkRegexQQ'.
+regex :: Regex -> IndexedTraversal' Int T.Text Match
+regex pattern = indexing (regexT pattern)
+
+-- | Base regex traversal. Used only to define 'regex'
+regexT :: Regex -> Traversal' T.Text Match
+regexT pattern f txt = collapseMatch <$> apply (fmap splitAgain <$> splitter txt matches)
   where
     matches :: [(MatchRange, GroupRanges)]
     matches = scanRanges pattern txt
@@ -151,26 +169,32 @@
     -- 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
--- > [ ("raindrops on roses", ["raindrops","roses"])
--- > , ("whiskers on kittens", ["whiskers","kittens"])
--- > ]
+-- >>> "raindrops on roses and whiskers on kittens" ^.. regex [rx|(\w+) on (\w+)|] . matchAndGroups
+-- [("raindrops on roses",["raindrops","roses"]),("whiskers on kittens",["whiskers","kittens"])]
 matchAndGroups :: Getter Match (T.Text, [T.Text])
 matchAndGroups = to $ \m -> (matchText m, m ^. groups)
 
+-- | 'QuasiQuoter' for compiling regexes.
+-- This is just 're' re-exported under a different name so as not to conflict with @re@ from
+-- 'Control.Lens'
+rx :: QuasiQuoter
+rx = re
+
 -- | 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
+-- >>> "raindrops on roses and whiskers on kittens" ^.. regex [rx|(\w+) on (\w+)|] . (withGroups <. match) . withIndex
+-- [(["raindrops","roses"],"raindrops on roses"),(["whiskers","kittens"],"whiskers on kittens")]
+--
 withMatch :: IndexedTraversal' T.Text Match Match
 withMatch p mtch = indexed p (matchText mtch) mtch
 
@@ -180,18 +204,24 @@
 --
 -- 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"])]
+-- >>> "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
 
+-- split up text into matches paired with groups; Left is unmatched text
 splitter :: Text -> [(MatchRange, GroupRanges)] -> [Either T.Text (T.Text, GroupRanges)]
-splitter t [] | T.null t = []
-              | otherwise = [Left t]
-splitter t (((start, end), grps) : rest) = do
+splitter t [] = wrapIfNotEmpty t
+splitter t (((start, end), grps) : rest) =
     splitOnce t ((start, end), grps)
-        <> splitter (T.drop end t) (rest & traversed . beside both (traversed . both) -~ end)
+    <> splitter (T.drop end t) (subtractFromAll end rest)
 
+splitOnce :: Text -> (MatchRange, GroupRanges) -> [Either T.Text (T.Text, GroupRanges)]
+splitOnce t ((start, end), grps) = do
+    let (before, mid) = T.splitAt start t
+    let focused = T.take (end - start) mid
+    wrapIfNotEmpty before <> [Right (focused, subtractFromAll start grps)]
+
 splitAgain :: (T.Text, GroupRanges) -> Match
 splitAgain (t, []) | T.null t = []
                    | otherwise = [Left t]
@@ -200,14 +230,11 @@
     let focused = T.take (end - start) mid
     wrapIfNotEmpty before
         <> [Right focused]
-        <> splitAgain ((T.drop end t), (rest & traversed . both -~ end))
+        <> splitAgain ((T.drop end t), (subtractFromAll end rest))
 
-splitOnce :: Text -> (MatchRange, GroupRanges) -> [Either T.Text (T.Text, GroupRanges)]
-splitOnce t ((start, end), grps) = do
-    let (before, mid) = T.splitAt start t
-    let focused = T.take (end - start) mid
-    wrapIfNotEmpty before
-      <> [Right (focused, grps & traversed . both -~ start)]
+--- helpers
+subtractFromAll :: (Data b) => Int -> b -> b
+subtractFromAll n = biplate -~ n
 
 wrapIfNotEmpty :: Text -> [Either Text a]
 wrapIfNotEmpty txt
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -55,22 +55,21 @@
                     ("one two three" & regex [rx|two|] . match %~ T.toUpper)
                     `shouldBe` "one TWO three"
 
-    describe "iregex" $ do
-        describe "match" $ do
+        describe "indexed" $ do
             it "should allow folding with index" $ do
-                ("one two three" ^.. (iregex [rx|\w+|] <. match) . withIndex)
+                ("one two three" ^.. (regex [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)
+                ("one two three" ^.. regex [rx|\w+|] . index 1 . match)
                 `shouldBe` ["two"]
 
             it "should allow setting with index" $ do
-                ("one two three" & iregex [rx|\w+|] <. match .@~ T.pack . show)
+                ("one two three" & regex [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)
+                ("one two three" & regex [rx|\w+|] <. match %@~ \i s -> (T.pack $ show i) <> ": " <> s)
                 `shouldBe` "0: one 1: two 2: three"
 
     describe "groups" $ do
@@ -87,6 +86,10 @@
                 ("one two three four" ^.. regex [rx|(\w+) (\w+)|] . groups . ix 1)
                 `shouldBe` ["two", "four"]
 
+            xit "should handle weird group alternation" $ do
+                "1:2 a=b" ^.. regex [rx|(\d):(\d)|(\w)=(\w)|] . match
+                `shouldBe` ["not entirely sure what I expect this to be yet"]
+
         describe "setting" $ do
             it "should allow setting groups as a list" $ do
                 ("one two three" & regex [rx|(\w+) (\w+)|] . groups .~ ["1", "2"])
@@ -118,7 +121,7 @@
                 `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)
+                ("one two three four" ^.. (regex [rx|(\w+) (\w+)|] <.> groups . traversed) . withIndex)
                 `shouldBe` [((0, 0), "one"), ((0, 1), "two"), ((1, 0), "three"), ((1, 1), "four")]
 
     describe "matchAndGroups" $ do
