diff --git a/Bench.hs b/Bench.hs
--- a/Bench.hs
+++ b/Bench.hs
@@ -3,22 +3,22 @@
 module Main where
 
 import Text.Regex.PCRE.Rex
-import Test
+import qualified Demo
 
 import Criterion.Main
 
 addEm :: Int -> [Double]
-addEm n = map math $
+addEm n = map Demo.math $
   zipWith (++)
     (zipWith (++) (map show [1..n])
     (concat $ repeat ["+", "/", "-", "*"]))
   (map show [100..])
 
-peanoize n = map (\i -> peano . (++"Z") . concat $ replicate i "S ") [0..n]
+peanoize n = map (\i -> Demo.peano . (++"Z") . concat $ replicate i "S ") [0..n]
 
-testPairs n = [parsePair $ "<" ++ replicate i ' ' ++ "a, pair>" | i <- [0..n]]
+testPairs n = [Demo.parsePair $ "<" ++ replicate i ' ' ++ "a, pair>" | i <- [0..n]]
 
-testDate n = [parseDate $ show i ++ ".10.20" | i <- [1900 .. 1900 + n]]
+testDate n = [Demo.parseDate $ show i ++ ".10.20" | i <- [1900 .. 1900 + n]]
 
 --NOTE: benchmark time includes test generation
 
diff --git a/CHANGES.md b/CHANGES.md
new file mode 100644
--- /dev/null
+++ b/CHANGES.md
@@ -0,0 +1,25 @@
+0.1: Jul 25 2011
+----------------
+  * initial release
+
+0.2: Sep 24 2011
+----------------
+  * Added custom configuration of PCRE options.
+  * Added non-precompiling quasiquoters.
+  * Fixed a bug where patterns with no captures would fail.
+  * Decided to remove the defaulting to 'read' - too much magic.
+
+0.3: Sep 25 2011
+  * Fixed a capture indexing bug, where capture fields which aren't bound would
+    cause subsequent bound captures to be incorrect.
+  * Above bug fix actually neatened up code.
+  * Added configuration of default mapping pattern.
+
+0.4: Oct 11 2012
+----------------
+  * Made configuration into a datatype.
+
+0.4.1: Feb 4 2013
+------------------
+  * Precompilation bugs fixed by [takano-akio](https://github.com/takano-akio)!
+    Now precompilation is on by default.
diff --git a/Demo.hs b/Demo.hs
new file mode 100644
--- /dev/null
+++ b/Demo.hs
@@ -0,0 +1,71 @@
+{-# LANGUAGE TemplateHaskell, QuasiQuotes, ViewPatterns #-}
+
+module Demo where
+
+import Text.Regex.PCRE.Rex
+
+import qualified Data.ByteString.Char8 as B
+import Data.Maybe (catMaybes, isJust)
+
+main =
+  do demonstrate "math"      math      "1 + 3"
+     demonstrate "math"      math      "3 * 2 + 100"
+     demonstrate "math"      math      "20 / 3 + 100 * 2"
+     demonstrate "peano"     peano     "S Z"
+     demonstrate "peano"     peano     "S S S S Z"
+     demonstrate "peano"     peano     "S   S   Z"
+     demonstrate "parsePair" parsePair "<-1, 3>"
+     demonstrate "parsePair" parsePair "<-4,3b0>"
+     demonstrate "parsePair" parsePair "< a,  -30 >"
+     demonstrate "parsePair" parsePair "< a,  other>"
+     demonstrate "parseDate" parseDate "1993.8.10"
+     demonstrate "parseDate" parseDate "1993.08.10"
+     demonstrate "parseDate" parseDate "2003.02.28"
+     demonstrate "parseDate" parseDate "2004.02.28"
+     demonstrate "parseDate" parseDate "2003.02.27"
+     demonstrate "disjunct"  disjunct  "a"
+     demonstrate "disjunct"  disjunct  "ab"
+     demonstrate "disjunct"  disjunct  "abc"
+     print $ "btest: " ++ show btest
+
+demonstrate n f input = putStrLn $ n ++ " \"" ++ input ++ "\" == " ++ show (f input)
+
+math x = mathl x 0
+
+mathl [] x = x
+mathl [rex|^  \s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s y
+mathl [rex|^\+\s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s $ x + y
+mathl [rex|^ -\s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s $ x - y
+mathl [rex|^\*\s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s $ x * y
+mathl [rex|^ /\s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s $ x / y
+mathl str x = error str
+
+peano :: String -> Maybe Int
+peano = [rex|^(?{ length . filter (=='S') } \s* (?:S\s+)*Z)\s*$|]
+
+parsePair :: String -> Maybe (String, String)
+parsePair = [rex|^<\s* (?{ }[^\s,>]+) \s*,\s* (?{ }[^\s,>]+) \s*>$|]
+
+-- From http://www.regular-expressions.info/dates.html
+parseDate :: String -> Maybe (Int, Int, Int)
+parseDate [rex|^(?{ read -> y }(?:19|20)\d\d)[- /.]
+                (?{ read -> m }0[1-9]|1[012])[- /.]
+                (?{ read -> d }0[1-9]|[12][0-9]|3[01])$|]
+  |  (d > 30 && (m `elem` [4, 6, 9, 11]))
+  || (m == 2 &&
+       (d ==29 && not (mod y 4 == 0 && (mod y 100 /= 0 || mod y 400 == 0)))
+    || (d > 29)) = Nothing
+  | otherwise = Just (y, m, d)
+parseDate _ = Nothing
+
+onNull a f [] = a
+onNull _ f xs = f xs
+
+nonNull = onNull Nothing
+
+disjunct [rex| ^(?:(?{nonNull $ Just . head -> a} .)
+             | (?{nonNull $ Just . head -> b} ..)
+             | (?{nonNull $ Just . last -> c} ...))$|] =
+  head $ catMaybes [a, b, c]
+
+btest = [brex|(?{}hello)|] (B.pack "hello") == Just (B.pack "hello")
diff --git a/README b/README
deleted file mode 100644
--- a/README
+++ /dev/null
@@ -1,79 +0,0 @@
-http://hackage.haskell.org/package/rex
-
-Provides a quasi-quoter for regular expressions which yields a tuple, of 
-appropriate arity and types, representing the results of the captures.  Allows 
-the user to specify parsers for captures as inline Haskell.  Can also be used to
-provide typeful pattern matching in function definitions and case patterns.
-
-To build / install:
-
-./Setup.hs configure --user
-./Setup.hs build
-./Setup.hs install
-
-See the haddock or Text/Regex/PCRE/QQT.hs for documentation.
-
-Some examples (verbatim from Test.hs):
-
-  math x = mathl x 0
-
-  mathl [] x = x
-  mathl [rex|^  \s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s y
-  mathl [rex|^\+\s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s $ x + y
-  mathl [rex|^ -\s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s $ x - y
-  mathl [rex|^\*\s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s $ x * y
-  mathl [rex|^ /\s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s $ x / y
-  mathl str x = error str
-
-
--- math "1 + 3" == 4.0
--- math "3 * 2 + 100" == 106.0
--- math "20 / 3 + 100 * 2" == 213.33333333333334
-
-
-  peano :: String -> Maybe Int
-  peano = [rex|^(?{ length . filter (=='S') } \s* (?:S\s+)*Z)\s*$|]
-
---  peano "S Z" == Just 1
---  peano "S S S S Z" == Just 4
---  peano "S   S   Z" == Just 2
-
-  parsePair :: String -> Maybe (String, String)
-  parsePair = [rex|^<\s* (?{ }[^\s,>]+) \s*,\s* (?{ }[^\s,>]+) \s*>$|]
-
---  parsePair "<-1, 3>" == Just ("-1","3")
---  parsePair "<-4,3b0>" == Just ("-4","3b0")
---  parsePair "< a,  -30 >" == Just ("a","-30")
---  parsePair "< a,  other>" == Just ("a","other")
-
-
--- From http://www.regular-expressions.info/dates.html
-  parseDate :: String -> Maybe (Int, Int, Int)
-  parseDate [rex|^(?{ read -> y }(?:19|20)\d\d)[- /.]
-                  (?{ read -> m }0[1-9]|1[012])[- /.]
-                  (?{ read -> d }0[1-9]|[12][0-9]|3[01])$|]
-    |  (d > 30 && (m `elem` [4, 6, 9, 11]))
-    || (m == 2 &&
-         (d ==29 && not (mod y 4 == 0 && (mod y 100 /= 0 || mod y 400 == 0)))
-      || (d > 29)) = Nothing
-    | otherwise = Just (y, m, d)
-  parseDate _ = Nothing
-
---  parseDate "1993.8.10" == Nothing
---  parseDate "1993.08.10" == Just (1993,8,10)
---  parseDate "2003.02.28" == Just (2003,2,28)
---  parseDate "2003.02.27" == Just (2003,2,27)
-
-  onNull a f [] = a
-  onNull _ f xs = f xs
-
-  nonNull = onNull Nothing
-
-  disjunct [rex| ^(?:(?{nonNull $ Just . head -> a} .)
-               | (?{nonNull $ Just . head -> b} ..)
-               | (?{nonNull $ Just . last -> c} ...))$|] =
-    head $ catMaybes [a, b, c]
-
---  disjunct "a" == 'a'
---  disjunct "ab" == 'a'
---  disjunct "abc" == 'c'
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,90 @@
+http://hackage.haskell.org/package/rex
+
+Provides a quasi-quoter for regular expressions which yields a tuple, of 
+appropriate arity and types, representing the results of the captures.  Allows 
+the user to specify parsers for captures as inline Haskell.  Can also be used to
+provide typeful pattern matching in function definitions and case patterns.
+
+To build / install:
+
+```
+./Setup.hs configure --user
+./Setup.hs build
+./Setup.hs install
+```
+
+See the haddock or `Text/Regex/PCRE/Rex.hs` for documentation.
+
+Some examples (verbatim from Test.hs):
+
+```haskell
+math x = mathl x 0
+
+mathl [] x = x
+mathl [rex|^  \s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s y
+mathl [rex|^\+\s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s $ x + y
+mathl [rex|^ -\s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s $ x - y
+mathl [rex|^\*\s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s $ x * y
+mathl [rex|^ /\s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s $ x / y
+mathl str x = error str
+
+-- math "1 + 3" == 4.0
+-- math "3 * 2 + 100" == 106.0
+-- math "20 / 3 + 100 * 2" == 213.33333333333334
+```
+
+
+```haskell
+peano :: String -> Maybe Int
+peano = [rex|^(?{ length . filter (=='S') } \s* (?:S\s+)*Z)\s*$|]
+
+--  peano "S Z" == Just 1
+--  peano "S S S S Z" == Just 4
+--  peano "S   S   Z" == Just 2
+```
+
+```haskell
+parsePair :: String -> Maybe (String, String)
+parsePair = [rex|^<\s* (?{ }[^\s,>]+) \s*,\s* (?{ }[^\s,>]+) \s*>$|]
+
+--  parsePair "<-1, 3>" == Just ("-1","3")
+--  parsePair "<-4,3b0>" == Just ("-4","3b0")
+--  parsePair "< a,  -30 >" == Just ("a","-30")
+--  parsePair "< a,  other>" == Just ("a","other")
+```
+
+
+```haskell
+-- From http://www.regular-expressions.info/dates.html
+parseDate :: String -> Maybe (Int, Int, Int)
+parseDate [rex|^(?{ read -> y }(?:19|20)\d\d)[- /.]
+                (?{ read -> m }0[1-9]|1[012])[- /.]
+                (?{ read -> d }0[1-9]|[12][0-9]|3[01])$|]
+  |  (d > 30 && (m `elem` [4, 6, 9, 11]))
+  || (m == 2 &&
+       (d ==29 && not (mod y 4 == 0 && (mod y 100 /= 0 || mod y 400 == 0)))
+    || (d > 29)) = Nothing
+  | otherwise = Just (y, m, d)
+parseDate _ = Nothing
+
+--  parseDate "1993.8.10" == Nothing
+--  parseDate "1993.08.10" == Just (1993,8,10)
+--  parseDate "2003.02.28" == Just (2003,2,28)
+--  parseDate "2003.02.27" == Just (2003,2,27)
+```
+
+```haskell
+onNull a f [] = a
+onNull _ f xs = f xs
+
+nonNull = onNull Nothing
+
+disjunct [rex| ^(?:(?{nonNull $ Just . head -> a} .)
+             | (?{nonNull $ Just . head -> b} ..)
+             | (?{nonNull $ Just . last -> c} ...))$|] =
+  head $ catMaybes [a, b, c]
+
+--  disjunct "a" == 'a'
+--  disjunct "ab" == 'a'
+--  disjunct "abc" == 'c'
+```
diff --git a/Test.hs b/Test.hs
deleted file mode 100644
--- a/Test.hs
+++ /dev/null
@@ -1,70 +0,0 @@
-{-# LANGUAGE TemplateHaskell, QuasiQuotes, ViewPatterns #-}
-
-module Test where
-
-import Text.Regex.PCRE.Rex
-
-import qualified Data.ByteString.Char8 as B
-import Data.Maybe (catMaybes, isJust)
-
-demo =
-  do demonstrate "math"      math      "1 + 3"
-     demonstrate "math"      math      "3 * 2 + 100"
-     demonstrate "math"      math      "20 / 3 + 100 * 2"
-     demonstrate "peano"     peano     "S Z"
-     demonstrate "peano"     peano     "S S S S Z"
-     demonstrate "peano"     peano     "S   S   Z"
-     demonstrate "parsePair" parsePair "<-1, 3>"
-     demonstrate "parsePair" parsePair "<-4,3b0>"
-     demonstrate "parsePair" parsePair "< a,  -30 >"
-     demonstrate "parsePair" parsePair "< a,  other>"
-     demonstrate "parseDate" parseDate "1993.8.10"
-     demonstrate "parseDate" parseDate "1993.08.10"
-     demonstrate "parseDate" parseDate "2003.02.28"
-     demonstrate "parseDate" parseDate "2003.02.27"
-     demonstrate "disjunct"  disjunct  "a"
-     demonstrate "disjunct"  disjunct  "ab"
-     demonstrate "disjunct"  disjunct  "abc"
-     print $ "btest: " ++ show btest
-
-demonstrate n f input = putStrLn $ n ++ " \"" ++ input ++ "\" == " ++ show (f input)
-
-math x = mathl x 0
-
-mathl [] x = x
-mathl [rex|^  \s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s y
-mathl [rex|^\+\s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s $ x + y
-mathl [rex|^ -\s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s $ x - y
-mathl [rex|^\*\s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s $ x * y
-mathl [rex|^ /\s*(?{ read -> y }\d+)\s*(?{ s }.*)$|] x = mathl s $ x / y
-mathl str x = error str
-
-peano :: String -> Maybe Int
-peano = [rex|^(?{ length . filter (=='S') } \s* (?:S\s+)*Z)\s*$|]
-
-parsePair :: String -> Maybe (String, String)
-parsePair = [rex|^<\s* (?{ }[^\s,>]+) \s*,\s* (?{ }[^\s,>]+) \s*>$|]
-
--- From http://www.regular-expressions.info/dates.html
-parseDate :: String -> Maybe (Int, Int, Int)
-parseDate [rex|^(?{ read -> y }(?:19|20)\d\d)[- /.]
-                (?{ read -> m }0[1-9]|1[012])[- /.]
-                (?{ read -> d }0[1-9]|[12][0-9]|3[01])$|]
-  |  (d > 30 && (m `elem` [4, 6, 9, 11]))
-  || (m == 2 &&
-       (d ==29 && not (mod y 4 == 0 && (mod y 100 /= 0 || mod y 400 == 0)))
-    || (d > 29)) = Nothing
-  | otherwise = Just (y, m, d)
-parseDate _ = Nothing
-
-onNull a f [] = a
-onNull _ f xs = f xs
-
-nonNull = onNull Nothing
-
-disjunct [rex| ^(?:(?{nonNull $ Just . head -> a} .)
-             | (?{nonNull $ Just . head -> b} ..)
-             | (?{nonNull $ Just . last -> c} ...))$|] =
-  head $ catMaybes [a, b, c]
-
-btest = [brex|(?{}hello)|] (B.pack "hello") == Just (B.pack "hello")
diff --git a/Text/Regex/PCRE/Precompile.hs b/Text/Regex/PCRE/Precompile.hs
--- a/Text/Regex/PCRE/Precompile.hs
+++ b/Text/Regex/PCRE/Precompile.hs
@@ -1,5 +1,4 @@
-{-# LANGUAGE TupleSections #-}
-
+{-# LANGUAGE MagicHash, BangPatterns #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Text.Regex.PCRE.Rex
@@ -18,44 +17,41 @@
 
 module Text.Regex.PCRE.Precompile where
 
-import Control.Monad (liftM)
-
-import qualified Data.ByteString.Char8 as B
-import Data.ByteString.Unsafe (unsafePackCStringLen, unsafeUseAsCString)
-
-import Foreign.ForeignPtr (withForeignPtr, newForeignPtr_)
-import Foreign.Ptr (nullPtr, castPtr)
-import Foreign.Marshal (alloca)
-import Foreign.Storable (peek)
-import Foreign.C.Types (CInt)
-
+import Control.Monad            (liftM)
+import Data.ByteString.Char8    (ByteString, packCStringLen)
+import Data.ByteString.Internal (toForeignPtr)
+import Foreign.C.Types          (CSize)
+import Foreign.ForeignPtr       (withForeignPtr)
+import Foreign.Ptr              (nullPtr, castPtr)
+import Foreign.Marshal          (alloca)
+import Foreign.Storable         (peek)
+import GHC.Exts                 (Int(..), plusAddr#)
+import GHC.ForeignPtr           (ForeignPtr(..))
 import Text.Regex.PCRE.Light
 import Text.Regex.PCRE.Light.Base
 
-import Debug.Trace
-
--- | A type synonym indicating which ByteStrings represent PCRE-format compiled
--- data.
-type CompiledBytes = B.ByteString
+-- | A synonym indicating which ByteStrings represent PCRE-format compiled data.
+type CompiledBytes = ByteString
 
--- | Compiles the given regular expression, and assuming nothing bad
--- happens, yields the bytestring filled with PCRE's compiled
--- representation.
-precompile :: B.ByteString -> [PCREOption] -> IO (Maybe CompiledBytes)
+-- | Compiles the given regular expression, and assuming nothing bad happens,
+-- yields the bytestring filled with PCRE's compiled representation.
+precompile :: ByteString -> [PCREOption] -> IO (Maybe CompiledBytes)
 precompile pat opts = regexToTable $ compile pat opts
 
--- | Takes a compiled regular expression, and yields .
+-- | Takes a compiled regular expression, and if successful, yields the
+-- compiled representation.
 regexToTable :: Regex -> IO (Maybe CompiledBytes)
 regexToTable (Regex p _) =
   withForeignPtr p $ \pcre -> alloca $ \res -> do
     success <- c_pcre_fullinfo pcre nullPtr info_size res
-    len <- return . fromIntegral =<< (peek res :: IO CInt)
+    len <- return . fromIntegral =<< (peek res :: IO CSize)
     if success >= 0 
-      then withForeignPtr p (liftM Just . unsafePackCStringLen . (, len) . castPtr)
+      then liftM Just $ packCStringLen (castPtr pcre, len)
       else return Nothing
 
 -- | Creates a regular expression from the compiled representation.
 regexFromTable :: CompiledBytes  -> IO Regex
-regexFromTable bytes = unsafeUseAsCString bytes $ \cstr -> do
-   ptr <- newForeignPtr_ (castPtr cstr)
-   return $ Regex ptr bytes
+regexFromTable bytes =
+  return $ Regex (ForeignPtr (plusAddr# addr offset) content) bytes
+ where
+  !(ForeignPtr addr content, I# offset, _) = toForeignPtr bytes
diff --git a/Text/Regex/PCRE/Rex.hs b/Text/Regex/PCRE/Rex.hs
--- a/Text/Regex/PCRE/Rex.hs
+++ b/Text/Regex/PCRE/Rex.hs
@@ -20,13 +20,13 @@
 -- 3) Allows for the inline interpolation of mapping functions :: String -> a.
 --
 -- 4) Precompiles the regular expression at compile time, by calling into the
--- PCRE library and storing a 'B.ByteString' literal representation of its state.
+-- PCRE library and storing a 'ByteString' literal representation of its state.
 --
 -- NOTE: for some unknown reason this feature is currently broken, and so off by
 -- default.
 --
 -- 5) Compile-time configurable to use different PCRE options, turn off
--- precompilation, use 'B.ByteString's, or set a default mapping expression.
+-- precompilation, use 'ByteString's, or set a default mapping expression.
 --
 -- Since this is a quasiquoter library that generates code using view patterns,
 -- the following extensions are required:
@@ -102,12 +102,6 @@
 -- a single variable / pattern, preferring the first non-empty option.  The
 -- general logic for this is a bit complicated, and postponed for a later
 -- release.
--- 
--- 3) The following error currently sometimes happens when using precompiled
---    regular expressions.  This 'feature' is now off by default until this is
---    fixed.
--- 
--- >  <interactive>: out of memory (requested 17584491593728 bytes)
 --
 -- Since pcre-light is a wrapper over a C API, the most efficient interface is
 -- ByteStrings, as it does not natively speak Haskell lists.  The [rex| ... ]
@@ -116,10 +110,13 @@
 -- 'QuasiQuoter' is provided for this purpose.  You can also define your own
 -- 'QuasiQuoter' - the definitions of the default configurations are as follows:
 --
--- > rex  = rexConf False True "id" rexPCREOptions []
--- > brex = rexConf True  True "id" rexPCREOptions []
+-- > rex  = rexWithConf $ defaultRexConf
+-- > brex = rexWithConf $ defaultRexConf { rexByteString = True } 
+-- >
+-- > defaultRexConf = RexConf False True "id" [PCRE.extended] []
 --
--- As mentioned, the other Bool determines whether precompilation is used.  The
+-- The first @False@ specifies to use @String@ rather than 'ByteString'.  The
+-- @True@ argument specifies to use precompilation.  --  The
 -- string following is the default mapping expression, used when omitted.
 -- Due to GHC staging restrictions, your configuration will need to be in a
 -- different module than its usage.
@@ -132,49 +129,55 @@
 --
 -----------------------------------------------------------------------------
 
-module Text.Regex.PCRE.Rex (
-  rex, brex, rexConf, rexPCREOptions,
-  maybeRead, padRight, makeQuasiMultiline) where
+module Text.Regex.PCRE.Rex
+  (
+  -- * Quasiquoters
+    rex, brex
+  -- * Configurable QuasiQuoter
+  , rexWithConf, RexConf(..), defaultRexConf
+  -- * Utility
+  , makeQuasiMultiline
+  -- * Used by Generated Code
+  , maybeRead, padRight
+  ) where
 
-import qualified Text.Regex.PCRE.Light as PCRE
-import qualified Text.Regex.PCRE.Light.Base as PCRE
 import Text.Regex.PCRE.Precompile
 
-import Control.Arrow (first)
-import Control.Monad (liftM)
+import qualified Text.Regex.PCRE.Light as PCRE
 
-import qualified Data.ByteString.Char8 as B
-import Data.Either.Utils (forceEitherMsg)
-import Data.List (find)
-import Data.List.Split (split, onSublist)
-import Data.Maybe (catMaybes, listToMaybe, fromJust, isJust)
-import Data.Maybe.Utils (forceMaybeMsg)
-import Data.Char (isSpace)
+import Control.Applicative   ( (<$>) )
+import Control.Arrow         ( first )
+import Control.Monad         ( liftM )
+import Data.ByteString.Char8 ( pack, unpack, empty )
+import Data.List             ( find )
+import Data.List.Split       ( split, onSublist )
+import Data.Maybe            ( catMaybes, listToMaybe, fromJust, isJust )
+import Data.Char             ( isSpace )
+import System.IO.Unsafe      ( unsafePerformIO )
 
 import Language.Haskell.TH
 import Language.Haskell.TH.Quote
 import Language.Haskell.Meta.Parse
 
-import System.IO.Unsafe (unsafePerformIO)
-
 {- TODO:
-  * Fix mentioned caveats
+  * Benchmark
   * Target Text.Regex.Base ? 
-  * Provide a variant which allows splicing in an expression that evaluates to
-    regex string.
   * Add unit tests
-  * Consider allowing passing arity lists in to configuration
 -}
 
-type ParseChunk = Either String (Int, String)
-type ParseChunks = (Int, String, [(Int, String)])
-type Config = (Bool, Bool, String, [PCRE.PCREOption], [PCRE.PCREExecOption])
+data RexConf = RexConf
+  { rexByteString :: Bool
+  , rexCompiled :: Bool
+  , rexView :: String 
+  , rexPCREOpts :: [PCRE.PCREOption]
+  , rexPCREExecOpts :: [PCRE.PCREExecOption]
+  }
 
--- | Default regular expression quasiquoter for 'String's and 'B.ByteString's,
+-- | Default regular expression quasiquoter for 'String's and 'ByteString's,
 -- respectively.
 rex, brex :: QuasiQuoter
-rex  = rexConf False False "id" rexPCREOptions []
-brex = rexConf True  False "id" rexPCREOptions []
+rex  = rexWithConf $ defaultRexConf
+brex = rexWithConf $ defaultRexConf { rexByteString = True }
 
 -- | This is a 'QuasiQuoter' transformer, which allows for a whitespace-sensitive
 -- quasi-quoter to be broken over multiple lines.  The default 'rex' and
@@ -183,30 +186,28 @@
 -- parameter, then this could be useful. The leading space of each line is
 -- ignored, and all newlines removed.
 makeQuasiMultiline :: QuasiQuoter -> QuasiQuoter
-makeQuasiMultiline (QuasiQuoter a b c d) =
-  QuasiQuoter (a . pre) (b . pre) (c . pre) (d . pre)
+makeQuasiMultiline (QuasiQuoter a b c d)
+  = QuasiQuoter (a . pre) (b . pre) (c . pre) (d . pre)
  where
   pre = concat . (\(x:xs) -> x : map (dropWhile isSpace) xs) . lines
 
--- | Default compilation time PCRE options.  The default is 'PCRE.extended',
--- which causes whitespace to be nonsemantic, and ignores # comments.
-rexPCREOptions :: [PCRE.PCREOption]
-rexPCREOptions = [ PCRE.extended ]
-  -- , dotall, caseless, utf8
-  -- , newline_any, PCRE.newline_crlf ]
+-- | Default rex configuration, which specifies that the regexes operate on
+-- strings, don't postprocess the matched patterns, and use 'PCRE.extended'.
+-- This setting causes whitespace to be nonsemantic, and ignores # comments.
+defaultRexConf :: RexConf
+defaultRexConf = RexConf False False "id" [PCRE.extended] []
 
 -- | A configureable regular-expression QuasiQuoter.  Takes the options to pass
--- to the PCRE engine, along with 'Bool's to flag 'B.ByteString' usage and
+-- to the PCRE engine, along with 'Bool's to flag 'ByteString' usage and
 -- non-compilation respecively.  The provided 'String' indicates which mapping
 -- function to use, when one is omitted - \"(?{} ...)\".
-rexConf :: Bool -> Bool -> String -> [PCRE.PCREOption] -> [PCRE.PCREExecOption]
-        -> QuasiQuoter
-rexConf bs pc d os eos = QuasiQuoter
-        (makeExp conf . parseIt)
-        (makePat conf . parseIt)
-        undefined undefined
- where
-  conf = (bs, pc, d, [PCRE.combineOptions os], [PCRE.combineExecOptions eos])
+rexWithConf :: RexConf -> QuasiQuoter
+rexWithConf conf
+  = QuasiQuoter
+      (makeExp conf . parseIt)
+      (makePat conf . parseIt)
+      undefined
+      undefined
 
 -- Template Haskell Code Generation
 -------------------------------------------------------------------------------
@@ -215,10 +216,10 @@
 -- regex.  This particular code mainly just handles making "read" the
 -- default for captures which lack a parser definition, and defaulting to making
 -- the parser that doesn't exist
-makeExp :: Config -> ParseChunks -> ExpQ
+makeExp :: RexConf -> ParseChunks -> ExpQ
 makeExp conf (cnt, pat, exs) = buildExp conf cnt pat exs'
  where
-  exs' = map (\ix -> liftM (processExp conf . snd) $ find ((==ix).fst) exs) [0..cnt]
+  exs' = map (\ix -> liftM (processExp conf . snd) $ find ((==ix) . fst) exs) [0..cnt]
   
 -- Creates the template haskell Pat which corresponds to the parsed interpolated
 -- regex. As well as handling the aforementioned defaulting considerations, this
@@ -226,7 +227,7 @@
 -- 
 -- E.g. [reg| ... (?{e1 -> v1} ...) ... (?{e2 -> v2} ...) ... |] becomes
 --      [reg| ... (?{e1} ...) ... (?{e2} ...) ... |] -> (v1, v2)
-makePat :: Config -> ParseChunks -> PatQ
+makePat :: RexConf -> ParseChunks -> PatQ
 makePat conf (cnt, pat, exs) = do
   viewExp <- buildExp conf cnt pat $ map (liftM fst) views
   return . ViewP viewExp
@@ -249,29 +250,29 @@
 -- Here's where the main meat of the template haskell is generated.  Given the
 -- number of captures, the pattern string, and a list of capture expressions,
 -- yields the template Haskell Exp which parses a string into a tuple.
-buildExp :: Config -> Int -> String -> [Maybe Exp] -> ExpQ
-buildExp (bs, nc, _, pcreOpts, pcreExecOpts) cnt pat xs =
+buildExp :: RexConf -> Int -> String -> [Maybe Exp] -> ExpQ
+buildExp conf cnt pat xs =
   [| let r = $(get_regex) in
-     $(process) . (flip $ PCRE.match r) $(liftRS pcreExecOpts)
-   . $(if bs then [| id |] else [| B.pack |]) |]
+     $(process) . (flip $ PCRE.match r) $(liftRS $ rexPCREExecOpts conf)
+   . $(if rexByteString conf then [| id |] else [| pack |]) |]
  where
-  liftRS x = [| read shown |]
-   where shown = show x
+  liftRS x = [| read shown |] where shown = show x
 
   --TODO: make sure this takes advantage of bytestring fusion stuff - is
   -- the right pack / unpack. Or use XOverloadedStrings
-  get_regex = if nc
-    then [| unsafePerformIO (regexFromTable $! $(table_bytes)) |]
-    else [| PCRE.compile (B.pack pat) $(liftRS pcreOpts)|]
-  table_bytes = [| B.pack $(runIO table_string) |]
-  table_string = precompile (B.pack pat) pcreOpts >>= 
-    return . LitE . StringL . B.unpack . 
-    forceMaybeMsg "Error while getting PCRE compiled representation\n"
+  get_regex 
+    | rexCompiled conf = [| unsafePerformIO (regexFromTable $! $(table_bytes)) |]
+    | otherwise = [| PCRE.compile (pack pat) $(liftRS pcreOpts) |]
+  table_bytes = [| pack $(LitE . StringL . unpack <$> runIO table_string) |]
+  table_string
+     = forceMaybeMsg "Error while getting PCRE compiled representation\n"
+   <$> precompile (pack pat) pcreOpts
+  pcreOpts = rexPCREOpts conf
 
-  process = case (null vs, bs) of
+  process = case (null vs, rexByteString conf) of
     (True, _)  -> [| liftM ( const () ) |]
-    (_, False) -> [| liftM (($(return maps)) . padRight "" pad . map B.unpack) |]
-    (_, True)  -> [| liftM (($(return maps)) . padRight B.empty pad) |]
+    (_, False) -> [| liftM ($(return maps) . padRight "" pad . map unpack) |]
+    (_, True)  -> [| liftM ($(return maps) . padRight empty pad) |]
   pad = cnt + 2
   maps = LamE [ListP . (WildP:) $ map VarP vs]
        . TupE . map (uncurry AppE)
@@ -282,10 +283,10 @@
   vs = [mkName $ "v" ++ show i | i <- [0..cnt]]
 
 -- Parse a Haskell expression into a template Haskell Exp
-processExp :: Config -> String -> Exp
-processExp (_, _, d, _, _) xs
+processExp :: RexConf -> String -> Exp
+processExp conf xs
   = forceEitherMsg ("Error while parsing capture mapper `" ++ xs ++ "'")
-  . parseExp $ onSpace xs d id
+  . parseExp $ onSpace xs (rexView conf) id
 
 -- Parse a Haskell pattern match into a template Haskell Pat, yielding Nothing
 -- for patterns which consist of just whitespace.
@@ -297,6 +298,9 @@
 -- Parsing
 -------------------------------------------------------------------------------
 
+type ParseChunk = Either String (Int, String)
+type ParseChunks = (Int, String, [(Int, String)])
+
 -- Postprocesses the results of the chunk-wise parse output, into the pattern to
 -- be pased to the regex engine, and the interpolated 
 parseIt :: String -> ParseChunks
@@ -371,3 +375,16 @@
 
 mapSnd :: (t -> t2) -> (t1, t) -> (t1, t2)
 mapSnd f (x, y) = (x, f y)
+
+-- From MissingH
+
+{- | Like 'forceMaybe', but lets you customize the error message raised if
+Nothing is supplied. -}
+forceMaybeMsg :: String -> Maybe a -> a
+forceMaybeMsg msg Nothing = error msg
+forceMaybeMsg _ (Just x) = x
+
+{- | Like 'forceEither', but can raise a specific message with the error. -}
+forceEitherMsg :: Show e => String -> Either e a -> a
+forceEitherMsg msg (Left x) = error $ msg ++ ": " ++ show x
+forceEitherMsg _ (Right x) = x
diff --git a/rex.cabal b/rex.cabal
--- a/rex.cabal
+++ b/rex.cabal
@@ -1,5 +1,5 @@
 Name:                rex
-Version:             0.3.1
+Version:             0.4.1
 Synopsis:            A quasi-quoter for typeful results of regex captures.
 Description:         Provides a quasi-quoter for regular expressions which
                      yields a tuple, of appropriate arity and types,
@@ -18,8 +18,9 @@
 Category:            Control
 Build-type:          Simple
 Stability:           experimental
-Extra-source-files:  Test.hs, Bench.hs
-Data-files:          README
+Extra-source-files:  Demo.hs, Bench.hs
+Data-files:          README.md
+                     CHANGES.md
 Cabal-version:       >=1.6
 Bug-Reports:         http://github.com/mgsloan/rex/issues
 Source-Repository head
@@ -30,6 +31,6 @@
   Extensions:        TemplateHaskell, QuasiQuotes, TupleSections, ViewPatterns
   Exposed-modules:   Text.Regex.PCRE.Rex, Text.Regex.PCRE.Precompile
   Build-depends:     base >= 3.0 && < 6, bytestring, containers, ghc >= 7.0,
-                     haskell-src-meta, MissingH, pcre-light, split,
+                     haskell-src-meta >= 0.5, pcre-light, split,
                      template-haskell >= 2.5.0.0
   Ghc-options:       -Wall
