diff --git a/README.markdown b/README.markdown
new file mode 100644
--- /dev/null
+++ b/README.markdown
@@ -0,0 +1,97 @@
+# regex
+
+Regex is a regular expression toolkit for regex-base with:
+
+  * text-replacement operations with named captures;
+  * special datatypes for matches and captures;
+  * compile-time checking of RE syntax;
+  * a unified means of controlling case-sensitivity and multi-line options;
+  * high-level AWK-like tools for building text processing apps;
+  * the option of using match operators with reduced polymorphism on the
+    text and/or result types;
+  * regular expression macros including:
+      + a number of useful RE macros;
+      + a test bench for testing and documenting new macro environments;
+  * built-in support for the TDFA and PCRE backends;
+  * comprehensive documentation and copious examples.
+
+
+See the [About page](http://about.regex.uk) for details.
+
+
+## Road Map
+
+&nbsp;&nbsp;&nbsp;&nbsp;&#x2612;&nbsp;&nbsp;2017-01-26  v0.0.0.1  Pre-release (I)
+
+&nbsp;&nbsp;&nbsp;&nbsp;&#x2612;&nbsp;&nbsp;2017-01-30  v0.0.0.2  Pre-release (II)
+
+&nbsp;&nbsp;&nbsp;&nbsp;&#x2612;&nbsp;&nbsp;2017-02-19  v0.1.0.0  [Proposed core API with presentable Haddocks](https://github.com/iconnect/regex/milestone/1)
+
+&nbsp;&nbsp;&nbsp;&nbsp;&#x2610;&nbsp;&nbsp;2017-02-26  v0.1.1.0  [Tutorials and examples finalized](https://github.com/iconnect/regex/milestone/2)
+
+&nbsp;&nbsp;&nbsp;&nbsp;&#x2610;&nbsp;&nbsp;2017-03-20  v1.0.0.0  [First stable release](https://github.com/iconnect/regex/milestone/3)
+
+&nbsp;&nbsp;&nbsp;&nbsp;&#x2610;&nbsp;&nbsp;2017-08-31  v2.0.0.0  [Fast text replacement with benchmarks](https://github.com/iconnect/regex/milestone/4)
+
+
+
+See the [Roadmap page](http://roadmap.regex.uk) for details.
+
+
+## Build Status
+
+[![Hackage](http://regex.uk/badges/hackage.svg)](https://hackage.haskell.org/package/regex) [![BSD3 License](http://regex.uk/badges/license.svg)](https://tldrlegal.com/license/bsd-3-clause-license-%28revised%29) [![Un*x build](http://regex.uk/badges/unix-build.svg)](https://travis-ci.org/iconnect/regex) [![Windows build](http://regex.uk/badges/windows-build.svg)](https://ci.appveyor.com/project/engineerirngirisconnectcouk/regex/branch/master) [![Coverage](http://regex.uk/badges/coverage.svg)](https://coveralls.io/github/iconnect/regex?branch=master)<br/>
+See [build status page](http://regex.uk/build-status) for details.
+
+
+## Installing the Package
+
+The package can be easily installed with cabal or stack on GHC-8.0,
+ 7.10 or 7.8 for the above platforms. See the
+[Installation page](http://installation.regex.uk) for details.
+
+
+## The Tutorial Tests and Examples
+
+See the [Tutorial page](http://tutorial.regex.uk) and
+[Examples page](http://examples.regex.uk) for details.
+
+
+## Helping Out
+
+If you have any feedback or suggestion then please drop us a line.
+
+&nbsp;&nbsp;&nbsp;&nbsp;`t` [&#64;hregex](https://twitter.com/hregex)<br/>
+&nbsp;&nbsp;&nbsp;&nbsp;`e` maintainers@regex.uk<br/>
+&nbsp;&nbsp;&nbsp;&nbsp;`w` http://issues.regex.uk
+
+The [Contact page](http://contact.regex.uk) has more details.
+
+
+## The API
+
+The Haddocks can be found at http://hs.regex.uk.
+
+
+## The Macro Tables
+
+The macro environments are an important part of the package and
+are documented [here](http://macros.regex.uk).
+
+
+## The regex.uk Directory
+
+A handy overview of the regex.uk domain can be found
+[here](http://directory.regex.uk).
+
+
+## The Changelog
+
+The `changelog` is posted [here](http://changelog.regex.uk).
+
+
+## The Authors
+
+This library was written and is currently maintained by
+[Chris Dornan](mailto:chris.dornan@irisconnect.com) aka
+[&#64;cdornan](https://twitter.com/cdornan)
diff --git a/README.md b/README.md
deleted file mode 100644
--- a/README.md
+++ /dev/null
@@ -1,47 +0,0 @@
-[![Hackage](https://img.shields.io/hackage/v/regex.svg)](https://hackage.haskell.org/package/regex)
-[![BSD3 License](http://img.shields.io/badge/license-BSD3-brightgreen.svg)](https://tldrlegal.com/license/bsd-3-clause-license-%28revised%29)
-[![Un*x build](https://img.shields.io/travis/iconnect/regex.svg?label=Linux%2BmacOS)](https://travis-ci.org/iconnect/regex)
-[![Windows build](https://img.shields.io/appveyor/ci/engineerirngirisconnectcouk/regex.svg?label=Windows)](https://ci.appveyor.com/project/engineerirngirisconnectcouk/regex/branch/master)
-[![Coverage](https://img.shields.io/coveralls/iconnect/regex.svg)](https://coveralls.io/github/iconnect/regex?branch=master)
-
-# regex: A Regular Expression Toolkit for regex-base
-
-regex extends regex-base with:
-
-  * a text-replacement toolkit
-  * special datatypes for many matches, first match and individual captures
-  * compile-time checking of RE syntax
-  * a unified means of controlling case-sensitivity and multi-line options
-  * high-level AWK-like tools for building text processing apps
-  * the option of using match operators with reduced polymorphism on the
-    text and/or result types
-  * regular expression macros including
-      + a number of useful RE macros
-      + a test bench for testing and documenting new macro environments
-  * built-in support for the TDFA and PCRE backends
-  * comprehensive documentation and copious examples
-
-
-Schedule
---------
-
-- [X] **2017-01-26**&nbsp;&nbsp;0.0.0.1&nbsp;&nbsp;Pre-release (I)
-- [X] **2017-01-30**&nbsp;&nbsp;0.0.0.2&nbsp;&nbsp;Pre-release (II)
-- [ ] **2017-02-06**&nbsp;&nbsp;0.0.1.0&nbsp;&nbsp;RFC
-- [ ] **2017-02-20**&nbsp;&nbsp;0.1.0.0&nbsp;&nbsp;a candidate stable release
-- [ ] **2017-03-20**&nbsp;&nbsp;1.0.0.0&nbsp;&nbsp;first stable release
-
-
-The Web Page
-------------
-
-We have a [web page](https://iconnect.github.io/regex/) with a tutorial,
-a major example and and more examples than you can shake a stick at (most
-of them used in the package itself).
-
-
-The Macro Tables
-----------------
-
-The macro environments are an important part of the package and they
-are documented [in these tables](tables).
diff --git a/Text/RE.hs b/Text/RE.hs
--- a/Text/RE.hs
+++ b/Text/RE.hs
@@ -1,14 +1,133 @@
 {-# OPTIONS_GHC -fno-warn-dodgy-exports #-}
+-- |
+-- Module      :  Text.RE
+-- Copyright   :  (C) 2016-17 Chris Dornan
+-- License     :  BSD3 (see the LICENSE file)
+-- Maintainer  :  Chris Dornan <chris.dornan@irisconnect.com>
+-- Stability   :  RFC
+-- Portability :  portable
 
 module Text.RE
-  ( module Text.RE.Capture
-  , module Text.RE.CaptureID
-  , module Text.RE.Edit
-  , module Text.RE.IsRegex
-  , module Text.RE.LineNo
-  , module Text.RE.Options
-  , module Text.RE.Parsers
-  , module Text.RE.Replace
+  (
+  -- * Tutorial
+  -- $tutorial
+
+  -- * How to use this library
+  -- $use
+
+  -- ** The Match Operators
+  -- $operators
+
+  -- * Matches, Match, Capture Types and Functions
+    Matches(..)
+  , Match(..)
+  , Capture(..)
+  , noMatch
+  -- ** Matches functions
+  , anyMatches
+  , countMatches
+  , matches
+  , mainCaptures
+  -- ** Match functions
+  , matched
+  , matchedText
+  , matchCapture
+  , matchCaptures
+  , (!$$)
+  , captureText
+  , (!$$?)
+  , captureTextMaybe
+  , (!$)
+  , capture
+  , (!$?)
+  , captureMaybe
+  -- ** Capture functions
+  , hasCaptured
+  , capturePrefix
+  , captureSuffix
+  -- * IsRegex
+  , IsRegex(..)
+  -- * Options
+  , Options_(..)
+  , IsOption(..)
+  , Mode(..)
+  , MacroID(..)
+  , Macros
+  , emptyMacros
+  , SimpleRegexOptions(..)
+  -- * CaptureID
+  , CaptureID(..)
+  , CaptureNames
+  , noCaptureNames
+  , CaptureName(..)
+  , CaptureOrdinal(..)
+  , findCaptureID
+  -- * Edit
+  , Edits(..)
+  , Edit(..)
+  , LineEdit(..)
+  , applyEdits
+  , applyEdit
+  , applyLineEdit
+  -- * LineNo
+  , LineNo(..)
+  , firstLine
+  , getLineNo
+  , lineNo
+  -- * Parsers
+  , parseInteger
+  , parseHex
+  , parseDouble
+  , parseString
+  , parseSimpleString
+  , parseDate
+  , parseSlashesDate
+  , parseTimeOfDay
+  , parseTimeZone
+  , parseDateTime
+  , parseDateTime8601
+  , parseDateTimeCLF
+  , parseShortMonth
+  , shortMonthArray
+  , IPV4Address
+  , parseIPv4Address
+  , Severity(..)
+  , parseSeverity
+  , severityKeywords
+  -- * Replace
+  , Replace(..)
+  , Replace_(..)
+  , replace_
+  , Phi(..)
+  , Context(..)
+  , Location(..)
+  , isTopLocation
+  , replace
+  , replaceAll
+  , replaceAllCaptures
+  , replaceAllCaptures'
+  , replaceAllCaptures_
+  , replaceAllCapturesM
+  , replaceCaptures
+  , replaceCaptures'
+  , replaceCaptures_
+  , replaceCapturesM
+  , expandMacros
+  , expandMacros'
+  -- * Tools
+  -- ** Grep
+  , grep
+  , grepLines
+  , GrepScript
+  , grepScript
+  , linesMatched
+  -- ** Lex
+  , alex
+  , alex'
+  -- ** Sed
+  , SedScript
+  , sed
+  , sed'
   ) where
 
 import           Text.RE.Capture
@@ -19,3 +138,61 @@
 import           Text.RE.Options
 import           Text.RE.Parsers
 import           Text.RE.Replace
+import           Text.RE.Tools.Grep
+import           Text.RE.Tools.Lex
+import           Text.RE.Tools.Sed
+
+-- $tutorial
+-- We have a regex tutorial at <http://tutorial.regex.uk>. These API
+-- docs are mainly for reference.
+
+-- $use
+--
+-- This module won't provide any operators to match a regular expression
+-- against text as it merely provides the toolkit for working with the
+-- output of the match operators.  You probably won't import it directly
+-- but import one of the modules that provides the match operators,
+-- which will in tuen re-export this module.
+--
+-- The module that you choose to import will depend upon two factors:
+--
+-- * Which flavour of regular expression do you want to use? If you want
+--   Posix flavour REs then you want the TDFA modules, otherwise its
+--   PCRE for Perl-style REs.
+--
+-- * What type of text do you want to match: (slow) @String@s, @ByteString@,
+--   @ByteString.Lazy@, @Text@, @Text.Lazy@ or the anachronistic @Seq Char@
+--   or indeed a good old-fashioned polymorphic operators?
+--
+-- While we aim to provide all combinations of these choices, some of them
+-- are currently not available.  We have:
+--
+-- * "Text.RE.PCRE"
+-- * "Text.RE.PCRE.ByteString"
+-- * "Text.RE.PCRE.ByteString.Lazy"
+-- * "Text.RE.PCRE.RE"
+-- * "Text.RE.PCRE.Sequence"
+-- * "Text.RE.PCRE.String"
+-- * "Text.RE.TDFA"
+-- * "Text.RE.TDFA.ByteString"
+-- * "Text.RE.TDFA.ByteString.Lazy"
+-- * "Text.RE.TDFA.RE"
+-- * "Text.RE.TDFA.Sequence"
+-- * "Text.RE.TDFA.String"
+-- * "Text.RE.TDFA.Text"
+-- * "Text.RE.TDFA.Text.Lazy"
+
+-- $operators
+--
+-- The traditional @=~@ and @=~~@ operators are exported by the @regex@,
+-- but we recommend that you use the two new operators, especially if
+-- you are not familiar with the old operators.  We have:
+--
+-- * @txt ?=~ re@ searches for a single match yielding a value of type
+--   'Match' @a@ where @a@ is the type of the text you are searching.
+--
+-- * @txt *=~ re@ searches for all non-overlapping matches in @txt@,
+--   returning a value of type 'Matches' @a@.
+--
+-- See the sections below for more information on these @Matches@ and
+-- @Match@ result types.
diff --git a/Text/RE/Capture.lhs b/Text/RE/Capture.lhs
--- a/Text/RE/Capture.lhs
+++ b/Text/RE/Capture.lhs
@@ -10,6 +10,8 @@
   ( Matches(..)
   , Match(..)
   , Capture(..)
+  , noMatch
+  , emptyMatchArray
   -- Matches functions
   , anyMatches
   , countMatches
@@ -20,9 +22,13 @@
   , matchedText
   , matchCapture
   , matchCaptures
+  , (!$$)
   , captureText
+  , (!$$?)
   , captureTextMaybe
+  , (!$)
   , capture
+  , (!$?)
   , captureMaybe
   -- Capture functions
   , hasCaptured
@@ -36,6 +42,8 @@
 import           Data.Maybe
 import           Text.Regex.Base
 import           Text.RE.CaptureID
+
+infixl 9 !$, !$$
 \end{code}
 
 
@@ -46,7 +54,7 @@
 data Matches a =
   Matches
     { matchesSource :: !a          -- ^ the source text being matched
-    , allMatches    :: [Match a]   -- ^ all captures found, left to right
+    , allMatches    :: ![Match a]  -- ^ all captures found, left to right
     }
   deriving (Show,Eq)
 \end{code}
@@ -59,7 +67,7 @@
 data Match a =
   Match
     { matchSource  :: !a                -- ^ the whole source text
-    , captureNames :: CaptureNames      -- ^ the RE's capture names
+    , captureNames :: !CaptureNames     -- ^ the RE's capture names
     , matchArray   :: !(Array CaptureOrdinal (Capture a))
                                         -- ^ 0..n-1 captures,
                                         -- starting with the
@@ -86,11 +94,21 @@
 \end{code}
 
 \begin{code}
+-- | Construct a Match that does not match anything.
+noMatch :: a -> Match a
+noMatch t = Match t noCaptureNames emptyMatchArray
+
+-- | an empty array of Capture
+emptyMatchArray :: Array CaptureOrdinal (Capture a)
+emptyMatchArray = listArray (CaptureOrdinal 0,CaptureOrdinal $ -1) []
+\end{code}
+
+\begin{code}
 instance Functor Matches where
   fmap f Matches{..} =
     Matches
       { matchesSource = f matchesSource
-      , allMatches   = map (fmap f) allMatches
+      , allMatches    = map (fmap f) allMatches
       }
 
 instance Functor Match where
@@ -151,29 +169,45 @@
   True  -> Nothing
   False -> Just (matchArray!0,drop 1 $ elems matchArray)
 
+-- | an alternative for captureText
+(!$$) :: Match a -> CaptureID -> a
+(!$$) = flip captureText
+
 -- | look up the text of the nth capture, 0 being the match of the whole
 -- RE against the source text, 1, the first bracketed sub-expression to
 -- be matched and so on
 captureText :: CaptureID -> Match a -> a
 captureText cid mtch = capturedText $ capture cid mtch
 
+-- | an alternative for captureTextMaybe
+(!$$?) :: Match a -> CaptureID -> Maybe a
+(!$$?) = flip captureTextMaybe
+
 -- | look up the text of the nth capture (0 being the match of the
 -- whole), returning Nothing if the Match doesn't contain the capture
 captureTextMaybe :: CaptureID -> Match a -> Maybe a
 captureTextMaybe cid mtch = do
-    cap <- captureMaybe cid mtch
+    cap <- mtch !$? cid
     case hasCaptured cap of
       True  -> Just $ capturedText cap
       False -> Nothing
 
+-- | an alternative for capture
+(!$) :: Match a -> CaptureID -> Capture a
+(!$) = flip capture
+
 -- | look up the nth capture, 0 being the match of the whole RE against
 -- the source text, 1, the first bracketed sub-expression to be matched
 -- and so on
 capture :: CaptureID -> Match a -> Capture a
-capture cid mtch = fromMaybe oops $ captureMaybe cid mtch
+capture cid mtch = fromMaybe oops $ mtch !$? cid
   where
     oops = error $ "capture: out of bounds (" ++ show cid ++ ")"
 
+-- | an alternative for capture captureMaybe
+(!$?) :: Match a -> CaptureID -> Maybe (Capture a)
+(!$?) = flip captureMaybe
+
 -- | look up the nth capture, 0 being the match of the whole RE against
 -- the source text, 1, the first bracketed sub-expression to be matched
 -- and so on, returning Nothing if there is no such capture, or if the
@@ -207,8 +241,6 @@
 captureSuffix :: Extract a => Capture a -> a
 captureSuffix Capture{..} = after (captureOffset+captureLength) captureSource
 \end{code}
-
-
 
 
 \begin{code}
diff --git a/Text/RE/Edit.lhs b/Text/RE/Edit.lhs
--- a/Text/RE/Edit.lhs
+++ b/Text/RE/Edit.lhs
@@ -1,5 +1,10 @@
 \begin{code}
+{-# LANGUAGE NoImplicitPrelude          #-}
 {-# LANGUAGE RecordWildCards            #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 
 module Text.RE.Edit
   ( LineNo
@@ -11,9 +16,8 @@
   , applyLineEdit
   ) where
 
-import           Control.Applicative
 import           Data.Maybe
-import           Data.Monoid
+import           Prelude.Compat
 import           Text.RE.Capture
 import           Text.RE.IsRegex
 import           Text.RE.LineNo
diff --git a/Text/RE/Internal/NamedCaptures.lhs b/Text/RE/Internal/NamedCaptures.lhs
--- a/Text/RE/Internal/NamedCaptures.lhs
+++ b/Text/RE/Internal/NamedCaptures.lhs
@@ -1,17 +1,20 @@
 \begin{code}
 {-# LANGUAGE QuasiQuotes                #-}
 {-# LANGUAGE TemplateHaskell            #-}
-{-# LANGUAGE FlexibleInstances          #-}
-{-# LANGUAGE MultiParamTypeClasses      #-}
 {-# LANGUAGE DeriveGeneric              #-}
 {-# LANGUAGE RecordWildCards            #-}
 
 module Text.RE.Internal.NamedCaptures
   ( cp
   , extractNamedCaptures
-  , namedCapturesTestTree
-  )
-  where
+  , idFormatTokenOptions
+  , Token(..)
+  , validToken
+  , formatTokens
+  , formatTokens'
+  , formatTokens0
+  , scan
+  ) where
 
 import           Data.Char
 import qualified Data.HashMap.Strict          as HM
@@ -19,15 +22,10 @@
 import           GHC.Generics
 import qualified Language.Haskell.TH          as TH
 import           Language.Haskell.TH.Quote
-import           Test.SmallCheck.Series
-import           Test.Tasty
-import           Test.Tasty.HUnit
-import           Test.Tasty.SmallCheck        as SC
 import           Text.Heredoc
 import           Text.RE
 import           Text.RE.Internal.PreludeMacros
 import           Text.RE.Internal.QQ
-import           Text.RE.Tools.Lex
 import           Text.Regex.PCRE
 
 
@@ -41,13 +39,6 @@
 extractNamedCaptures s = Right (analyseTokens tks,formatTokens tks)
   where
     tks = scan s
-
-namedCapturesTestTree :: TestTree
-namedCapturesTestTree = localOption (SmallCheckDepth 4) $
-  testGroup "NamedCaptures"
-    [ formatScanTestTree
-    , analyseTokensTestTree
-    ]
 \end{code}
 
 
@@ -64,8 +55,6 @@
   | Other       Char
   deriving (Show,Generic,Eq)
 
-instance Monad m => Serial m Token
-
 validToken :: Token -> Bool
 validToken tkn = case tkn of
     ECap  mb -> maybe True check_ecap mb
@@ -161,9 +150,9 @@
 defFormatTokenOptions :: FormatTokenOptions
 defFormatTokenOptions =
   FormatTokenOptions
-    { _fto_regex_type     = Nothing
-    , _fto_min_caps       = False
-    , _fto_incl_caps = False
+    { _fto_regex_type = Nothing
+    , _fto_min_caps   = False
+    , _fto_incl_caps  = False
     }
 
 idFormatTokenOptions :: FormatTokenOptions
@@ -213,59 +202,4 @@
           Bra     -> "("
           BS    c -> "\\" ++ [c]
           Other c -> [c]
-\end{code}
-
-
-Testing : FormatToken/Scan Properties
--------------------------------------
-
-\begin{code}
-formatScanTestTree :: TestTree
-formatScanTestTree =
-  testGroup "FormatToken/Scan Properties"
-    [ localOption (SmallCheckDepth 4) $
-        SC.testProperty "formatTokens == formatTokens0" $
-          \tks -> formatTokens tks == formatTokens0 tks
-    , localOption (SmallCheckDepth 4) $
-        SC.testProperty "scan . formatTokens' idFormatTokenOptions == id" $
-          \tks -> all validToken tks ==>
-                    scan (formatTokens' idFormatTokenOptions tks) == tks
-    ]
-\end{code}
-
-
-Testing : Analysing [Token] Unit Tests
---------------------------------------
-
-\begin{code}
-analyseTokensTestTree :: TestTree
-analyseTokensTestTree =
-  testGroup "Analysing [Token] Unit Tests"
-    [ tc [here|foobar|]                                       []
-    , tc [here||]                                             []
-    , tc [here|$([0-9]{4})|]                                  []
-    , tc [here|${x}()|]                                       [(1,"x")]
-    , tc [here|${}()|]                                        []
-    , tc [here|${}()${foo}()|]                                [(2,"foo")]
-    , tc [here|${x}(${y()})|]                                 [(1,"x")]
-    , tc [here|${x}(${y}())|]                                 [(1,"x"),(2,"y")]
-    , tc [here|${a}(${b{}())|]                                [(1,"a")]
-    , tc [here|${y}([0-9]{4})-${m}([0-9]{2})-${d}([0-9]{2})|] [(1,"y"),(2,"m"),(3,"d")]
-    , tc [here|@$(@|\{${name}([^{}]+)\})|]                    [(2,"name")]
-    , tc [here|${y}[0-9]{4}|]                                 []
-    , tc [here|${}([0-9]{4})|]                                []
-    ]
-  where
-    tc s al =
-      testCase s $ assertEqual "CaptureNames"
-        (xnc s)
-        (HM.fromList
-          [ (CaptureName $ T.pack n,CaptureOrdinal i)
-              | (i,n)<-al
-              ]
-        )
-
-    xnc = either oops fst . extractNamedCaptures
-      where
-        oops = error "analyseTokensTestTree: unexpected parse failure"
 \end{code}
diff --git a/Text/RE/Internal/PreludeMacros.hs b/Text/RE/Internal/PreludeMacros.hs
--- a/Text/RE/Internal/PreludeMacros.hs
+++ b/Text/RE/Internal/PreludeMacros.hs
@@ -1,6 +1,11 @@
+{-# LANGUAGE NoImplicitPrelude          #-}
 {-# LANGUAGE RecordWildCards            #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE OverloadedStrings          #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 
 module Text.RE.Internal.PreludeMacros
   ( RegexType(..)
@@ -18,12 +23,13 @@
   , preludeMacroDescriptor
   ) where
 
-import           Control.Applicative
 import           Data.Array
-import qualified Data.HashMap.Lazy              as HML
+import qualified Data.HashMap.Lazy            as HML
 import           Data.List
 import           Data.Maybe
+import qualified Data.Text                    as T
 import           Data.Time
+import           Prelude.Compat
 import           Text.RE.Options
 import           Text.RE.Parsers
 import           Text.RE.TestBench
@@ -72,14 +78,15 @@
                        -> PreludeMacro
                        -> Maybe MacroDescriptor
 preludeMacroDescriptor rty env pm = case pm of
-  PM_natural          -> natural_macro          rty env pm
-  PM_natural_hex      -> natural_hex_macro      rty env pm
-  PM_integer          -> integer_macro          rty env pm
-  PM_decimal          -> decimal_macro          rty env pm
+  PM_nat              -> natural_macro          rty env pm
+  PM_hex              -> natural_hex_macro      rty env pm
+  PM_int              -> integer_macro          rty env pm
+  PM_frac             -> decimal_macro          rty env pm
   PM_string           -> string_macro           rty env pm
   PM_string_simple    -> string_simple_macro    rty env pm
   PM_id               -> id_macro               rty env pm
   PM_id'              -> id'_macro              rty env pm
+  PM_id_              -> id__macro              rty env pm
   PM_date             -> date_macro             rty env pm
   PM_date_slashes     -> date_slashes_macro     rty env pm
   PM_time             -> time_macro             rty env pm
@@ -96,16 +103,17 @@
 -- | an enumeration of all of the prelude macros
 data PreludeMacro
   -- numbers
-  = PM_natural
-  | PM_natural_hex
-  | PM_integer
-  | PM_decimal
+  = PM_nat
+  | PM_hex
+  | PM_int
+  | PM_frac
   -- strings
   | PM_string
   | PM_string_simple
   -- identifiers
   | PM_id
   | PM_id'
+  | PM_id_
   -- dates & times
   | PM_date
   | PM_date_slashes
@@ -125,8 +133,12 @@
 
 -- | naming the macros
 presentPreludeMacro :: PreludeMacro -> String
-presentPreludeMacro = (prelude_prefix++) . map tr . drop 3 . show
+presentPreludeMacro pm = case pm of
+    PM_id_  -> prelude_prefix++"id-"
+    _       -> fmt pm
   where
+    fmt = (prelude_prefix++) . map tr . drop 3 . show
+
     tr '_' = '.'
     tr c   = c
 
@@ -263,7 +275,7 @@
              -> Maybe MacroDescriptor
 string_macro     PCRE _  _   = Nothing
 string_macro rty@TDFA env pm =
-  Just $ run_tests rty parseString samples env pm
+  Just $ run_tests rty (fmap T.unpack . parseString) samples env pm
     MacroDescriptor
       { _md_source          = "\"(?:[^\"\\]+|\\\\[\\\"])*\""
       , _md_samples         = map fst samples
@@ -294,7 +306,7 @@
                     -> PreludeMacro
                     -> Maybe MacroDescriptor
 string_simple_macro rty env pm =
-  Just $ run_tests rty parseSimpleString samples env pm
+  Just $ run_tests rty (fmap T.unpack . parseSimpleString) samples env pm
     MacroDescriptor
       { _md_source          = "\"[^\"[:cntrl:]]*\""
       , _md_samples         = map fst samples
@@ -404,6 +416,53 @@
         , "_1'"
         ]
 
+id__macro :: RegexType
+          -> MacroEnv
+          -> PreludeMacro
+          -> Maybe MacroDescriptor
+id__macro rty env pm =
+  Just $ run_tests rty Just samples env pm
+    MacroDescriptor
+      { _md_source          = "_*[a-zA-Z][a-zA-Z0-9_'-]*"
+      , _md_samples         = map fst samples
+      , _md_counter_samples = counter_samples
+      , _md_test_results    = []
+      , _md_parser          = Nothing
+      , _md_description     = "an identifier with -s"
+      }
+  where
+    samples :: [(String,String)]
+    samples =
+        [ f "a"
+        , f "A"
+        , f "A1"
+        , f "a_"
+        , f "a1_B2"
+        , f "_abc"
+        , f "__abc"
+        , f "a'"
+        , f "_a'"
+        , f "a'b"
+        , f "a-"
+        , f "a1-B2"
+        , f "a1-B2-"
+        ]
+      where
+        f s = (s,s)
+
+    counter_samples =
+        [ ""
+        , "1"
+        , "_"
+        , "__"
+        , "__1"
+        , "1a"
+        , "'"
+        , "'a"
+        , "_'"
+        , "_1'"
+        ]
+
 date_macro :: RegexType -> MacroEnv -> PreludeMacro -> Maybe MacroDescriptor
 date_macro rty env pm =
   Just $ run_tests rty parseDate samples env pm
@@ -636,7 +695,7 @@
   Just $ run_tests rty parseShortMonth samples env pm
     MacroDescriptor
       { _md_source          = bracketedRegexSource $
-                                intercalate "|" $ elems shortMonthArray
+                                intercalate "|" $ map T.unpack $ elems shortMonthArray
       , _md_samples         = map fst samples
       , _md_counter_samples = counter_samples
       , _md_test_results    = []
@@ -742,14 +801,14 @@
 
     re_tdfa = bracketedRegexSource $
           intercalate "|" $
-            [ kw
+            [ T.unpack kw
               | (kw0,kws) <- map severityKeywords [minBound..maxBound]
               , kw <- kw0:kws
               ]
 
     re_pcre = bracketedRegexSource $
           intercalate "|" $
-            [ kw
+            [ T.unpack kw
               | (kw0,kws) <- map severityKeywords $
                                   filter (/=Err) [minBound..maxBound]
               , kw <- kw0:kws
diff --git a/Text/RE/PCRE.hs b/Text/RE/PCRE.hs
--- a/Text/RE/PCRE.hs
+++ b/Text/RE/PCRE.hs
@@ -1,4 +1,8 @@
 {-# LANGUAGE FlexibleContexts           #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 {-# OPTIONS_GHC -fno-warn-dodgy-exports #-}
 
 module Text.RE.PCRE
diff --git a/Text/RE/PCRE/ByteString.hs b/Text/RE/PCRE/ByteString.hs
--- a/Text/RE/PCRE/ByteString.hs
+++ b/Text/RE/PCRE/ByteString.hs
@@ -2,6 +2,10 @@
 {-# LANGUAGE FlexibleContexts           #-}
 {-# LANGUAGE FlexibleInstances          #-}
 {-# OPTIONS_GHC -fno-warn-orphans       #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 
 module Text.RE.PCRE.ByteString
   ( (*=~)
diff --git a/Text/RE/PCRE/ByteString/Lazy.hs b/Text/RE/PCRE/ByteString/Lazy.hs
--- a/Text/RE/PCRE/ByteString/Lazy.hs
+++ b/Text/RE/PCRE/ByteString/Lazy.hs
@@ -2,6 +2,10 @@
 {-# LANGUAGE FlexibleContexts           #-}
 {-# LANGUAGE FlexibleInstances          #-}
 {-# OPTIONS_GHC -fno-warn-orphans       #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 
 module Text.RE.PCRE.ByteString.Lazy
   ( (*=~)
diff --git a/Text/RE/PCRE/RE.hs b/Text/RE/PCRE/RE.hs
--- a/Text/RE/PCRE/RE.hs
+++ b/Text/RE/PCRE/RE.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude          #-}
 {-# LANGUAGE RecordWildCards            #-}
 {-# LANGUAGE QuasiQuotes                #-}
 {-# LANGUAGE TemplateHaskell            #-}
@@ -5,6 +6,10 @@
 {-# LANGUAGE TypeSynonymInstances       #-}
 {-# LANGUAGE FlexibleInstances          #-}
 {-# LANGUAGE FlexibleContexts           #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 {-# OPTIONS_GHC -fno-warn-orphans       #-}
 
 module Text.RE.PCRE.RE
@@ -39,11 +44,11 @@
   , compileRegex
   ) where
 
-import           Control.Applicative
 import           Data.Bits
 import           Data.Functor.Identity
 import           Language.Haskell.TH
 import           Language.Haskell.TH.Quote
+import           Prelude.Compat
 import           Text.RE
 import           Text.RE.Internal.NamedCaptures
 import           Text.RE.Internal.PreludeMacros
diff --git a/Text/RE/PCRE/Sequence.hs b/Text/RE/PCRE/Sequence.hs
--- a/Text/RE/PCRE/Sequence.hs
+++ b/Text/RE/PCRE/Sequence.hs
@@ -2,6 +2,10 @@
 {-# LANGUAGE FlexibleContexts           #-}
 {-# LANGUAGE FlexibleInstances          #-}
 {-# OPTIONS_GHC -fno-warn-orphans       #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 
 module Text.RE.PCRE.Sequence
   ( (*=~)
diff --git a/Text/RE/PCRE/String.hs b/Text/RE/PCRE/String.hs
--- a/Text/RE/PCRE/String.hs
+++ b/Text/RE/PCRE/String.hs
@@ -2,6 +2,10 @@
 {-# LANGUAGE FlexibleContexts           #-}
 {-# LANGUAGE FlexibleInstances          #-}
 {-# OPTIONS_GHC -fno-warn-orphans       #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 
 module Text.RE.PCRE.String
   ( (*=~)
diff --git a/Text/RE/Parsers.hs b/Text/RE/Parsers.hs
--- a/Text/RE/Parsers.hs
+++ b/Text/RE/Parsers.hs
@@ -1,3 +1,6 @@
+{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}
+{-# LANGUAGE OverloadedStrings                  #-}
+
 module Text.RE.Parsers
   ( parseInteger
   , parseHex
@@ -23,7 +26,9 @@
 import           Data.Array
 import qualified Data.HashMap.Strict        as HM
 import           Data.Maybe
+import qualified Data.Text                  as T
 import           Data.Time
+import qualified Data.Time.Locale.Compat    as LC
 import           Data.Word
 import           Text.Printf
 import           Text.Read
@@ -39,17 +44,11 @@
 parseDouble :: Replace a => a -> Maybe Double
 parseDouble = readMaybe . unpack_
 
-parseString :: Replace a => a -> Maybe String
+parseString :: Replace a => a -> Maybe T.Text
 parseString = readMaybe . unpack_
 
-parseSimpleString :: Replace a => a -> Maybe String
-parseSimpleString = topntail . unpack_
-  where
-    topntail  ('"':t) = topntail' $ reverse t
-    topntail  _       = Nothing
-
-    topntail' ('"':rt) = Just $ reverse rt
-    topntail' _        = Nothing
+parseSimpleString :: Replace a => a -> Maybe T.Text
+parseSimpleString = Just . T.dropEnd 1 . T.drop 1 . textify
 
 date_templates, time_templates, timezone_templates,
   date_time_8601_templates, date_time_templates :: [String]
@@ -98,16 +97,16 @@
 parse_time tpls = prs . unpack_
   where
     prs s = listToMaybe $ catMaybes
-      [ parseTimeM False defaultTimeLocale fmt s
+      [ parseTime LC.defaultTimeLocale fmt s
           | fmt<-tpls
           ]
 
 short_month_hm :: HM.HashMap String Int
-short_month_hm = HM.fromList [ (shortMonthArray!i,i) | i<-[1..12] ]
+short_month_hm = HM.fromList [ (T.unpack $ shortMonthArray!i,i) | i<-[1..12] ]
 
-shortMonthArray :: Array Int String
+shortMonthArray :: Array Int T.Text
 shortMonthArray = listArray (1,12) $
-  words "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
+  T.words "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
 
 type IPV4Address = (Word8,Word8,Word8,Word8)
 
@@ -138,9 +137,9 @@
   deriving (Bounded,Enum,Ord,Eq,Show)
 
 parseSeverity :: Replace a => a -> Maybe Severity
-parseSeverity = flip HM.lookup severity_hm . unpack_
+parseSeverity = flip HM.lookup severity_hm . textify
 
-severity_hm :: HM.HashMap String Severity
+severity_hm :: HM.HashMap T.Text Severity
 severity_hm = HM.fromList
   [ (kw,pri)
       | pri<-[minBound..maxBound]
@@ -148,7 +147,7 @@
       , kw <- kw0:kws
       ]
 
-severityKeywords :: Severity -> (String,[String])
+severityKeywords :: Severity -> (T.Text,[T.Text])
 severityKeywords pri = case pri of
   Emerg     -> (,) "emerg"    ["panic"]
   Alert     -> (,) "alert"    []
diff --git a/Text/RE/Replace.lhs b/Text/RE/Replace.lhs
--- a/Text/RE/Replace.lhs
+++ b/Text/RE/Replace.lhs
@@ -1,4 +1,5 @@
 \begin{code}
+{-# LANGUAGE NoImplicitPrelude          #-}
 {-# LANGUAGE QuasiQuotes                #-}
 {-# LANGUAGE OverloadedStrings          #-}
 {-# LANGUAGE RecordWildCards            #-}
@@ -41,6 +42,7 @@
 import qualified Data.Text                      as T
 import qualified Data.Text.Encoding             as TE
 import qualified Data.Text.Lazy                 as LT
+import           Prelude.Compat
 import           Text.Heredoc
 import           Text.RE.Capture
 import           Text.RE.CaptureID
@@ -461,7 +463,7 @@
     Just $ replaceAllCaptures' TOP phi $
       tpl $=~ [here|\$(\$|[0-9]+|\{([^{}]+)\})|]
   where
-    phi t_mtch _ _ = case captureMaybe c2 t_mtch of
+    phi t_mtch _ _ = case t_mtch !$? c2  of
       Just cap -> this $ CID_name $ CaptureName txt
         where
           txt = T.pack $ unpack $ capturedText cap
@@ -472,7 +474,7 @@
         s  = unpack t
         t  = capturedText $ capture c1 t_mtch
 
-        this cid = capturedText <$> captureMaybe cid mtch
+        this cid = capturedText <$> mtch !$? cid
 
     c1 = CID_ordinal $ CaptureOrdinal 1
     c2 = CID_ordinal $ CaptureOrdinal 2
diff --git a/Text/RE/TDFA.hs b/Text/RE/TDFA.hs
--- a/Text/RE/TDFA.hs
+++ b/Text/RE/TDFA.hs
@@ -1,4 +1,8 @@
 {-# LANGUAGE FlexibleContexts           #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 {-# OPTIONS_GHC -fno-warn-dodgy-exports #-}
 
 module Text.RE.TDFA
diff --git a/Text/RE/TDFA/ByteString.hs b/Text/RE/TDFA/ByteString.hs
--- a/Text/RE/TDFA/ByteString.hs
+++ b/Text/RE/TDFA/ByteString.hs
@@ -2,6 +2,10 @@
 {-# LANGUAGE FlexibleContexts           #-}
 {-# LANGUAGE FlexibleInstances          #-}
 {-# OPTIONS_GHC -fno-warn-orphans       #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 
 module Text.RE.TDFA.ByteString
   ( (*=~)
diff --git a/Text/RE/TDFA/ByteString/Lazy.hs b/Text/RE/TDFA/ByteString/Lazy.hs
--- a/Text/RE/TDFA/ByteString/Lazy.hs
+++ b/Text/RE/TDFA/ByteString/Lazy.hs
@@ -2,6 +2,10 @@
 {-# LANGUAGE FlexibleContexts           #-}
 {-# LANGUAGE FlexibleInstances          #-}
 {-# OPTIONS_GHC -fno-warn-orphans       #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 
 module Text.RE.TDFA.ByteString.Lazy
   ( (*=~)
diff --git a/Text/RE/TDFA/RE.hs b/Text/RE/TDFA/RE.hs
--- a/Text/RE/TDFA/RE.hs
+++ b/Text/RE/TDFA/RE.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NoImplicitPrelude          #-}
 {-# LANGUAGE RecordWildCards            #-}
 {-# LANGUAGE QuasiQuotes                #-}
 {-# LANGUAGE TemplateHaskell            #-}
@@ -5,6 +6,10 @@
 {-# LANGUAGE TypeSynonymInstances       #-}
 {-# LANGUAGE FlexibleInstances          #-}
 {-# LANGUAGE FlexibleContexts           #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 {-# OPTIONS_GHC -fno-warn-orphans       #-}
 
 module Text.RE.TDFA.RE
@@ -39,10 +44,10 @@
   , compileRegex
   ) where
 
-import           Control.Applicative
 import           Data.Functor.Identity
 import           Language.Haskell.TH
 import           Language.Haskell.TH.Quote
+import           Prelude.Compat
 import           Text.RE
 import           Text.RE.Internal.NamedCaptures
 import           Text.RE.Internal.PreludeMacros
diff --git a/Text/RE/TDFA/Sequence.hs b/Text/RE/TDFA/Sequence.hs
--- a/Text/RE/TDFA/Sequence.hs
+++ b/Text/RE/TDFA/Sequence.hs
@@ -2,6 +2,10 @@
 {-# LANGUAGE FlexibleContexts           #-}
 {-# LANGUAGE FlexibleInstances          #-}
 {-# OPTIONS_GHC -fno-warn-orphans       #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 
 module Text.RE.TDFA.Sequence
   ( (*=~)
diff --git a/Text/RE/TDFA/String.hs b/Text/RE/TDFA/String.hs
--- a/Text/RE/TDFA/String.hs
+++ b/Text/RE/TDFA/String.hs
@@ -2,6 +2,10 @@
 {-# LANGUAGE FlexibleContexts           #-}
 {-# LANGUAGE FlexibleInstances          #-}
 {-# OPTIONS_GHC -fno-warn-orphans       #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 
 module Text.RE.TDFA.String
   ( (*=~)
diff --git a/Text/RE/TDFA/Text.hs b/Text/RE/TDFA/Text.hs
--- a/Text/RE/TDFA/Text.hs
+++ b/Text/RE/TDFA/Text.hs
@@ -2,6 +2,10 @@
 {-# LANGUAGE FlexibleContexts           #-}
 {-# LANGUAGE FlexibleInstances          #-}
 {-# OPTIONS_GHC -fno-warn-orphans       #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 
 module Text.RE.TDFA.Text
   ( (*=~)
diff --git a/Text/RE/TDFA/Text/Lazy.hs b/Text/RE/TDFA/Text/Lazy.hs
--- a/Text/RE/TDFA/Text/Lazy.hs
+++ b/Text/RE/TDFA/Text/Lazy.hs
@@ -2,6 +2,10 @@
 {-# LANGUAGE FlexibleContexts           #-}
 {-# LANGUAGE FlexibleInstances          #-}
 {-# OPTIONS_GHC -fno-warn-orphans       #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 
 module Text.RE.TDFA.Text.Lazy
   ( (*=~)
diff --git a/Text/RE/TestBench.lhs b/Text/RE/TestBench.lhs
--- a/Text/RE/TestBench.lhs
+++ b/Text/RE/TestBench.lhs
@@ -1,7 +1,12 @@
 \begin{code}
+{-# LANGUAGE NoImplicitPrelude          #-}
 {-# LANGUAGE RecordWildCards            #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE OverloadedStrings          #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 
 module Text.RE.TestBench
   ( MacroID(..)
@@ -23,17 +28,17 @@
   , formatMacroSources
   , formatMacroSource
   , testMacroDescriptors
--- , regexSource
   ) where
 
 import           Data.Array
-import           Control.Applicative
+import           Data.Char
 import qualified Data.HashMap.Lazy              as HML
-import           Data.List
+import qualified Data.List                      as L
 import           Data.Maybe
 import           Data.Ord
 import           Data.String
 import           Text.Printf
+import           Prelude.Compat
 import           Text.RE.Capture
 import           Text.RE.Options
 import           Text.RE.Replace
@@ -200,8 +205,10 @@
     writeFile fp_t $ formatMacroTable   rty              m_env
     writeFile fp_s $ formatMacroSources rty ExclCaptures m_env
   where
-    fp_t = "tables/" ++ lab ++ "-" ++ show rty ++ ".md"
-    fp_s = "tables/" ++ lab ++ "-" ++ show rty ++ ".txt"
+    fp_t  = "docs/" ++ rty_s ++ "-" ++ lab ++ ".txt"
+    fp_s  = "docs/" ++ rty_s ++ "-" ++ lab ++ "-src.txt"
+
+    rty_s = map toLower $ show rty
 \end{code}
 
 \begin{code}
@@ -209,7 +216,7 @@
 formatMacroTable rty env = unlines $
   format_table macro_table_hdr
     [ macro_table_row rty mid md
-        | (mid,md) <- sortBy (comparing fst) $ HML.toList env
+        | (mid,md) <- L.sortBy (comparing fst) $ HML.toList env
         ]
 \end{code}
 
@@ -240,7 +247,7 @@
                    -> String
 formatMacroSources rty wc env = unlines $
     [ printf "%-20s : %s" (_MacroID mid) $ formatMacroSource rty wc env mid
-        | mid <- sort $ HML.keys env
+        | mid <- L.sort $ HML.keys env
         ]
 \end{code}
 
@@ -363,7 +370,7 @@
 
 format_row :: Array Col Int -> TableRow -> [String]
 format_row cw_arr row =
-  [ ("|"++) $ intercalate "|"
+  [ ("|"++) $ L.intercalate "|"
       [ field cw_arr row c i | c<-[minBound..maxBound] ]
     | i <- [0..depth-1]
     ]
diff --git a/Text/RE/Tools/Grep.lhs b/Text/RE/Tools/Grep.lhs
--- a/Text/RE/Tools/Grep.lhs
+++ b/Text/RE/Tools/Grep.lhs
@@ -1,16 +1,19 @@
 \begin{code}
+{-# LANGUAGE NoImplicitPrelude          #-}
 {-# LANGUAGE RecordWildCards            #-}
 {-# LANGUAGE FlexibleContexts           #-}
+{-# LANGUAGE CPP                        #-}
 
 module Text.RE.Tools.Grep
   ( grep
   , grepLines
   , GrepScript
   , grepScript
+  , linesMatched
   ) where
 
-import           Control.Applicative
 import qualified Data.ByteString.Lazy.Char8               as LBS
+import           Prelude.Compat
 import           Text.Printf
 import           Text.RE.Capture
 import           Text.RE.IsRegex
@@ -47,12 +50,12 @@
       Just t  -> t : loop (succ i) lns
 
 report :: [Line] -> String
-report = unlines . map fmt . lines_matched
+report = unlines . map fmt . linesMatched
   where
     fmt Line{..} =
       printf "%05d %s" (getLineNo _ln_no) $
           LBS.unpack $ matchesSource _ln_matches
 
-lines_matched :: [Line] -> [Line]
-lines_matched = filter $ anyMatches . _ln_matches
+linesMatched :: [Line] -> [Line]
+linesMatched = filter $ anyMatches . _ln_matches
 \end{code}
diff --git a/Text/RE/Tools/Lex.lhs b/Text/RE/Tools/Lex.lhs
--- a/Text/RE/Tools/Lex.lhs
+++ b/Text/RE/Tools/Lex.lhs
@@ -1,8 +1,12 @@
 \begin{code}
+{-# LANGUAGE NoImplicitPrelude          #-}
+
 module Text.RE.Tools.Lex where
 
-import           Control.Applicative
-import           Text.RE
+import           Prelude.Compat
+import           Text.RE.Capture
+import           Text.RE.IsRegex
+import           Text.RE.Replace
 
 
 alex :: IsRegex re s => [(re,Match s->Maybe t)] -> t -> s -> [t]
diff --git a/Text/RE/Tools/Sed.lhs b/Text/RE/Tools/Sed.lhs
--- a/Text/RE/Tools/Sed.lhs
+++ b/Text/RE/Tools/Sed.lhs
@@ -1,6 +1,11 @@
 \begin{code}
+{-# LANGUAGE NoImplicitPrelude          #-}
 {-# LANGUAGE RecordWildCards            #-}
 {-# LANGUAGE FlexibleContexts           #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 
 module Text.RE.Tools.Sed
   ( SedScript
@@ -8,8 +13,8 @@
   , sed'
   ) where
 
-import           Control.Applicative
 import qualified Data.ByteString.Lazy.Char8               as LBS
+import           Prelude.Compat
 import           Text.RE.Edit
 import           Text.RE.LineNo
 import           Text.RE.IsRegex
diff --git a/changelog b/changelog
--- a/changelog
+++ b/changelog
@@ -1,5 +1,17 @@
 -*-change-log-*-
 
+0.1.0.0 Chris Dornan <chris.dornan@irisconnect.co.uk> 2017-02-17
+  * Cabal file generated from a DRY template
+  * Library dependencies minimised, test depndencies moved into
+    examples/re-tests
+  * A proper static website generated by 're-prep all'
+  * README/sidebar Badges are a static record of current release
+    with links to a live build-status reporting on HEAD
+  * Added !$, !$?, !$$ and !$$? alternatives for looking up captures
+    in a Match
+  * Text.RE.Parsers now generate Text where they were generating String
+  * %nat, %int, %frac and %hex get their new names
+
 0.0.0.2 Chris Dornan <chris.dornan@irisconnect.co.uk> 2017-01-30
   * Fix for Windows
   * Remove hsyslog dependency
diff --git a/examples/TestKit.lhs b/examples/TestKit.lhs
--- a/examples/TestKit.lhs
+++ b/examples/TestKit.lhs
@@ -1,22 +1,104 @@
 \begin{code}
+{-# LANGUAGE NoImplicitPrelude          #-}
+{-# LANGUAGE QuasiQuotes                #-}
 {-# LANGUAGE RecordWildCards            #-}
 {-# LANGUAGE OverloadedStrings          #-}
+{-# LANGUAGE FlexibleContexts           #-}
+{-# LANGUAGE CPP                        #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+#endif
 
 module TestKit
-  ( Test
+  ( Vrn
+  , bumpVersion
+  , substVersion
+  , substVersion_
+  , Test
   , runTests
   , checkThis
   , test_pp
+  , cmp
   ) where
 
+import           Control.Applicative
 import           Control.Exception
+import qualified Control.Monad                            as M
+import           Data.Maybe
 import qualified Data.Text                                as T
+import qualified Data.ByteString.Lazy.Char8               as LBS
+import           Prelude.Compat
 import qualified Shelly                                   as SH
 import           System.Directory
 import           System.Environment
 import           System.Exit
 import           System.IO
+import           Text.Printf
+import           Text.RE.TDFA
 \end{code}
+
+
+Vrn and friends
+---------------
+
+\begin{code}
+data Vrn = Vrn { _vrn_a, _vrn_b, _vrn_c, _vrn_d :: Int }
+  deriving (Show,Eq,Ord)
+
+-- | register a new version of the package
+bumpVersion :: String -> IO ()
+bumpVersion vrn_s = do
+    vrn0 <- read_current_version
+    rex' <- compileRegex () $ printf "- \\[[xX]\\].*%d\\.%d\\.%d\\.%d" _vrn_a _vrn_b _vrn_c _vrn_d
+    nada <- null . linesMatched <$> grepLines rex' "lib/md/roadmap-incl.md"
+    M.when nada $
+      error $ vrn_s ++ ": not ticked off in the roadmap"
+    rex  <- compileRegex () $ printf "%d\\.%d\\.%d\\.%d" _vrn_a _vrn_b _vrn_c _vrn_d
+    nope <- null . linesMatched <$> grepLines rex "changelog"
+    M.when nope $
+      error $ vrn_s ++ ": not in the changelog"
+    case vrn > vrn0 of
+      True  -> do
+        write_current_version vrn
+        substVersion "lib/hackage-template.svg" "docs/badges/hackage.svg"
+      False -> error $
+        printf "version not later ~(%s > %s)" vrn_s $ present_vrn vrn0
+  where
+    vrn@Vrn{..} = parse_vrn vrn_s
+
+substVersion :: FilePath -> FilePath -> IO ()
+substVersion in_f out_f =
+    LBS.readFile in_f >>= substVersion_ >>= LBS.writeFile out_f
+
+substVersion_ :: (IsRegex RE a,Replace a) => a -> IO a
+substVersion_ txt =
+    flip replaceAll ms . pack_ . present_vrn <$> read_current_version
+  where
+    ms = txt *=~ [re|<<\$version\$>>|]
+
+read_current_version :: IO Vrn
+read_current_version = parse_vrn <$> readFile "lib/version.txt"
+
+write_current_version :: Vrn -> IO ()
+write_current_version = writeFile "lib/version.txt" . present_vrn
+
+present_vrn :: Vrn -> String
+present_vrn Vrn{..} = printf "%d.%d.%d.%d" _vrn_a _vrn_b _vrn_c _vrn_d
+
+parse_vrn :: String -> Vrn
+parse_vrn vrn_s = case matched m of
+    True  -> Vrn (p [cp|a|]) (p [cp|b|]) (p [cp|c|]) (p [cp|d|])
+    False -> error $ "not a valid version: " ++ vrn_s
+  where
+    p c  = fromMaybe oops $ parseInteger $ m !$$ c
+    m    = vrn_s ?=~ [re|^${a}(@{%nat})\.${b}(@{%nat})\.${c}(@{%nat})\.${d}(@{%nat})$|]
+
+    oops = error "parse_vrn"
+\end{code}
+
+
+Test and friends
+----------------
 
 \begin{code}
 data Test =
diff --git a/examples/re-gen-cabals.lhs b/examples/re-gen-cabals.lhs
new file mode 100644
--- /dev/null
+++ b/examples/re-gen-cabals.lhs
@@ -0,0 +1,191 @@
+\begin{code}
+{-# LANGUAGE NoImplicitPrelude          #-}
+{-# LANGUAGE RecordWildCards            #-}
+{-# LANGUAGE TemplateHaskell            #-}
+{-# LANGUAGE QuasiQuotes                #-}
+{-# LANGUAGE OverloadedStrings          #-}
+{-# LANGUAGE CPP                        #-}
+
+module Main (main) where
+
+import qualified Data.ByteString.Lazy.Char8               as LBS
+import           Data.Char
+import           Data.IORef
+import qualified Data.List                                as L
+import qualified Data.Map                                 as Map
+import           Data.Maybe
+import           Data.Monoid
+import           Prelude.Compat
+import           System.Directory
+import           System.Environment
+import           System.Exit
+import           System.IO
+import           TestKit
+import           Text.Printf
+import           Text.RE.TDFA.ByteString.Lazy
+
+
+main :: IO ()
+main = do
+  (pn,as) <- (,) <$> getProgName <*> getArgs
+  case as of
+    []        -> test
+    ["test"]  -> test
+    ["gen"]   -> gen  "lib/cabal-masters/regex.cabal" "regex.cabal"
+    _         -> do
+      hPutStrLn stderr $ "usage: " ++ pn ++ " [test|gen]"
+      exitWith $ ExitFailure 1
+
+test :: IO ()
+test = do
+  createDirectoryIfMissing False "tmp"
+  gen "lib/cabal-masters/regex.cabal" "tmp/regex.cabal"
+  ok <- cmp "tmp/regex.cabal" "regex.cabal"
+  case ok of
+    True  -> return ()
+    False -> exitWith $ ExitFailure 1
+
+gen :: FilePath -> FilePath -> IO ()
+gen in_f out_f = do
+    ctx <- setup
+    substVersion in_f "tmp/regex-vrn.cabal"
+    sed (gc_script ctx) "tmp/regex-vrn.cabal" out_f
+
+data Ctx =
+  Ctx
+    { _ctx_package_constraints :: IORef (Map.Map LBS.ByteString LBS.ByteString)
+    , _ctx_test_exe            :: IORef (Maybe TestExe)
+    }
+
+data TestExe =
+  TestExe
+    { _te_test :: Bool
+    , _te_exe  :: Bool
+    , _te_name :: LBS.ByteString
+    , _te_text :: LBS.ByteString
+    }
+  deriving (Show)
+
+setup :: IO Ctx
+setup = Ctx <$> (newIORef Map.empty) <*> (newIORef Nothing)
+
+gc_script :: Ctx -> SedScript RE
+gc_script ctx = Select
+    [ (,) [re|^%- +${pkg}(@{%id-}) +${cond}(.*)$|]             $ EDIT_gen $ cond_gen                 ctx
+    , (,) [re|^%build-depends +${list}(@{%id-}( +@{%id-})+)$|] $ EDIT_gen $ build_depends_gen        ctx
+    , (,) [re|^%test +${i}(@{%id-})$|]                         $ EDIT_gen $ test_exe_gen True  False ctx
+    , (,) [re|^%exe +${i}(@{%id-})$|]                          $ EDIT_gen $ test_exe_gen False True  ctx
+    , (,) [re|^%test-exe +${i}(@{%id-})$|]                     $ EDIT_gen $ test_exe_gen True  True  ctx
+    , (,) [re|^.*$|]                                           $ EDIT_gen $ default_gen              ctx
+    ]
+
+cond_gen, build_depends_gen,
+  default_gen :: Ctx
+              -> LineNo
+              -> Matches LBS.ByteString
+              -> IO (LineEdit LBS.ByteString)
+
+cond_gen Ctx{..} _ mtchs = do
+    modifyIORef _ctx_package_constraints $ Map.insert pkg cond
+    return Delete
+  where
+    pkg  = captureText [cp|pkg|]  mtch
+    cond = captureText [cp|cond|] mtch
+
+    mtch = allMatches mtchs !! 0
+
+build_depends_gen ctx@Ctx{..} _ mtchs = do
+    mp <- readIORef _ctx_package_constraints
+    put ctx $ mk_build_depends mp lst
+  where
+    lst  = LBS.words $ captureText [cp|list|] mtch
+    mtch = allMatches mtchs !! 0
+
+default_gen ctx@Ctx{..} _ mtchs = do
+    mb <- readIORef _ctx_test_exe
+    case mb of
+      Nothing -> return $ ReplaceWith ln
+      Just te -> case isSpace $ LBS.head $ ln<>"\n" of
+        True  -> put ctx ln
+        False -> adjust_le (<>ln) <$> close_test_exe ctx te
+  where
+    ln   = matchSource mtch
+    mtch = allMatches mtchs !! 0
+
+test_exe_gen :: Bool
+             -> Bool
+             -> Ctx
+             -> LineNo
+             -> Matches LBS.ByteString
+             -> IO (LineEdit LBS.ByteString)
+test_exe_gen is_t is_e ctx _ mtchs = do
+    mb <- readIORef  (_ctx_test_exe ctx)
+    le <- maybe (return Delete) (close_test_exe ctx) mb
+    writeIORef (_ctx_test_exe ctx) $ Just $
+      TestExe
+        { _te_test = is_t
+        , _te_exe  = is_e
+        , _te_name = i
+        , _te_text = ""
+        }
+    return le
+  where
+    i    = captureText [cp|i|] mtch
+
+    mtch = allMatches mtchs !! 0
+
+close_test_exe :: Ctx -> TestExe -> IO (LineEdit LBS.ByteString)
+close_test_exe ctx@Ctx{..} te = do
+  writeIORef _ctx_test_exe Nothing
+  put ctx $ mconcat $ concat $
+    [ [ mk_test_exe False te "Executable" | _te_exe  te ]
+    , [ mk_test_exe True  te "Test-Suite" | _te_test te ]
+    ]
+
+put :: Ctx -> LBS.ByteString -> IO (LineEdit LBS.ByteString)
+put Ctx{..} lbs = do
+    mb <- readIORef _ctx_test_exe
+    case mb of
+      Nothing -> return $ ReplaceWith lbs
+      Just te -> do
+        writeIORef _ctx_test_exe $ Just te { _te_text = _te_text te <> lbs <> "\n" }
+        return Delete
+
+mk_test_exe :: Bool -> TestExe -> LBS.ByteString -> LBS.ByteString
+mk_test_exe is_t te te_lbs_kw = (<>_te_text te) $ LBS.unlines $ concat
+    [ [ LBS.pack $ printf "%s %s" (LBS.unpack te_lbs_kw) nm ]
+    , [ "    type:               exitcode-stdio-1.0" | is_t ]
+    ]
+  where
+    nm = case is_t of
+      True  -> LBS.unpack $ _te_name te <> "-test"
+      False -> LBS.unpack $ _te_name te
+
+mk_build_depends :: Map.Map LBS.ByteString LBS.ByteString
+                 -> [LBS.ByteString]
+                 -> LBS.ByteString
+mk_build_depends mp pks = LBS.unlines $
+        (:) "    Build-depends:" $
+          map fmt $ zip (True : repeat False) $
+              L.sortBy comp pks
+  where
+    fmt (isf,pk) = LBS.pack $
+      printf "      %c %-20s %s"
+        (if isf then ' ' else ',')
+        (LBS.unpack pk)
+        (maybe "" LBS.unpack $ Map.lookup pk mp)
+
+    comp x y = case (x=="regex",y=="regex") of
+      (True ,True ) -> EQ
+      (True ,False) -> LT
+      (False,True ) -> GT
+      (False,False) -> compare x y
+
+adjust_le :: (LBS.ByteString->LBS.ByteString)
+          -> LineEdit LBS.ByteString
+          -> LineEdit LBS.ByteString
+adjust_le f le = case le of
+  NoEdit          -> error "adjust_le: not enough context"
+  ReplaceWith lbs -> ReplaceWith $ f lbs
+  Delete          -> ReplaceWith $ f ""
+\end{code}
diff --git a/examples/re-gen-modules.lhs b/examples/re-gen-modules.lhs
--- a/examples/re-gen-modules.lhs
+++ b/examples/re-gen-modules.lhs
@@ -1,21 +1,22 @@
 \begin{code}
+{-# LANGUAGE NoImplicitPrelude          #-}
 {-# LANGUAGE TemplateHaskell            #-}
 {-# LANGUAGE QuasiQuotes                #-}
 {-# LANGUAGE OverloadedStrings          #-}
+{-# LANGUAGE CPP                        #-}
 
 module Main (main) where
 
-import           Control.Applicative
 import           Control.Exception
 import qualified Data.ByteString.Lazy.Char8               as LBS
 import qualified Data.Text                                as T
+import           Prelude.Compat
 import qualified Shelly                                   as SH
 import           System.Directory
 import           System.Environment
 import           System.Exit
 import           System.IO
 import           Text.RE.TDFA.ByteString.Lazy
-import           Text.RE.Tools.Sed
 
 
 main :: IO ()
diff --git a/examples/re-include.lhs b/examples/re-include.lhs
--- a/examples/re-include.lhs
+++ b/examples/re-include.lhs
@@ -1,4 +1,5 @@
 \begin{code}
+{-# LANGUAGE NoImplicitPrelude          #-}
 {-# LANGUAGE RecordWildCards            #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE TemplateHaskell            #-}
@@ -12,12 +13,12 @@
 import           Control.Applicative
 import qualified Data.ByteString.Lazy.Char8               as LBS
 import           Data.Maybe
+import qualified Data.Text                                as T
+import           Prelude.Compat
 import           System.Environment
 import           TestKit
 import           Text.RE.Edit
 import           Text.RE.TDFA.ByteString.Lazy
-import           Text.RE.Tools.Grep
-import           Text.RE.Tools.Sed
 \end{code}
 
 \begin{code}
@@ -66,7 +67,7 @@
     fp    = prs_s $ captureText [cp|file|] mtch
     re_s  = prs_s $ captureText [cp|rex|]  mtch
 
-    prs_s = fromMaybe (error "includeDoc") . parseString
+    prs_s = maybe (error "includeDoc") T.unpack . parseString
 \end{code}
 
 
diff --git a/examples/re-nginx-log-processor.lhs b/examples/re-nginx-log-processor.lhs
--- a/examples/re-nginx-log-processor.lhs
+++ b/examples/re-nginx-log-processor.lhs
@@ -1,4 +1,5 @@
 \begin{code}
+{-# LANGUAGE NoImplicitPrelude          #-}
 {-# LANGUAGE RecordWildCards            #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE TemplateHaskell            #-}
@@ -22,6 +23,7 @@
 import           Data.String
 import qualified Data.Text                                as T
 import           Data.Time
+import           Prelude.Compat
 import qualified Shelly                                   as SH
 import           System.Directory
 import           System.Environment
@@ -31,8 +33,7 @@
 import           Text.RE.Parsers
 import           Text.RE.TestBench
 import           Text.RE.PCRE.ByteString.Lazy
-import qualified Text.RE.PCRE.String              as S
-import           Text.RE.Tools.Sed
+import qualified Text.RE.PCRE.String                      as S
 import           Text.Printf
 \end{code}
 
@@ -201,7 +202,7 @@
   where
     (a,b,c,d) = _event_address
 
-    svrty_kw  = fst . severityKeywords
+    svrty_kw  = T.unpack . fst . severityKeywords
 
 class IsEvent a where
   mkEvent :: LineNo -> Source -> a -> Event
@@ -216,12 +217,12 @@
       , _event_address  = _a_remote_addr
       , _event_details  = LBS.pack $
           printf "%s %d %d %s %s %s"
-            _a_request
-            _a_status
-            _a_body_bytes
-            _a_http_referrer
-            _a_http_user_agent
-            _a_other
+            (T.unpack _a_request        )
+                      _a_status
+                      _a_body_bytes
+            (T.unpack _a_http_referrer  )
+            (T.unpack _a_http_user_agent)
+            (T.unpack _a_other          )
       }
 
 instance IsEvent Error where
@@ -318,7 +319,7 @@
 pid_tid_macro env mid =
   runTests regexType parse_pid_tid samples env mid
     MacroDescriptor
-      { _md_source          = "(?:@{%natural})#(?:@{%natural}):"
+      { _md_source          = "(?:@{%nat})#(?:@{%nat}):"
       , _md_samples         = map fst samples
       , _md_counter_samples = counter_samples
       , _md_test_results    = []
@@ -440,15 +441,15 @@
 
 data Access =
   Access
-    { _a_remote_addr      :: IPV4Address
-    , _a_remote_user      :: User
-    , _a_time_local       :: UTCTime
-    , _a_request          :: String
-    , _a_status           :: Int
-    , _a_body_bytes       :: Int
-    , _a_http_referrer    :: String
-    , _a_http_user_agent  :: String
-    , _a_other            :: String
+    { _a_remote_addr      :: !IPV4Address
+    , _a_remote_user      :: !User
+    , _a_time_local       :: !UTCTime
+    , _a_request          :: !T.Text
+    , _a_status           :: !Int
+    , _a_body_bytes       :: !Int
+    , _a_http_referrer    :: !T.Text
+    , _a_http_user_agent  :: !T.Text
+    , _a_other            :: !T.Text
     }
   deriving (Eq,Show)
 \end{code}
@@ -461,8 +462,8 @@
   , "(@{user})"
   , "\\[(@{%datetime.clf})\\]"
   , "(@{%string.simple})"
-  , "(@{%natural})"
-  , "(@{%natural})"
+  , "(@{%nat})"
+  , "(@{%nat})"
   , "(@{%string.simple})"
   , "(@{%string.simple})"
   , "(@{%string.simple})"
@@ -563,7 +564,7 @@
 --
 
 parse_pid_tid :: Replace a => a -> Maybe (Int,Int)
-parse_pid_tid x = case allMatches $ unpack_ x S.*=~ [re|@{%natural}|] of
+parse_pid_tid x = case allMatches $ unpack_ x S.*=~ [re|@{%nat}|] of
     [cs,cs'] -> (,) <$> p cs <*> p cs'
     _        -> Nothing
   where
diff --git a/examples/re-pp.lhs b/examples/re-pp.lhs
deleted file mode 100644
--- a/examples/re-pp.lhs
+++ /dev/null
@@ -1,459 +0,0 @@
-\begin{code}
-{-# LANGUAGE RecordWildCards            #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE TemplateHaskell            #-}
-{-# LANGUAGE QuasiQuotes                #-}
-{-# LANGUAGE OverloadedStrings          #-}
-
-module Main
-  ( main
-  ) where
-
-import           Control.Applicative
-import           Control.Monad
-import qualified Data.ByteString.Lazy.Char8               as LBS
-import           Data.IORef
-import           Data.Maybe
-import           Data.Monoid
-import qualified Data.Text                                as T
-import qualified Shelly                                   as SH
-import           System.Directory
-import           System.Environment
-import           TestKit
-import           Text.Printf
-import           Text.RE.Edit
-import           Text.RE.TDFA.ByteString.Lazy
-import           Text.RE.TDFA.Text                as T
-import           Text.RE.Tools.Grep
-import           Text.RE.Tools.Sed
-\end{code}
-
-\begin{code}
-main :: IO ()
-main = do
-  as  <- getArgs
-  case as of
-    []                          -> test
-    ["test"]                    -> test
-    ["doc",fn,fn'] | is_file fn -> doc fn fn'
-    ["gen",fn,fn'] | is_file fn -> gen fn fn'
-    ["all"]                     -> gen_all
-    _                           -> usage
-  where
-    is_file = not . (== "--") . take 2
-
-    doc fn fn' = docMode >>= \dm -> loop dm fn fn'
-    gen fn fn' = genMode >>= \gm -> loop gm fn fn'
-
-    usage = do
-      pnm <- getProgName
-      let prg = ((pnm++" ")++)
-      putStr $ unlines
-        [ "usage:"
-        , "  "++prg "--help"
-        , "  "++prg "[test]"
-        , "  "++prg "all"
-        , "  "++prg "doc (-|<in-file>) (-|<out-file>)"
-        , "  "++prg "gen (-|<in-file>) (-|<out-file>)"
-        ]
-\end{code}
-
-
-The Sed Script
---------------
-
-\begin{code}
--- | the MODE determines whether we are generating documentation
--- or a Haskell testsuite and includes any IO-accessible state
--- needed by the relevant processor
-data MODE
-  = Doc DocState  -- ^ document-generation state
-  | Gen GenState  -- ^ adjusting-the-program-for-testing state
-\end{code}
-
-The `DocState` is initialised to `Outside` and flips though the different
-states as it traverses a code block, so that we can wrap code
-blocks in special <div class="replcodeblock"> blocks when their
-first line indicates that it contains a REPL calculation, which the
-style sheet can pick up and present accordingly.
-
-\begin{code}
-data DocMode
-  = Outside     -- not inside a begin{code} ... \end{code} block
-  | Beginning   -- at the start of a begin{code} ... \end{code} block
-  | InsideRepl  -- inside a REPL code block
-  | InsideProg  -- inside a non-REPL code block
-  deriving (Eq,Show)
-
-type DocState = IORef DocMode
-
-genMode :: IO MODE
-genMode = Gen <$> newIORef []
-\end{code}
-
-\begin{code}
--- | the state is the accumulated test function identifiers for
--- generating the list of them gets added to the end of the programme
-type GenState = IORef [String]
-
-docMode :: IO MODE
-docMode = Doc <$> newIORef Outside
-\end{code}
-
-
-\begin{code}
-loop :: MODE -> FilePath -> FilePath -> IO ()
-loop mode =
-  sed $ Select
-    [ (,) [re|^%include ${file}(@{%string}) ${rex}(@{%string})$|]      $ EDIT_fun TOP $ include mode
-    , (,) [re|^%main ${arg}(top|bottom)$|]                             $ EDIT_gen     $ main_   mode
-    , (,) [re|^\\begin\{code\}$|]                                      $ EDIT_gen     $ begin   mode
-    , (,) [re|^${fn}(evalme@{%id}) = checkThis ${arg}(@{%string}).*$|] $ EDIT_fun TOP $ evalme  mode
-    , (,) [re|^\\end\{code\}$|]                                        $ EDIT_fun TOP $ end     mode
-    , (,) [re|^.*$|]                                                   $ EDIT_fun TOP $ other   mode
-    ]
-\end{code}
-
-\begin{code}
-include, evalme, end,
-  other :: MODE
-        -> LineNo
-        -> Match LBS.ByteString
-        -> Location
-        -> Capture LBS.ByteString
-        -> IO (Maybe LBS.ByteString)
-
-main_,
-  begin :: MODE
-        -> LineNo
-        -> Matches LBS.ByteString
-        -> IO (LineEdit LBS.ByteString)
-
-include (Doc _ ) = includeDoc
-include (Gen _ ) = passthru
-
-main_   (Doc _ ) = mainDoc
-main_   (Gen gs) = mainGen    gs
-
-begin   (Doc ds) = beginDoc   ds
-begin   (Gen _ ) = passthru_g
-
-evalme  (Doc ds) = evalmeDoc  ds
-evalme  (Gen gs) = evalmeGen  gs
-
-end     (Doc ds) = endDoc     ds
-end     (Gen _ ) = passthru
-
-other   (Doc ds) = otherDoc   ds
-other   (Gen _ ) = passthru
-
-passthru :: LineNo
-         -> Match LBS.ByteString
-         -> Location
-         -> Capture LBS.ByteString
-         -> IO (Maybe LBS.ByteString)
-passthru _ _ _ _ = return Nothing
-
-passthru_g :: LineNo
-           -> Matches LBS.ByteString
-           -> IO (LineEdit LBS.ByteString)
-passthru_g _ _ = return NoEdit
-\end{code}
-
-
-Script to Generate All Tutorial Tests and Docs
-----------------------------------------------
-
-\begin{code}
-gen_all :: IO ()
-gen_all = do
-    -- prepare HTML docs for the (literate) tools
-    pd "re-gen-modules"
-    pd "re-include"
-    pd "re-nginx-log-processor"
-    pd "re-pp"
-    pd "re-tests"
-    pd "TestKit"
-    pd "RE/Capture"
-    pd "RE/Edit"
-    pd "RE/IsRegex"
-    pd "RE/Options"
-    pd "RE/Replace"
-    pd "RE/TestBench"
-    pd "RE/Tools/Grep"
-    pd "RE/Tools/Lex"
-    pd "RE/Tools/Sed"
-    pd "RE/Internal/NamedCaptures"
-    -- render the tutorial in HTML
-    dm <- docMode
-    loop dm "examples/re-tutorial-master.lhs" "tmp/re-tutorial.lhs"
-    createDirectoryIfMissing False "tmp"
-    pandoc'
-      "re-tutorial.lhs"
-      "examples/re-tutorial.lhs"
-      "tmp/re-tutorial.lhs"
-      "docs/re-tutorial.html"
-    -- generate the tutorial-based tests
-    gm <- genMode
-    loop gm "examples/re-tutorial-master.lhs" "examples/re-tutorial.lhs"
-    putStrLn ">> examples/re-tutorial.lhs"
-  where
-    pd fnm = case captureTextMaybe [cp|mnm|] $ fnm T.?=~ [re|^RE/(Tools/|Internal/)?${mnm}(@{%id})|] of
-        Just mnm -> pandoc fnm ("Text/"<>fnm<>".lhs") ("docs/"<>mnm<>".html")
-        Nothing  -> pandoc fnm (  "examples/"<>fnm<>".lhs") ("docs/"<>fnm<>".html")
-\end{code}
-
-
-Generating the Tutorial
------------------------
-
-\begin{code}
-includeDoc :: LineNo
-           -> Match LBS.ByteString
-           -> Location
-           -> Capture LBS.ByteString
-           -> IO (Maybe LBS.ByteString)
-includeDoc _ mtch _ _ = fmap Just $
-    extract fp =<< compileRegex () re_s
-  where
-    fp    = prs_s $ captureText [cp|file|] mtch
-    re_s  = prs_s $ captureText [cp|rex|]  mtch
-
-    prs_s = fromMaybe (error "includeDoc") . parseString
-\end{code}
-
-\begin{code}
-mainDoc :: LineNo
-        -> Matches LBS.ByteString
-        -> IO (LineEdit LBS.ByteString)
-mainDoc _ _ = return Delete
-\end{code}
-
-\begin{code}
-beginDoc :: DocState
-         -> LineNo
-         -> Matches LBS.ByteString
-         -> IO (LineEdit LBS.ByteString)
-beginDoc ds _ _ = writeIORef ds Beginning >> return Delete
-\end{code}
-
-\begin{code}
-evalmeDoc, endDoc, otherDoc :: DocState
-                            -> LineNo
-                            -> Match LBS.ByteString
-                            -> Location
-                            -> Capture LBS.ByteString
-                            -> IO (Maybe LBS.ByteString)
-
-evalmeDoc ds lno _ _ _ = do
-  dm <- readIORef ds
-  when (dm/=Beginning) $
-    bad_state "evalme" lno dm
-  writeIORef ds InsideRepl
-  return $ Just $ "<div class=\"replcodeblock\">\n"<>begin_code
-
-endDoc    ds lno _ _ _ = do
-  dm <- readIORef ds
-  case dm of
-    Outside    -> bad_state "end" lno dm
-    Beginning  -> return $ Just $ begin_code <> "\n" <> end_code
-    InsideRepl -> return $ Just $ end_code   <> "\n</div>"
-    InsideProg -> return   Nothing
-
-otherDoc  ds _ mtch _ _ = do
-  dm <- readIORef ds
-  case dm of
-    Beginning -> do
-      writeIORef ds InsideProg
-      return $ Just $ begin_code <> "\n" <> matchSource mtch
-    _ -> return Nothing
-
-bad_state :: String -> LineNo -> DocMode -> IO a
-bad_state lab lno dm = error $
-  printf "Bad document syntax: %s: %d: %s" lab (getLineNo lno) $ show dm
-\end{code}
-
-
-Generating the Tests
---------------------
-
-\begin{code}
-evalmeGen :: GenState
-          -> LineNo
-          -> Match LBS.ByteString
-          -> Location
-          -> Capture LBS.ByteString
-          -> IO (Maybe LBS.ByteString)
-evalmeGen gs _ mtch0 _ _ = Just <$>
-    replaceCapturesM replace_ ALL f mtch0
-  where
-    f mtch loc cap = case _loc_capture loc of
-      2 -> do
-          modifyIORef gs (ide:)
-          return $ Just $ LBS.pack $ show ide
-        where
-          ide = LBS.unpack $ captureText [cp|fn|] mtch
-      _ -> return $ Just $ capturedText cap
-\end{code}
-
-How are we doing?
-
-\begin{code}
-mainGen :: GenState
-        -> LineNo
-        -> Matches LBS.ByteString
-        -> IO (LineEdit LBS.ByteString)
-mainGen gs _ mtchs = case allMatches mtchs of
-  [mtch]  ->
-    case captureText [cp|arg|] $ mtch of
-      "top"    -> return $ ReplaceWith $ LBS.unlines $
-          [ begin_code
-          , "module Main(main) where"
-          , end_code
-          , ""
-          , "*********************************************************"
-          , "*"
-          , "* WARNING: this is generated from pp-tutorial-master.lhs "
-          , "*"
-          , "*********************************************************"
-          ]
-      "bottom" -> do
-        fns <- readIORef gs
-        return $ ReplaceWith $ LBS.unlines $
-          [ begin_code
-          , "main :: IO ()"
-          , "main = runTests"
-          ] ++ mk_list fns ++
-          [ end_code
-          ]
-      _ -> error "mainGen (b)"
-  _ -> error "mainGen (a)"
-\end{code}
-
-We cannot place these strings inline without confusing pandoc so we
-use these definitions instead.
-
-\begin{code}
-begin_code, end_code :: LBS.ByteString
-begin_code = "\\"<>"begin{code}"
-end_code   = "\\"<>"end{code}"
-\end{code}
-
-
-
-\begin{code}
-mk_list :: [String] -> [LBS.ByteString]
-mk_list []          = ["[]"]
-mk_list (ide0:ides) = f "[" ide0 $ foldr (f ",") ["  ]"] ides
-  where
-    f pfx ide t = ("  "<>pfx<>" "<>LBS.pack ide) : t
-\end{code}
-
-
-Extracting a Literate Fragment from a Haskell Program Text
-----------------------------------------------------------
-
-\begin{code}
-extract :: FilePath -> RE -> IO LBS.ByteString
-extract fp rex = extr . LBS.lines <$> LBS.readFile fp
-  where
-    extr lns =
-      case parse $ scan rex lns of
-        Nothing      -> oops
-        Just (lno,n) -> LBS.unlines $ (hdr :) $ (take n $ drop i lns) ++ [ftr]
-          where
-            i = getZeroBasedLineNo lno
-
-    oops = error $ concat
-      [ "failed to locate fragment matching "
-      , show $ reSource rex
-      , " in file "
-      , show fp
-      ]
-
-    hdr  = "<div class='includedcodeblock'>"
-    ftr  = "</div>"
-\end{code}
-
-\begin{code}
-parse :: [Token] -> Maybe (LineNo,Int)
-parse []       = Nothing
-parse (tk:tks) = case (tk,tks) of
-  (Bra b_ln,Hit:Ket k_ln:_) -> Just (b_ln,count_lines_incl b_ln k_ln)
-  _                         -> parse tks
-\end{code}
-
-\begin{code}
-count_lines_incl :: LineNo -> LineNo -> Int
-count_lines_incl b_ln k_ln =
-  getZeroBasedLineNo k_ln + 1 - getZeroBasedLineNo b_ln
-\end{code}
-
-\begin{code}
-data Token = Bra LineNo | Hit | Ket LineNo   deriving (Show)
-\end{code}
-
-\begin{code}
-scan :: RE -> [LBS.ByteString] -> [Token]
-scan rex = grepScript
-    [ (,) [re|\\begin\{code\}|] $ \i -> chk $ Bra i
-    , (,) rex                   $ \_ -> chk   Hit
-    , (,) [re|\\end\{code\}|]   $ \i -> chk $ Ket i
-    ]
-  where
-    chk x mtchs = case anyMatches mtchs of
-      True  -> Just x
-      False -> Nothing
-\end{code}
-
-
-pandoc
-------
-
-\begin{code}
-pandoc :: T.Text -> T.Text -> T.Text -> IO ()
-pandoc title in_file = pandoc' title in_file in_file
-
-pandoc' :: T.Text -> T.Text -> T.Text -> T.Text -> IO ()
-pandoc' title repo_path in_file out_file = do
-  writeFile "tmp/bc.html" bc
-  fmap (const ()) $
-    SH.shelly $ SH.verbosely $
-      SH.run "pandoc"
-        [ "-f", "markdown+lhs+grid_tables"
-        , "-t", "html"
-        , "-s"
-        , "-B", "tmp/bc.html"
-        , "-c", "lib/styles.css"
-        , "-c", "lib/bs.css"
-        , "-o", out_file
-        , in_file
-        ]
-  where
-    bc = concat
-      [ "<ol class='breadcrumb'><li><a href='.' title='Home'>"
-      , "Home</a></li> &gt; <a title='source file' href='"
-      , repo_url
-      , "'>"
-      , T.unpack title
-      , "</a></ol>"
-      ]
-
-    repo_url = concat
-      [ "https://github.com/iconnect/regex/blob/master/"
-      , T.unpack repo_path
-      ]
-\end{code}
-
-testing
--------
-
-\begin{code}
-test :: IO ()
-test = do
-  dm <- docMode
-  test_pp "pp-doc" (loop dm) "data/pp-test.lhs" "data/pp-result-doc.lhs"
-  gm <- genMode
-  test_pp "pp-gen" (loop gm) "data/pp-test.lhs" "data/pp-result-gen.lhs"
-  putStrLn "tests passed"
-\end{code}
diff --git a/examples/re-prep.lhs b/examples/re-prep.lhs
new file mode 100644
--- /dev/null
+++ b/examples/re-prep.lhs
@@ -0,0 +1,828 @@
+\begin{code}
+{-# LANGUAGE NoImplicitPrelude          #-}
+{-# LANGUAGE RecordWildCards            #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE TemplateHaskell            #-}
+{-# LANGUAGE QuasiQuotes                #-}
+{-# LANGUAGE FlexibleContexts           #-}
+{-# LANGUAGE OverloadedStrings          #-}
+
+module Main
+  ( main
+  ) where
+
+import           Control.Applicative
+import qualified Control.Monad                            as M
+import qualified Data.ByteString.Lazy.Char8               as LBS
+import           Data.IORef
+import           Data.Maybe
+import           Data.Monoid
+import qualified Data.Text                                as T
+import qualified Data.Text.Encoding                       as TE
+import           Network.HTTP.Conduit
+import           Prelude.Compat
+import qualified Shelly                                   as SH
+import           System.Directory
+import           System.Environment
+import           TestKit
+import           Text.Heredoc
+import           Text.Printf
+import           Text.RE.Edit
+import           Text.RE.TDFA.ByteString.Lazy
+import qualified Text.RE.TDFA.Text                        as TT
+\end{code}
+
+\begin{code}
+main :: IO ()
+main = do
+  as  <- getArgs
+  case as of
+    []                          -> test
+    ["test"]                    -> test
+    ["doc",fn,fn'] | is_file fn -> doc fn fn'
+    ["gen",fn,fn'] | is_file fn -> gen fn fn'
+    ["badges"]                  -> badges
+    ["bump-version",vrn]        -> bumpVersion vrn
+    ["pages"]                   -> pages
+    ["all"]                     -> gen_all
+    _                           -> usage
+  where
+    is_file = not . (== "--") . take 2
+
+    doc fn fn' = docMode >>= \dm -> loop dm fn fn'
+    gen fn fn' = genMode >>= \gm -> loop gm fn fn'
+
+    usage = do
+      pnm <- getProgName
+      let prg = (("  "++pnm++" ")++)
+      putStr $ unlines
+        [ "usage:"
+        , prg "--help"
+        , prg "[test]"
+        , prg "badges"
+        , prg "bump-version <version>"
+        , prg "pages"
+        , prg "all"
+        , prg "doc (-|<in-file>) (-|<out-file>)"
+        , prg "gen (-|<in-file>) (-|<out-file>)"
+        ]
+\end{code}
+
+
+The Sed Script
+--------------
+
+\begin{code}
+-- | the MODE determines whether we are generating documentation
+-- or a Haskell testsuite and includes any IO-accessible state
+-- needed by the relevant processor
+data MODE
+  = Doc DocState  -- ^ document-generation state
+  | Gen GenState  -- ^ adjusting-the-program-for-testing state
+\end{code}
+
+The `DocState` is initialised to `Outside` and flips though the different
+states as it traverses a code block, so that we can wrap code
+blocks in special <div class="replcodeblock"> blocks when their
+first line indicates that it contains a REPL calculation, which the
+style sheet can pick up and present accordingly.
+
+\begin{code}
+data DocMode
+  = Outside     -- not inside a begin{code} ... \end{code} block
+  | Beginning   -- at the start of a begin{code} ... \end{code} block
+  | InsideRepl  -- inside a REPL code block
+  | InsideProg  -- inside a non-REPL code block
+  deriving (Eq,Show)
+
+type DocState = IORef DocMode
+
+genMode :: IO MODE
+genMode = Gen <$> newIORef []
+\end{code}
+
+\begin{code}
+-- | the state is the accumulated test function identifiers for
+-- generating the list of them gets added to the end of the programme
+type GenState = IORef [String]
+
+docMode :: IO MODE
+docMode = Doc <$> newIORef Outside
+\end{code}
+
+
+\begin{code}
+loop :: MODE -> FilePath -> FilePath -> IO ()
+loop mode =
+  sed $ Select
+    [ (,) [re|^%include ${file}(@{%string}) ${rex}(@{%string})$|]      $ EDIT_fun TOP $ inclde mode
+    , (,) [re|^%main ${arg}(top|bottom)$|]                             $ EDIT_gen     $ main_  mode
+    , (,) [re|^\\begin\{code\}$|]                                      $ EDIT_gen     $ begin  mode
+    , (,) [re|^${fn}(evalme@{%id}) = checkThis ${arg}(@{%string}).*$|] $ EDIT_fun TOP $ evalme mode
+    , (,) [re|^\\end\{code\}$|]                                        $ EDIT_fun TOP $ end    mode
+    , (,) [re|^.*$|]                                                   $ EDIT_fun TOP $ other  mode
+    ]
+\end{code}
+
+\begin{code}
+inclde, evalme, end,
+  other :: MODE
+        -> LineNo
+        -> Match LBS.ByteString
+        -> Location
+        -> Capture LBS.ByteString
+        -> IO (Maybe LBS.ByteString)
+
+main_,
+  begin :: MODE
+        -> LineNo
+        -> Matches LBS.ByteString
+        -> IO (LineEdit LBS.ByteString)
+
+inclde (Doc _ ) = includeDoc
+inclde (Gen _ ) = passthru
+
+main_  (Doc _ ) = mainDoc
+main_  (Gen gs) = mainGen    gs
+
+begin  (Doc ds) = beginDoc   ds
+begin  (Gen _ ) = passthru_g
+
+evalme (Doc ds) = evalmeDoc  ds
+evalme (Gen gs) = evalmeGen  gs
+
+end    (Doc ds) = endDoc     ds
+end    (Gen _ ) = passthru
+
+other  (Doc ds) = otherDoc   ds
+other  (Gen _ ) = passthru
+
+passthru :: LineNo
+         -> Match LBS.ByteString
+         -> Location
+         -> Capture LBS.ByteString
+         -> IO (Maybe LBS.ByteString)
+passthru _ _ _ _ = return Nothing
+
+passthru_g :: LineNo
+           -> Matches LBS.ByteString
+           -> IO (LineEdit LBS.ByteString)
+passthru_g _ _ = return NoEdit
+\end{code}
+
+
+Script to Generate the Whole Web Site
+-------------------------------------
+
+\begin{code}
+gen_all :: IO ()
+gen_all = do
+    -- prepare HTML docs for the (literate) tools
+    pd "re-gen-cabals"
+    pd "re-gen-modules"
+    pd "re-include"
+    pd "re-nginx-log-processor"
+    pd "re-prep"
+    pd "re-tests"
+    pd "TestKit"
+    pd "RE/Capture"
+    pd "RE/Edit"
+    pd "RE/IsRegex"
+    pd "RE/Options"
+    pd "RE/Replace"
+    pd "RE/TestBench"
+    pd "RE/Tools/Grep"
+    pd "RE/Tools/Lex"
+    pd "RE/Tools/Sed"
+    pd "RE/Internal/NamedCaptures"
+    -- render the tutorial in HTML
+    dm <- docMode
+    loop dm "examples/re-tutorial-master.lhs" "tmp/re-tutorial.lhs"
+    createDirectoryIfMissing False "tmp"
+    pandoc_lhs'
+      "re-tutorial.lhs"
+      "examples/re-tutorial.lhs"
+      "tmp/re-tutorial.lhs"
+      "docs/re-tutorial.html"
+    -- generate the tutorial-based tests
+    gm <- genMode
+    loop gm "examples/re-tutorial-master.lhs" "examples/re-tutorial.lhs"
+    putStrLn ">> examples/re-tutorial.lhs"
+    pages
+  where
+    pd fnm = case (mtch !$$? [cp|fdr|],mtch !$$? [cp|mnm|]) of
+        (Nothing ,Just mnm) -> pandoc_lhs ("Text.RE."          <>mnm) ("Text/"    <>fnm<>".lhs") ("docs/"<>mnm<>".html")
+        (Just fdr,Just mnm) -> pandoc_lhs ("Text.RE."<>fdr<>"."<>mnm) ("Text/"    <>fnm<>".lhs") ("docs/"<>mnm<>".html")
+        _                   -> pandoc_lhs ("examples/"<>fnm<>".lhs" ) ("examples/"<>fnm<>".lhs") ("docs/"<>fnm<>".html")
+      where
+        mtch = fnm TT.?=~ [re|^RE/(${fdr}(Tools|Internal)/)?${mnm}(@{%id})|]
+\end{code}
+
+
+Generating the Tutorial
+-----------------------
+
+\begin{code}
+includeDoc :: LineNo
+           -> Match LBS.ByteString
+           -> Location
+           -> Capture LBS.ByteString
+           -> IO (Maybe LBS.ByteString)
+includeDoc _ mtch _ _ = fmap Just $
+    extract fp =<< compileRegex () re_s
+  where
+    fp    = prs_s $ captureText [cp|file|] mtch
+    re_s  = prs_s $ captureText [cp|rex|]  mtch
+
+    prs_s = maybe (error "includeDoc") T.unpack . parseString
+\end{code}
+
+\begin{code}
+mainDoc :: LineNo
+        -> Matches LBS.ByteString
+        -> IO (LineEdit LBS.ByteString)
+mainDoc _ _ = return Delete
+\end{code}
+
+\begin{code}
+beginDoc :: DocState
+         -> LineNo
+         -> Matches LBS.ByteString
+         -> IO (LineEdit LBS.ByteString)
+beginDoc ds _ _ = writeIORef ds Beginning >> return Delete
+\end{code}
+
+\begin{code}
+evalmeDoc, endDoc, otherDoc :: DocState
+                            -> LineNo
+                            -> Match LBS.ByteString
+                            -> Location
+                            -> Capture LBS.ByteString
+                            -> IO (Maybe LBS.ByteString)
+
+evalmeDoc ds lno _ _ _ = do
+  dm <- readIORef ds
+  M.when (dm/=Beginning) $
+    bad_state "evalme" lno dm
+  writeIORef ds InsideRepl
+  return $ Just $ "<div class=\"replcodeblock\">\n"<>begin_code
+
+endDoc    ds lno _ _ _ = do
+  dm <- readIORef ds
+  case dm of
+    Outside    -> bad_state "end" lno dm
+    Beginning  -> return $ Just $ begin_code <> "\n" <> end_code
+    InsideRepl -> return $ Just $ end_code   <> "\n</div>"
+    InsideProg -> return   Nothing
+
+otherDoc  ds _ mtch _ _ = do
+  dm <- readIORef ds
+  case dm of
+    Beginning -> do
+      writeIORef ds InsideProg
+      return $ Just $ begin_code <> "\n" <> matchSource mtch
+    _ -> return Nothing
+
+bad_state :: String -> LineNo -> DocMode -> IO a
+bad_state lab lno dm = error $
+  printf "Bad document syntax: %s: %d: %s" lab (getLineNo lno) $ show dm
+\end{code}
+
+
+Generating the Tests
+--------------------
+
+\begin{code}
+evalmeGen :: GenState
+          -> LineNo
+          -> Match LBS.ByteString
+          -> Location
+          -> Capture LBS.ByteString
+          -> IO (Maybe LBS.ByteString)
+evalmeGen gs _ mtch0 _ _ = Just <$>
+    replaceCapturesM replace_ ALL f mtch0
+  where
+    f mtch loc cap = case _loc_capture loc of
+      2 -> do
+          modifyIORef gs (ide:)
+          return $ Just $ LBS.pack $ show ide
+        where
+          ide = LBS.unpack $ captureText [cp|fn|] mtch
+      _ -> return $ Just $ capturedText cap
+\end{code}
+
+How are we doing?
+
+\begin{code}
+mainGen :: GenState
+        -> LineNo
+        -> Matches LBS.ByteString
+        -> IO (LineEdit LBS.ByteString)
+mainGen gs _ mtchs = case allMatches mtchs of
+  [mtch]  ->
+    case captureText [cp|arg|] $ mtch of
+      "top"    -> return $ ReplaceWith $ LBS.unlines $
+          [ begin_code
+          , "module Main(main) where"
+          , end_code
+          , ""
+          , "*********************************************************"
+          , "*"
+          , "* WARNING: this is generated from pp-tutorial-master.lhs "
+          , "*"
+          , "*********************************************************"
+          ]
+      "bottom" -> do
+        fns <- readIORef gs
+        return $ ReplaceWith $ LBS.unlines $
+          [ begin_code
+          , "main :: IO ()"
+          , "main = runTests"
+          ] ++ mk_list fns ++
+          [ end_code
+          ]
+      _ -> error "mainGen (b)"
+  _ -> error "mainGen (a)"
+\end{code}
+
+We cannot place these strings inline without confusing pandoc so we
+use these definitions instead.
+
+\begin{code}
+begin_code, end_code :: LBS.ByteString
+begin_code = "\\"<>"begin{code}"
+end_code   = "\\"<>"end{code}"
+\end{code}
+
+
+
+\begin{code}
+mk_list :: [String] -> [LBS.ByteString]
+mk_list []          = ["[]"]
+mk_list (ide0:ides) = f "[" ide0 $ foldr (f ",") ["  ]"] ides
+  where
+    f pfx ide t = ("  "<>pfx<>" "<>LBS.pack ide) : t
+\end{code}
+
+
+Extracting a Literate Fragment from a Haskell Program Text
+----------------------------------------------------------
+
+\begin{code}
+extract :: FilePath -> RE -> IO LBS.ByteString
+extract fp rex = extr . LBS.lines <$> LBS.readFile fp
+  where
+    extr lns =
+      case parse $ scan rex lns of
+        Nothing      -> oops
+        Just (lno,n) -> LBS.unlines $ (hdr :) $ (take n $ drop i lns) ++ [ftr]
+          where
+            i = getZeroBasedLineNo lno
+
+    oops = error $ concat
+      [ "failed to locate fragment matching "
+      , show $ reSource rex
+      , " in file "
+      , show fp
+      ]
+
+    hdr  = "<div class='includedcodeblock'>"
+    ftr  = "</div>"
+\end{code}
+
+\begin{code}
+parse :: [Token] -> Maybe (LineNo,Int)
+parse []       = Nothing
+parse (tk:tks) = case (tk,tks) of
+  (Bra b_ln,Hit:Ket k_ln:_) -> Just (b_ln,count_lines_incl b_ln k_ln)
+  _                         -> parse tks
+\end{code}
+
+\begin{code}
+count_lines_incl :: LineNo -> LineNo -> Int
+count_lines_incl b_ln k_ln =
+  getZeroBasedLineNo k_ln + 1 - getZeroBasedLineNo b_ln
+\end{code}
+
+\begin{code}
+data Token = Bra LineNo | Hit | Ket LineNo   deriving (Show)
+\end{code}
+
+\begin{code}
+scan :: RE -> [LBS.ByteString] -> [Token]
+scan rex = grepScript
+    [ (,) [re|\\begin\{code\}|] $ \i -> chk $ Bra i
+    , (,) rex                   $ \_ -> chk   Hit
+    , (,) [re|\\end\{code\}|]   $ \i -> chk $ Ket i
+    ]
+  where
+    chk x mtchs = case anyMatches mtchs of
+      True  -> Just x
+      False -> Nothing
+\end{code}
+
+
+badges
+------
+
+\begin{code}
+badges :: IO ()
+badges = do
+    mapM_ collect
+      [ (,) "license"             "https://img.shields.io/badge/license-BSD3-brightgreen.svg"
+      , (,) "unix-build"          "https://img.shields.io/travis/iconnect/regex.svg?label=Linux%2BmacOS"
+      , (,) "windows-build"       "https://img.shields.io/appveyor/ci/engineerirngirisconnectcouk/regex.svg?label=Windows"
+      , (,) "coverage"            "https://img.shields.io/coveralls/iconnect/regex.svg"
+      , (,) "build-status"        "https://img.shields.io/travis/iconnect/regex.svg?label=Build%20Status"
+      , (,) "maintainers-contact" "https://img.shields.io/badge/email-maintainers%40regex.uk-blue.svg"
+      , (,) "feedback-contact"    "https://img.shields.io/badge/email-feedback%40regex.uk-blue.svg"
+      ]
+  where
+    collect (nm,url) = do
+      putStrLn $ "updating badge: " ++ nm
+      simpleHttp url >>= LBS.writeFile (badge_fn nm)
+
+    badge_fn nm = "docs/badges/"++nm++".svg"
+\end{code}
+
+
+pages
+-----
+
+\begin{code}
+pages :: IO ()
+pages = do
+  prep_page   MM_hackage "lib/md/index.md" "README.markdown"
+  prep_page   MM_github  "lib/md/index.md" "README.md"
+  mapM_ pandoc_page [minBound..maxBound]
+\end{code}
+
+\begin{code}
+data Page
+  = PG_index
+  | PG_about
+  | PG_contact
+  | PG_build_status
+  | PG_installation
+  | PG_tutorial
+  | PG_examples
+  | PG_roadmap
+  | PG_macros
+  | PG_directory
+  | PG_changelog
+  deriving (Bounded,Enum,Eq,Ord,Show)
+
+page_root :: Page -> String
+page_root = map tr . drop 3 . show
+  where
+    tr '_' = '-'
+    tr c   = c
+
+page_master_file, page_docs_file :: Page -> FilePath
+page_master_file pg = "lib/md/" ++ page_root pg ++ ".md"
+page_docs_file   pg = "docs/"   ++ page_root pg ++ ".html"
+
+page_address :: Page -> LBS.ByteString
+page_address = LBS.pack . page_root
+
+page_title :: Page -> LBS.ByteString
+page_title pg = case pg of
+  PG_index        -> "Home"
+  PG_about        -> "About"
+  PG_contact      -> "Contact"
+  PG_build_status -> "Build Status"
+  PG_installation -> "Installation"
+  PG_tutorial     -> "Tutorial"
+  PG_examples     -> "Examples"
+  PG_roadmap      -> "Roadmap"
+  PG_macros       -> "Macro Tables"
+  PG_directory    -> "Directory"
+  PG_changelog    -> "Change Log"
+\end{code}
+
+\begin{code}
+pandoc_page :: Page -> IO ()
+pandoc_page pg = do
+  mt_lbs <- LBS.readFile $ page_master_file pg
+  (hdgs,md_lbs) <- prep_page' MM_pandoc mt_lbs
+  LBS.writeFile "tmp/metadata.markdown"  $ LBS.unlines ["---","title: "<>page_title pg,"---"]
+  LBS.writeFile "tmp/heading.markdown"   $ page_heading pg
+  LBS.writeFile "tmp/page_pre_body.html" $ mk_pre_body_html pg hdgs
+  LBS.writeFile "tmp/page_pst_body.html"   pst_body_html
+  LBS.writeFile "tmp/page.markdown"        md_lbs
+  fmap (const ()) $
+    SH.shelly $ SH.verbosely $
+      SH.run "pandoc"
+        [ "-f", "markdown+grid_tables+autolink_bare_uris"
+        , "-t", "html5"
+        , "-T", "regex"
+        , "-s"
+        , "-H", "lib/favicons.html"
+        , "-B", "tmp/page_pre_body.html"
+        , "-A", "tmp/page_pst_body.html"
+        , "-c", "lib/styles.css"
+        , "-o", T.pack $ page_docs_file pg
+        , "tmp/metadata.markdown"
+        , "tmp/heading.markdown"
+        , "tmp/page.markdown"
+        ]
+
+data Heading =
+  Heading
+    { _hdg_id    :: LBS.ByteString
+    , _hdg_title :: LBS.ByteString
+    }
+  deriving (Show)
+
+data MarkdownMode
+  = MM_github
+  | MM_hackage
+  | MM_pandoc
+  deriving (Eq,Show)
+
+page_heading :: Page -> LBS.ByteString
+page_heading PG_index = ""
+page_heading pg       =
+  "<p class='pagebc'><a href='.' title='Home'>Home</a> &raquo; **"<>page_title pg<>"**</p>\n"
+
+prep_page :: MarkdownMode -> FilePath -> FilePath -> IO ()
+prep_page mmd in_fp out_fp = do
+  lbs      <- LBS.readFile in_fp
+  (_,lbs') <- prep_page' mmd lbs
+  LBS.writeFile out_fp lbs'
+
+prep_page' :: MarkdownMode -> LBS.ByteString -> IO ([Heading],LBS.ByteString)
+prep_page' mmd lbs = do
+    rf_h <- newIORef []
+    rf_t <- newIORef False
+    lbs1 <- sed' (scr rf_h rf_t) =<< include lbs
+    lbs2 <- fromMaybe "" <$> fin_task_list' mmd rf_t
+    hdgs <- reverse <$> readIORef rf_h
+    return (hdgs,lbs1<>lbs2)
+  where
+    scr rf_h rf_t = Select
+      [ (,) [re|^%heading#${ide}(@{%id}) +${ttl}([^ ].*)$|] $ EDIT_fun TOP $ heading       mmd rf_t rf_h
+      , (,) [re|^- \[ \] +${itm}(.*)$|]                     $ EDIT_fun TOP $ task_list     mmd rf_t False
+      , (,) [re|^- \[[Xx]\] +${itm}(.*)$|]                  $ EDIT_fun TOP $ task_list     mmd rf_t True
+      , (,) [re|^.*$|]                                      $ EDIT_fun TOP $ fin_task_list mmd rf_t
+      ]
+
+heading :: MarkdownMode
+        -> IORef Bool
+        -> IORef [Heading]
+        -> LineNo
+        -> Match LBS.ByteString
+        -> Location
+        -> Capture LBS.ByteString
+        -> IO (Maybe LBS.ByteString)
+heading mmd rf_t rf_h _ mtch _ _ = do
+    lbs <- fromMaybe "" <$> fin_task_list' mmd rf_t
+    modifyIORef rf_h (Heading ide ttl:)
+    return $ Just $ lbs<>h2
+  where
+    h2 = case mmd of
+      MM_github  -> "## "<>ttl
+      MM_hackage -> "## "<>ttl
+      MM_pandoc  -> "<h2 id='"<>ide<>"'>"<>ttl<>"</h2>"
+
+    ide = mtch !$$ [cp|ide|]
+    ttl = mtch !$$ [cp|ttl|]
+
+mk_pre_body_html :: Page -> [Heading] -> LBS.ByteString
+mk_pre_body_html pg hdgs = hdr <> LBS.concat (map nav [minBound..maxBound]) <> ftr
+  where
+    hdr :: LBS.ByteString
+    hdr = [here|    <div id="container">
+    <div id="sidebar">
+      <div id="corner">
+        |] <> branding <> [here|
+      </div>
+      <div class="widget" id="pages">
+        <ul class="page-nav">
+|]
+
+    nav dst_pg = LBS.unlines $
+      nav_li "          " pg_cls pg_adr pg_ttl :
+        [ nav_li "            " ["secnav"] ("#"<>_hdg_id) _hdg_title
+          | Heading{..} <- hdgs
+          , is_moi
+          ]
+      where
+        pg_cls = ["pagenav",if is_moi then "moi" else "toi"]
+        pg_adr = page_address dst_pg
+        pg_ttl = page_title   dst_pg
+        is_moi = pg == dst_pg
+
+    nav_li pfx cls dst title = LBS.concat
+      [ pfx
+      , "<li class='"
+      , LBS.unwords cls
+      , "'><a href='"
+      , dst
+      , "'>"
+      , title
+      , "</a></li>"
+      ]
+
+    ftr = [here|          </ul>
+      </div>
+      <div class="supplementary widget" id="github">
+        <a href="https://github.com/iconnect/regex"><img src="images/code.svg" alt="github code" /> Code</a>
+      </div>
+      <div class="supplementary widget" id="github-issues">
+        <a href="https://github.com/iconnect/regex/issues"><img src="images/issue-opened.svg" alt="github code" /> Issues</a>
+      </div>
+      <div class="widget-divider">&nbsp;</div>
+      <div class="supplementary widget" id="build-status">
+        <a href="https://hackage.haskell.org/package/regex">
+          <img src="badges/hackage.svg" alt="hackage version" />
+        </a>
+      </div>
+      <div class="supplementary widget" id="build-status">
+        <a href="build-status">
+          <img src="badges/build-status.svg" alt="build status" />
+        </a>
+      </div>
+      <div class="supplementary widget" id="maintainers-contact">
+        <a href="mailto:maintainers@regex.uk">
+          <img src="badges/maintainers-contact.svg" alt="build status" />
+        </a>
+      </div>
+      <div class="supplementary widget" id="feedback-contact">
+        <a href="mailto:feedback@regex.uk">
+          <img src="badges/feedback-contact.svg" alt="build status" />
+        </a>
+      </div>
+      <div class="supplementary widget twitter">
+        <iframe style="width:162px; height:20px;" src="https://platform.twitter.com/widgets/follow_button.html?screen_name=hregex&amp;show_count=false">
+        </iframe>
+      </div>
+    </div>
+    <div id="content">
+|]
+
+pst_body_html :: LBS.ByteString
+pst_body_html = [here|      </div>
+    </div>
+|]
+\end{code}
+
+
+Task Lists
+----------
+
+\begin{code}
+-- | replacement function to convert GFM task list line into HTML if we
+-- aren't writing GFM (i.e.,  generating markdown for GitHub)
+task_list :: MarkdownMode               -- ^ what flavour of md are we generating
+          -> IORef Bool                 -- ^ will contain True iff we have already entered a task list
+          -> Bool                       -- ^ true if this is a checjed line
+          -> LineNo                     -- ^ line no of the replacement redex (unused)
+          -> Match LBS.ByteString       -- ^ the matched task-list line
+          -> Location                   -- ^ which match and capure (unused)
+          -> Capture LBS.ByteString     -- ^ the capture weare replacing (unsuded)
+          -> IO (Maybe LBS.ByteString)  -- ^ the replacement text, or Nothing to indicate no change to this line
+task_list mmd rf chk _ mtch _ _ =
+  case mmd of
+    MM_github  -> return Nothing
+    MM_hackage -> return $ Just $ "&nbsp;&nbsp;&nbsp;&nbsp;"<>cb<>"&nbsp;&nbsp;"<>itm<>"\n"
+    MM_pandoc  -> do
+      in_tl <- readIORef rf
+      writeIORef rf True
+      return $ tl_line in_tl chk
+  where
+    tl_line in_tl enbl = Just $ LBS.concat
+      [ if in_tl then "" else "<ul class='contains-task-list'>\n"
+      , "  <li class='task-list-item'>"
+      , "<input type='checkbox' class='task-list-item-checkbox'"
+      , if enbl then " checked=''" else ""
+      , " disabled=''/>"
+      , itm
+      , "</li>"
+      ]
+
+    cb  = if chk then "&#x2612;" else "&#x2610;"
+
+    itm = mtch !$$ [cp|itm|]
+
+-- | replacement function used for 'other' lines -- terminate any task
+-- list that was being generated
+fin_task_list :: MarkdownMode               -- ^ what flavour of md are we generating
+              -> IORef Bool                 -- ^ will contain True iff we have already entered a task list
+              -> LineNo                     -- ^ line no of the replacement redex (unused)
+              -> Match LBS.ByteString       -- ^ the matched task-list line
+              -> Location                   -- ^ which match and capure (unused)
+              -> Capture LBS.ByteString     -- ^ the capture weare replacing (unsuded)
+              -> IO (Maybe LBS.ByteString)  -- ^ the replacement text, or Nothing to indicate no change to this line
+fin_task_list mmd rf_t _ mtch _ _ =
+  fmap (<>matchSource mtch) <$> fin_task_list' mmd rf_t
+
+-- | close any task list being processed, returning the closing text
+-- as necessary
+fin_task_list' :: MarkdownMode              -- ^ what flavour of md are we generating
+               -> IORef Bool                -- ^ will contain True iff we have already entered a task list
+               -> IO (Maybe LBS.ByteString) -- ^ task-list closure HTML, if task-list HTML needs closing
+fin_task_list' mmd rf = do
+  in_tl <- readIORef rf
+  writeIORef rf False
+  case mmd==MM_github || not in_tl of
+    True  -> return Nothing
+    False -> return $ Just $ "</ul>\n"
+\end{code}
+
+
+Literate Haskell Pages
+----------------------
+
+\begin{code}
+pandoc_lhs :: T.Text -> T.Text -> T.Text -> IO ()
+pandoc_lhs title in_file = pandoc_lhs' title in_file in_file
+
+pandoc_lhs' :: T.Text -> T.Text -> T.Text -> T.Text -> IO ()
+pandoc_lhs' title repo_path in_file out_file = do
+  LBS.writeFile "tmp/metadata.markdown"  $
+                    LBS.unlines
+                      [ "---"
+                      , "title: "<>LBS.fromStrict (TE.encodeUtf8 title)
+                      ,"---"
+                      ]
+  LBS.writeFile "tmp/bc.html" bc
+  LBS.writeFile "tmp/ft.html" ft
+  fmap (const ()) $
+    SH.shelly $ SH.verbosely $
+      SH.run "pandoc"
+        [ "-f", "markdown+lhs+grid_tables"
+        , "-t", "html5"
+        , "-T", "regex"
+        , "-s"
+        , "-H", "lib/favicons.html"
+        , "-B", "tmp/bc.html"
+        , "-A", "tmp/ft.html"
+        , "-c", "lib/lhs-styles.css"
+        , "-c", "lib/bs.css"
+        , "-o", out_file
+        , "tmp/metadata.markdown"
+        , in_file
+        ]
+  where
+    bc = LBS.unlines
+    --  [ "<div class='brandingdiv'>"
+    --  , "  " <> branding
+    --  , "</div>"
+      [ "<div class='bcdiv'>"
+      , "  <ol class='breadcrumb'>"
+      , "    <li>"<>branding<>"</li>"
+      , "    <li><a title='source file' href='" <>
+              repo_url <> "'>" <> (LBS.pack $ T.unpack title) <> "</a></li>"
+      , "</ol>"
+      , "</div>"
+      , "<div class='litcontent'>"
+      ]
+
+    ft = LBS.concat
+      [ "</div>"
+      ]
+
+    repo_url = LBS.concat
+      [ "https://github.com/iconnect/regex/blob/master/"
+      , LBS.pack $ T.unpack repo_path
+      ]
+\end{code}
+
+
+simple include processor
+------------------------
+
+\begin{code}
+include :: LBS.ByteString -> IO LBS.ByteString
+include = sed' $ Select
+    [ (,) [re|^%include ${file}(@{%string})$|] $ EDIT_fun TOP   incl
+    , (,) [re|^.*$|]                           $ EDIT_fun TOP $ \_ _ _ _->return Nothing
+    ]
+  where
+    incl _ mtch _ _ = Just <$> LBS.readFile (prs_s $ mtch !$$ [cp|file|])
+    prs_s           = maybe (error "include") T.unpack . parseString
+\end{code}
+
+
+branding
+--------
+
+\begin{code}
+branding :: LBS.ByteString
+branding = [here|<a href="." style="Arial, 'Helvetica Neue', Helvetica, sans-serif;" id="branding">[<span style='color:red;'>re</span>|${<span style='color:red;'>gex</span>}(.*)|<span></span>]</a>|]
+\end{code}
+
+
+testing
+-------
+
+\begin{code}
+test :: IO ()
+test = do
+  dm <- docMode
+  test_pp "pp-doc" (loop dm) "data/pp-test.lhs" "data/pp-result-doc.lhs"
+  gm <- genMode
+  test_pp "pp-gen" (loop gm) "data/pp-test.lhs" "data/pp-result-gen.lhs"
+  putStrLn "tests passed"
+\end{code}
diff --git a/examples/re-tests.lhs b/examples/re-tests.lhs
--- a/examples/re-tests.lhs
+++ b/examples/re-tests.lhs
@@ -1,17 +1,21 @@
 \begin{code}
+{-# LANGUAGE NoImplicitPrelude          #-}
 {-# LANGUAGE RecordWildCards            #-}
 {-# LANGUAGE OverloadedStrings          #-}
 {-# LANGUAGE QuasiQuotes                #-}
+{-# LANGUAGE MultiParamTypeClasses      #-}
+{-# LANGUAGE FlexibleInstances          #-}
 {-# LANGUAGE TemplateHaskell            #-}
+{-# OPTIONS_GHC -fno-warn-orphans       #-}
 
 module Main (main) where
 
-import           Control.Applicative
 import           Control.Exception
 import           Data.Array
 import qualified Data.ByteString.Char8          as B
 import qualified Data.ByteString.Lazy.Char8     as LBS
 import qualified Data.Foldable                  as F
+import qualified Data.HashMap.Strict            as HM
 import           Data.Maybe
 import           Data.Monoid
 import qualified Data.Sequence                  as S
@@ -19,9 +23,14 @@
 import qualified Data.Text                      as T
 import qualified Data.Text.Lazy                 as LT
 import           Language.Haskell.TH.Quote
+import           Prelude.Compat
+import           Test.SmallCheck.Series
 import           Test.Tasty
 import           Test.Tasty.HUnit
+import           Test.Tasty.SmallCheck          as SC
+import           Text.Heredoc
 import qualified Text.Regex.PCRE                as PCRE_
+
 import qualified Text.Regex.TDFA                as TDFA_
 import           Text.RE
 import           Text.RE.Internal.NamedCaptures
@@ -65,11 +74,11 @@
   where
     tc rty m_env =
       testCase (show rty) $ do
-        dumpMacroTable "prelude" rty m_env
+        dumpMacroTable "macros" rty m_env
         assertBool "testMacroEnv" =<< testMacroEnv "prelude" rty m_env
 
-str, str' :: String
-str       = "a bbbb aa b"
+str_, str' :: String
+str_      = "a bbbb aa b"
 str'      = "foo"
 
 regex_, regex_alt :: RE
@@ -158,35 +167,35 @@
 parsing_tests = testGroup "Parsing"
   [ testCase "complete check (matchM/ByteString)" $ do
       r    <- compileRegex () $ reSource regex_
-      assertEqual "Match" (B.pack <$> regex_str_match) $ B.pack str ?=~ r
+      assertEqual "Match" (B.pack <$> regex_str_match) $ B.pack str_ ?=~ r
   , testCase "matched (matchM/Text)" $ do
       r     <- compileRegex () $ reSource regex_
-      assertEqual "matched" True $ matched $ T.pack str ?=~ r
+      assertEqual "matched" True $ matched $ T.pack str_ ?=~ r
   ]
 
 core_tests :: TestTree
 core_tests = testGroup "Match"
   [ testCase "text (=~~Text.Lazy)" $ do
-      txt <- LT.pack str =~~ [re|(a+) (b+)|] :: IO (LT.Text)
+      txt <- LT.pack str_ =~~ [re|(a+) (b+)|] :: IO (LT.Text)
       assertEqual "text" txt "a bbbb"
   , testCase "multi (=~~/String)" $ do
-      let sm = str =~ regex_ :: Match String
+      let sm = str_ =~ regex_ :: Match String
           m  = capture [cp|0|] sm
       assertEqual "captureSource" "a bbbb aa b" $ captureSource m
       assertEqual "capturedText"  "a bbbb"      $ capturedText  m
       assertEqual "capturePrefix" ""            $ capturePrefix m
       assertEqual "captureSuffix" " aa b"       $ captureSuffix m
   , testCase "complete (=~~/ByteString)" $ do
-      mtch <- B.pack str =~~ regex_ :: IO (Match B.ByteString)
+      mtch <- B.pack str_ =~~ regex_ :: IO (Match B.ByteString)
       assertEqual "Match" mtch $ B.pack <$> regex_str_match
   , testCase "complete (all,String)" $ do
-      let mtchs = str =~ regex_     :: Matches String
+      let mtchs = str_ =~ regex_     :: Matches String
       assertEqual "Matches" mtchs regex_str_matches
   , testCase "complete (all,reg_alt)" $ do
-      let mtchs = str =~ regex_alt  :: Matches String
+      let mtchs = str_ =~ regex_alt  :: Matches String
       assertEqual "Matches" mtchs regex_alt_str_matches
   , testCase "complete (=~~,all)" $ do
-      mtchs <- str =~~ regex_       :: IO (Matches String)
+      mtchs <- str_ =~~ regex_       :: IO (Matches String)
       assertEqual "Matches" mtchs regex_str_matches
   , testCase "fail (all)" $ do
       let mtchs = str' =~ regex_    :: Matches String
@@ -196,27 +205,27 @@
 replace_tests :: TestTree
 replace_tests = testGroup "Replace"
   [ testCase "String/single" $ do
-      let m = str =~ regex_ :: Match String
+      let m = str_ =~ regex_ :: Match String
           r = replaceCaptures' ALL fmt m
       assertEqual "replaceCaptures'" r "(0:0:(0:1:a) (0:2:bbbb)) aa b"
   , testCase "String/alt" $ do
-      let ms = str =~ regex_ :: Matches String
+      let ms = str_ =~ regex_ :: Matches String
           r  = replaceAllCaptures' ALL fmt ms
       chk r
   , testCase "String" $ do
-      let ms = str =~ regex_ :: Matches String
+      let ms = str_ =~ regex_ :: Matches String
           r  = replaceAllCaptures' ALL fmt ms
       chk r
   , testCase "ByteString" $ do
-      let ms = B.pack str =~ regex_ :: Matches B.ByteString
+      let ms = B.pack str_ =~ regex_ :: Matches B.ByteString
           r  = replaceAllCaptures' ALL fmt ms
       chk r
   , testCase "LBS.ByteString" $ do
-      let ms = LBS.pack str =~ regex_ :: Matches LBS.ByteString
+      let ms = LBS.pack str_ =~ regex_ :: Matches LBS.ByteString
           r  = replaceAllCaptures' ALL fmt ms
       chk r
   , testCase "Seq Char" $ do
-      let ms = S.fromList str =~ regex_ :: Matches (S.Seq Char)
+      let ms = S.fromList str_ =~ regex_ :: Matches (S.Seq Char)
           f  = \_ (Location i j) Capture{..} -> Just $ S.fromList $
                   "(" <> show i <> ":" <> show_co j <> ":" <>
                     F.toList capturedText <> ")"
@@ -224,11 +233,11 @@
       assertEqual "replaceAllCaptures'" r $
         S.fromList "(0:0:(0:1:a) (0:2:bbbb)) (1:0:(1:1:aa) (1:2:b))"
   , testCase "Text" $ do
-      let ms = T.pack str =~ regex_ :: Matches T.Text
+      let ms = T.pack str_ =~ regex_ :: Matches T.Text
           r  = replaceAllCaptures' ALL fmt ms
       chk r
   , testCase "LT.Text" $ do
-      let ms = LT.pack str =~ regex_ :: Matches LT.Text
+      let ms = LT.pack str_ =~ regex_ :: Matches LT.Text
           r  = replaceAllCaptures' ALL fmt ms
       chk r
   ]
@@ -438,4 +447,76 @@
 
 tdfa_prelude_macros :: [PreludeMacro]
 tdfa_prelude_macros = [minBound..maxBound]
+\end{code}
+
+
+Testing : FormatToken/Scan Properties
+-------------------------------------
+
+\begin{code}
+namedCapturesTestTree :: TestTree
+namedCapturesTestTree = localOption (SmallCheckDepth 4) $
+  testGroup "NamedCaptures"
+    [ formatScanTestTree
+    , analyseTokensTestTree
+    ]
+\end{code}
+
+\begin{code}
+instance Monad m => Serial m Token
+\end{code}
+
+
+Testing : FormatToken/Scan Properties
+-------------------------------------
+
+\begin{code}
+formatScanTestTree :: TestTree
+formatScanTestTree =
+  testGroup "FormatToken/Scan Properties"
+    [ localOption (SmallCheckDepth 4) $
+        SC.testProperty "formatTokens == formatTokens0" $
+          \tks -> formatTokens tks == formatTokens0 tks
+    , localOption (SmallCheckDepth 4) $
+        SC.testProperty "scan . formatTokens' idFormatTokenOptions == id" $
+          \tks -> all validToken tks ==>
+                    scan (formatTokens' idFormatTokenOptions tks) == tks
+    ]
+\end{code}
+
+
+Testing : Analysing [Token] Unit Tests
+--------------------------------------
+
+\begin{code}
+analyseTokensTestTree :: TestTree
+analyseTokensTestTree =
+  testGroup "Analysing [Token] Unit Tests"
+    [ tc [here|foobar|]                                       []
+    , tc [here||]                                             []
+    , tc [here|$([0-9]{4})|]                                  []
+    , tc [here|${x}()|]                                       [(1,"x")]
+    , tc [here|${}()|]                                        []
+    , tc [here|${}()${foo}()|]                                [(2,"foo")]
+    , tc [here|${x}(${y()})|]                                 [(1,"x")]
+    , tc [here|${x}(${y}())|]                                 [(1,"x"),(2,"y")]
+    , tc [here|${a}(${b{}())|]                                [(1,"a")]
+    , tc [here|${y}([0-9]{4})-${m}([0-9]{2})-${d}([0-9]{2})|] [(1,"y"),(2,"m"),(3,"d")]
+    , tc [here|@$(@|\{${name}([^{}]+)\})|]                    [(2,"name")]
+    , tc [here|${y}[0-9]{4}|]                                 []
+    , tc [here|${}([0-9]{4})|]                                []
+    ]
+  where
+    tc s al =
+      testCase s $ assertEqual "CaptureNames"
+        (xnc s)
+        (HM.fromList
+          [ (CaptureName $ T.pack n,CaptureOrdinal i)
+              | (i,n)<-al
+              ]
+        )
+
+    xnc = either oops fst . extractNamedCaptures
+      where
+        oops = error "analyseTokensTestTree: unexpected parse failure"
 \end{code}
diff --git a/examples/re-tutorial.lhs b/examples/re-tutorial.lhs
--- a/examples/re-tutorial.lhs
+++ b/examples/re-tutorial.lhs
@@ -29,7 +29,7 @@
 should be enabled.
 
 \begin{code}
-{-# LANGUAGE QuasiQuotes                      #-}
+{-# LANGUAGE QuasiQuotes #-}
 \end{code}
 
 Use this command to configure ghci accordingly (not necessary if you
@@ -38,21 +38,22 @@
 :seti -XQuasiQuotes
 ```
 
-[Overloaded string
-literals](https://www.schoolofhaskell.com/school/to-infinity-and-beyond/pick-of-the-week/guide-to-ghc-extensions/basic-syntax-extensions#overloadedstrings)
-are usually enabled in modern Haskell and we do so here.
-\begin{code}
-{-# LANGUAGE OverloadedStrings                #-}
-\end{code}
-
 Because we are mimicking the REPL in this tutorial we will leave off the type
 signatures on the example calculations and disable the compiler
 warnings about missing type signatures.
 \begin{code}
-{-# OPTIONS_GHC -fno-warn-missing-signatures  #-}
+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
 \end{code}
 
+This pragma is a just technical pragma, combined with the
+`Prelude.Compat` import below used to avoid certain warnings while
+comiling against multiple versions of the compiler. It can be safely
+ignored.
+\begin{code}
+{-# LANGUAGE NoImplicitPrelude #-}
+\end{code}
 
+
 Loading Up: The Imports
 -----------------------
 
@@ -107,9 +108,11 @@
 import           Text.Printf
 \end{code}
 
-And finally we will import a small specail toolkit will be used to help
+And finally we a special edition of the prelude (see the commentary for
+the pragma section above) and a small specail toolkit will be used to help
 manage the example calculations.
 \begin{code}
+import           Prelude.Compat
 import           TestKit
 \end{code}
 This allows simple calculations to be defined stylistically
@@ -613,7 +616,7 @@
     that matches one of the REs, substituting the text returned from the action
     in the output stream. (Used in the [include](re-include.html),
     [gen-modules](re-gen-modules.html),
-    [log-processor](re-nginx-log-processor.html) and [tutorial-pp](re-pp)
+    [log-processor](re-nginx-log-processor.html) and [tutorial-pp](re-prep)
     examples.)
 
 
@@ -691,9 +694,9 @@
 package's website uses the following 'gen_all' diriver which uses
 REs to analyse file paths.
 
-%include "examples/re-pp.lhs" "^gen_all ::"
+%include "examples/re-prep.lhs" "^gen_all ::"
 
-See [examples/re-pp.lhs](re-pp.html)
+See [examples/re-prep.lhs](re-prep.html)
 
 
 Example: parsing RE macros
@@ -751,7 +754,7 @@
     Just $ replaceAllCaptures' TOP phi $
       tpl *=~ [re|\$${arg}(\$|[0-9]+|\{${name}([^{}]+)\})|]
   where
-    phi t_mtch _ _ = case captureMaybe [cp|name|] t_mtch of
+    phi t_mtch _ _ = case t_mtch !$? [cp|name|] of
       Just cap -> this $ CID_name $ CaptureName txt
         where
           txt = T.pack $ capturedText cap
@@ -761,7 +764,7 @@
       where
         t = capturedText $ capture [cp|arg|] t_mtch
 
-        this cid = capturedText <$> captureMaybe cid mtch
+        this cid = capturedText <$> mtch !$? cid
 
 my_replace :: RE -> Template-> String -> String
 my_replace rex tpl src = replaceAllCaptures' TOP (parse_tpl_ tpl) $ src *=~ rex
@@ -813,7 +816,7 @@
 
 The preprocessor that converts this literate Haskell program into a web
 page and a test suite that makes plenty of use of regex is in
-[examples/re-pp.lhs](re-pp.html).
+[examples/re-prep.lhs](re-prep.html).
 
 
 Example: gen-modules
diff --git a/regex.cabal b/regex.cabal
--- a/regex.cabal
+++ b/regex.cabal
@@ -1,6 +1,6 @@
 Name:                   regex
-Version:                0.0.0.2
-Synopsis:               A Regular Expression Toolkit for regex-base
+Version:                0.1.0.0
+Synopsis:               Toolkit for regex-base
 Description:            A Regular Expression Toolkit for regex-base with
                         Compile-time checking of RE syntax, data types for
                         matches and captures, a text replacement toolkit,
@@ -18,23 +18,25 @@
 Stability:              rfc
 bug-reports:            https://github.com/iconnect/regex/issues
 
-extra-source-files:
-    README.md
+Extra-Source-Files:
+    README.markdown
     changelog
 
-Cabal-version:          >= 1.16
+Cabal-Version:          >= 1.16
 
-Source-repository head
+Source-Repository head
     type:               git
     location:           https://github.com/iconnect/regex.git
 
 Source-Repository this
     Type:               git
     Location:           https://github.com/iconnect/regex.git
-    Tag:                0.0.0.2
+    Tag:                0.1.0.0
 
+
 Library
-    Exposed-modules:
+    Hs-Source-Dirs:     .
+    Exposed-Modules:
       Text.RE
       Text.RE.Capture
       Text.RE.CaptureID
@@ -66,326 +68,491 @@
       Text.RE.Tools.Lex
       Text.RE.Tools.Sed
 
-    Other-modules:
+    Other-Modules:
       Text.RE.Internal.AddCaptureNames
 
+    Default-Language:   Haskell2010
+    GHC-Options:
+      -Wall
+      -fwarn-tabs
+
     Build-depends:
-      array                   >= 0.4            ,
-      bytestring              >= 0.10.2.0       ,
-      base                    >= 4       && < 5 ,
-      containers              >= 0.4            ,
-      hashable                >= 1.2.3.3        ,
-      heredoc                 >= 0.2.0.0        ,
-      regex-base              >= 0.93.2         ,
-      regex-tdfa              >= 1.2.1          ,
-      regex-tdfa-text         >= 1.0.0.3        ,
-      regex-pcre-builtin      >= 0.94.4.8.8.35  ,
-      smallcheck              >= 1.1.1          ,
-      tasty                   >= 0.10.1.2       ,
-      tasty-hunit             >= 0.9.2          ,
-      tasty-smallcheck        >= 0.8.0.1        ,
-      template-haskell        >= 2.7            ,
-      transformers            >= 0.2.2          ,
-      text                    >= 1.2.1.3        ,
-      time                    >= 1.5.0.1        ,
-      unordered-containers    >= 0.2.5.1
+        array                >= 0.4
+      , base                 >= 4 && < 5
+      , base-compat          >= 0.6.0
+      , bytestring           >= 0.10.2.0
+      , containers           >= 0.4
+      , hashable             >= 1.2.3.3
+      , heredoc              >= 0.2.0.0
+      , regex-base           >= 0.93.2
+      , regex-pcre-builtin   >= 0.94.4.8.8.35
+      , regex-tdfa           >= 1.2.0
+      , regex-tdfa-text      >= 1.0.0.3
+      , template-haskell     >= 2.7
+      , text                 >= 1.2.0.6
+      , time                 >= 1.4.2
+      , time-locale-compat   >= 0.1.0.1
+      , transformers         >= 0.2.2
+      , unordered-containers >= 0.2.5.1
 
+
+Executable re-gen-cabals
+    Hs-Source-Dirs:     examples
+
+    Main-Is:            re-gen-cabals.lhs
+
+    Other-Modules:
+      TestKit
+
     Default-Language:   Haskell2010
     GHC-Options:
-        -Wall
-        -fwarn-tabs
+      -Wall
+      -fwarn-tabs
 
+    Build-depends:
+        regex                
+      , array                >= 0.4
+      , base                 >= 4 && < 5
+      , base-compat          >= 0.6.0
+      , bytestring           >= 0.10.2.0
+      , containers           >= 0.4
+      , directory            >= 1.2.1.0
+      , regex-base           >= 0.93.2
+      , regex-tdfa           >= 1.2.0
+      , shelly               >= 1.6.1.2
+      , text                 >= 1.2.0.6
 
+
+Test-Suite re-gen-cabals-test
+    type:               exitcode-stdio-1.0
+    Hs-Source-Dirs:     examples
+
+    Main-Is:            re-gen-cabals.lhs
+
+    Other-Modules:
+      TestKit
+
+    Default-Language:   Haskell2010
+    GHC-Options:
+      -Wall
+      -fwarn-tabs
+
+    Build-depends:
+        regex                
+      , array                >= 0.4
+      , base                 >= 4 && < 5
+      , base-compat          >= 0.6.0
+      , bytestring           >= 0.10.2.0
+      , containers           >= 0.4
+      , directory            >= 1.2.1.0
+      , regex-base           >= 0.93.2
+      , regex-tdfa           >= 1.2.0
+      , shelly               >= 1.6.1.2
+      , text                 >= 1.2.0.6
+
+
+
 Executable re-gen-modules
     Hs-Source-Dirs:     examples
 
-    Main-is:            re-gen-modules.lhs
+    Main-Is:            re-gen-modules.lhs
 
     Default-Language:   Haskell2010
     GHC-Options:
-        -Wall
-        -fwarn-tabs
+      -Wall
+      -fwarn-tabs
 
     Build-depends:
-      regex                                     ,
-      array                   >= 0.4            ,
-      bytestring              >= 0.10.2.0       ,
-      base                    >= 4              ,
-      directory               >= 1.2.1.0        ,
-      regex-base              >= 0.93.2         ,
-      regex-tdfa              >= 1.2.0          ,
-      shelly                  >= 1.6.1.2        ,
-      text                    >= 1.2.1.3
+        regex                
+      , array                >= 0.4
+      , base                 >= 4 && < 5
+      , base-compat          >= 0.6.0
+      , bytestring           >= 0.10.2.0
+      , directory            >= 1.2.1.0
+      , regex-base           >= 0.93.2
+      , regex-tdfa           >= 1.2.0
+      , shelly               >= 1.6.1.2
+      , text                 >= 1.2.0.6
 
 
 Test-Suite re-gen-modules-test
     type:               exitcode-stdio-1.0
     Hs-Source-Dirs:     examples
 
-    Main-is:            re-gen-modules.lhs
+    Main-Is:            re-gen-modules.lhs
 
     Default-Language:   Haskell2010
     GHC-Options:
-        -Wall
-        -fwarn-tabs
+      -Wall
+      -fwarn-tabs
 
     Build-depends:
-      regex                                     ,
-      array                   >= 0.4            ,
-      bytestring              >= 0.10.2.0       ,
-      base                    >= 4       && < 5 ,
-      directory               >= 1.2.1.0        ,
-      regex-base              >= 0.93.2         ,
-      regex-tdfa              >= 1.2.0          ,
-      shelly                  >= 1.6.1.2        ,
-      text                    >= 1.2.1.3
+        regex                
+      , array                >= 0.4
+      , base                 >= 4 && < 5
+      , base-compat          >= 0.6.0
+      , bytestring           >= 0.10.2.0
+      , directory            >= 1.2.1.0
+      , regex-base           >= 0.93.2
+      , regex-tdfa           >= 1.2.0
+      , shelly               >= 1.6.1.2
+      , text                 >= 1.2.0.6
 
 
+
 Executable re-include
     Hs-Source-Dirs:     examples
 
-    Main-is: re-include.lhs
+    Main-Is:            re-include.lhs
 
     Default-Language:   Haskell2010
     GHC-Options:
-        -Wall
-        -fwarn-tabs
+      -Wall
+      -fwarn-tabs
 
-    Other-modules:
+    Other-Modules:
       TestKit
 
     Build-depends:
-      regex                                     ,
-      bytestring              >= 0.10.2.0       ,
-      base                    >= 4       && < 5 ,
-      directory               >= 1.2.1.0        ,
-      shelly                  >= 1.6.1.2        ,
-      text                    >= 1.2.1.3
+        regex                
+      , base                 >= 4 && < 5
+      , base-compat          >= 0.6.0
+      , bytestring           >= 0.10.2.0
+      , directory            >= 1.2.1.0
+      , shelly               >= 1.6.1.2
+      , text                 >= 1.2.0.6
 
 
 Test-Suite re-include-test
     type:               exitcode-stdio-1.0
     Hs-Source-Dirs:     examples
 
-    Main-is: re-include.lhs
+    Main-Is:            re-include.lhs
 
     Default-Language:   Haskell2010
     GHC-Options:
-        -Wall
-        -fwarn-tabs
+      -Wall
+      -fwarn-tabs
 
-    Other-modules:
+    Other-Modules:
       TestKit
 
     Build-depends:
-      regex                                     ,
-      bytestring              >= 0.10.2.0       ,
-      base                    >= 4              ,
-      directory               >= 1.2.1.0        ,
-      shelly                  >= 1.6.1.2        ,
-      text                    >= 1.2.1.3
+        regex                
+      , base                 >= 4 && < 5
+      , base-compat          >= 0.6.0
+      , bytestring           >= 0.10.2.0
+      , directory            >= 1.2.1.0
+      , shelly               >= 1.6.1.2
+      , text                 >= 1.2.0.6
 
 
+
+Executable re-nginx-log-processor
+    Hs-Source-Dirs:     examples
+
+    Main-Is:            re-nginx-log-processor.lhs
+
+    Default-Language:   Haskell2010
+    GHC-Options:
+      -Wall
+      -fwarn-tabs
+
+    Build-depends:
+        regex                
+      , array                >= 0.4
+      , base                 >= 4 && < 5
+      , base-compat          >= 0.6.0
+      , bytestring           >= 0.10.2.0
+      , directory            >= 1.2.1.0
+      , regex-base           >= 0.93.2
+      , regex-tdfa           >= 1.2.0
+      , shelly               >= 1.6.1.2
+      , text                 >= 1.2.0.6
+      , time                 >= 1.4.2
+      , time-locale-compat   >= 0.1.0.1
+      , transformers         >= 0.2.2
+      , unordered-containers >= 0.2.5.1
+
+
 Test-Suite re-nginx-log-processor-test
     type:               exitcode-stdio-1.0
     Hs-Source-Dirs:     examples
 
-    Main-is:            re-nginx-log-processor.lhs
+    Main-Is:            re-nginx-log-processor.lhs
 
     Default-Language:   Haskell2010
     GHC-Options:
-        -Wall
-        -fwarn-tabs
+      -Wall
+      -fwarn-tabs
 
     Build-depends:
-      regex                                     ,
-      array                   >= 0.4            ,
-      bytestring              >= 0.10.2.0       ,
-      base                    >= 4       && < 5 ,
-      directory               >= 1.2.1.0        ,
-      regex-base              >= 0.93.2         ,
-      regex-tdfa              >= 1.2.0          ,
-      shelly                  >= 1.6.1.2        ,
-      text                    >= 1.2.1.3        ,
-      time                    >= 1.5.0.1        ,
-      transformers            >= 0.3.0.0        ,
-      unordered-containers    >= 0.2.5.1
+        regex                
+      , array                >= 0.4
+      , base                 >= 4 && < 5
+      , base-compat          >= 0.6.0
+      , bytestring           >= 0.10.2.0
+      , directory            >= 1.2.1.0
+      , regex-base           >= 0.93.2
+      , regex-tdfa           >= 1.2.0
+      , shelly               >= 1.6.1.2
+      , text                 >= 1.2.0.6
+      , time                 >= 1.4.2
+      , time-locale-compat   >= 0.1.0.1
+      , transformers         >= 0.2.2
+      , unordered-containers >= 0.2.5.1
 
 
-Executable re-nginx-log-processor
+
+Executable re-prep
     Hs-Source-Dirs:     examples
 
-    Main-is:            re-nginx-log-processor.lhs
+    Main-Is:            re-prep.lhs
 
     Default-Language:   Haskell2010
     GHC-Options:
-        -Wall
-        -fwarn-tabs
+      -Wall
+      -fwarn-tabs
 
+    Other-Modules:
+      TestKit
+
     Build-depends:
-      regex                                     ,
-      array                   >= 0.4            ,
-      bytestring              >= 0.10.2.0       ,
-      base                    >= 4       && < 5 ,
-      directory               >= 1.2.1.0        ,
-      regex-base              >= 0.93.2         ,
-      regex-tdfa              >= 1.2.0          ,
-      shelly                  >= 1.6.1.2        ,
-      text                    >= 1.2.1.3        ,
-      time                    >= 1.5.0.1        ,
-      transformers            >= 0.3.0.0        ,
-      unordered-containers    >= 0.2.5.1
+        regex                
+      , base                 >= 4 && < 5
+      , base-compat          >= 0.6.0
+      , bytestring           >= 0.10.2.0
+      , directory            >= 1.2.1.0
+      , heredoc              >= 0.2.0.0
+      , http-conduit         >= 2.1.7.2
+      , shelly               >= 1.6.1.2
+      , text                 >= 1.2.0.6
 
 
-Executable re-pp
+Test-Suite re-prep-test
+    type:               exitcode-stdio-1.0
     Hs-Source-Dirs:     examples
 
-    Main-is: re-pp.lhs
+    Main-Is:            re-prep.lhs
 
     Default-Language:   Haskell2010
     GHC-Options:
-        -Wall
-        -fwarn-tabs
+      -Wall
+      -fwarn-tabs
 
-    Other-modules:
+    Other-Modules:
       TestKit
 
     Build-depends:
-      regex                                     ,
-      bytestring              >= 0.10.2.0       ,
-      base                    >= 4       && < 5 ,
-      directory               >= 1.2.1.0        ,
-      shelly                  >= 1.6.1.2        ,
-      text                    >= 1.2.1.3
+        regex                
+      , base                 >= 4 && < 5
+      , base-compat          >= 0.6.0
+      , bytestring           >= 0.10.2.0
+      , directory            >= 1.2.1.0
+      , heredoc              >= 0.2.0.0
+      , http-conduit         >= 2.1.7.2
+      , shelly               >= 1.6.1.2
+      , text                 >= 1.2.0.6
 
 
-Test-Suite re-pp-test
-    type:               exitcode-stdio-1.0
+
+Executable re-tests
     Hs-Source-Dirs:     examples
 
-    Main-is: re-pp.lhs
+    Main-Is:            re-tests.lhs
 
     Default-Language:   Haskell2010
     GHC-Options:
-        -Wall
-        -fwarn-tabs
+      -Wall
+      -fwarn-tabs
 
-    Other-modules:
+    Other-Modules:
       TestKit
 
     Build-depends:
-      regex                                     ,
-      bytestring              >= 0.10.2.0       ,
-      base                    >= 4       && < 5 ,
-      directory               >= 1.2.1.0        ,
-      shelly                  >= 1.6.1.2        ,
-      text                    >= 1.2.1.3
+        regex                
+      , array                >= 0.4
+      , base                 >= 4 && < 5
+      , base-compat          >= 0.6.0
+      , bytestring           >= 0.10.2.0
+      , containers           >= 0.4
+      , directory            >= 1.2.1.0
+      , heredoc              >= 0.2.0.0
+      , regex-base           >= 0.93.2
+      , regex-pcre-builtin   >= 0.94.4.8.8.35
+      , regex-tdfa           >= 1.2.0
+      , regex-tdfa-text      >= 1.0.0.3
+      , smallcheck           >= 1.1.1
+      , tasty                >= 0.10.1.2
+      , tasty-hunit          >= 0.9.2
+      , tasty-smallcheck     >= 0.8.0.1
+      , template-haskell     >= 2.7
+      , text                 >= 1.2.0.6
+      , unordered-containers >= 0.2.5.1
 
 
-Test-Suite re-tests
+Test-Suite re-tests-test
     type:               exitcode-stdio-1.0
     Hs-Source-Dirs:     examples
 
-    Main-is:            re-tests.lhs
+    Main-Is:            re-tests.lhs
 
     Default-Language:   Haskell2010
     GHC-Options:
-        -Wall
-        -fwarn-tabs
+      -Wall
+      -fwarn-tabs
 
-    Other-modules:
+    Other-Modules:
       TestKit
 
     Build-depends:
-      regex                                     ,
-      array                   >= 0.4            ,
-      bytestring              >= 0.10.2.0       ,
-      base                    >= 4       && < 5 ,
-      containers              >= 0.4            ,
-      directory               >= 1.2.1.0        ,
-      regex-base              >= 0.93.2         ,
-      regex-tdfa              >= 1.2.0          ,
-      regex-tdfa-text         >= 1.0.0.3        ,
-      regex-pcre-builtin      >= 0.94.4.8.8.35  ,
-      tasty                   >= 0.10.1.2       ,
-      tasty-hunit             >= 0.9.2          ,
-      template-haskell        >= 2.7            ,
-      text                    >= 1.2.1.3
+        regex                
+      , array                >= 0.4
+      , base                 >= 4 && < 5
+      , base-compat          >= 0.6.0
+      , bytestring           >= 0.10.2.0
+      , containers           >= 0.4
+      , directory            >= 1.2.1.0
+      , heredoc              >= 0.2.0.0
+      , regex-base           >= 0.93.2
+      , regex-pcre-builtin   >= 0.94.4.8.8.35
+      , regex-tdfa           >= 1.2.0
+      , regex-tdfa-text      >= 1.0.0.3
+      , smallcheck           >= 1.1.1
+      , tasty                >= 0.10.1.2
+      , tasty-hunit          >= 0.9.2
+      , tasty-smallcheck     >= 0.8.0.1
+      , template-haskell     >= 2.7
+      , text                 >= 1.2.0.6
+      , unordered-containers >= 0.2.5.1
 
 
+
 Executable re-tutorial
-    Hs-Source-Dirs:     examples .
+    Hs-Source-Dirs:     examples
 
-    Main-is:            re-tutorial.lhs
+    Main-Is:            re-tutorial.lhs
 
-    Other-modules:
+    Other-Modules:
       TestKit
 
     Default-Language:   Haskell2010
     Default-Extensions: QuasiQuotes
     GHC-Options:
-        -Wall
-        -fwarn-tabs
+      -Wall
+      -fwarn-tabs
 
     Build-depends:
-      regex                                     ,
-      array                   >= 0.4            ,
-      bytestring              >= 0.10.2.0       ,
-      base                    >= 4       && < 5 ,
-      containers              >= 0.4            ,
-      directory               >= 1.2.1.0        ,
-      hashable                >= 1.2.3.3        ,
-      heredoc                 >= 0.2.0.0        ,
-      regex-base              >= 0.93.2         ,
-      regex-tdfa              >= 1.2.1          ,
-      regex-tdfa-text         >= 1.0.0.3        ,
-      regex-pcre-builtin      >= 0.94.4.8.8.35  ,
-      shelly                  >= 1.6.1.2        ,
-      smallcheck              >= 1.1.1          ,
-      tasty                   >= 0.10.1.2       ,
-      tasty-hunit             >= 0.9.2          ,
-      tasty-smallcheck        >= 0.8.0.1        ,
-      template-haskell        >= 2.7            ,
-      transformers            >= 0.2.2          ,
-      text                    >= 1.2.1.3        ,
-      time                    >= 1.5.0.1        ,
-      unordered-containers    >= 0.2.5.1
+        regex                
+      , array                >= 0.4
+      , base                 >= 4 && < 5
+      , base-compat          >= 0.6.0
+      , bytestring           >= 0.10.2.0
+      , containers           >= 0.4
+      , directory            >= 1.2.1.0
+      , hashable             >= 1.2.3.3
+      , heredoc              >= 0.2.0.0
+      , regex-base           >= 0.93.2
+      , regex-pcre-builtin   >= 0.94.4.8.8.35
+      , regex-tdfa           >= 1.2.0
+      , regex-tdfa-text      >= 1.0.0.3
+      , shelly               >= 1.6.1.2
+      , smallcheck           >= 1.1.1
+      , tasty                >= 0.10.1.2
+      , tasty-hunit          >= 0.9.2
+      , tasty-smallcheck     >= 0.8.0.1
+      , template-haskell     >= 2.7
+      , text                 >= 1.2.0.6
+      , time                 >= 1.4.2
+      , time-locale-compat   >= 0.1.0.1
+      , transformers         >= 0.2.2
+      , unordered-containers >= 0.2.5.1
 
+
 Test-Suite re-tutorial-test
     type:               exitcode-stdio-1.0
-    Hs-Source-Dirs:     examples .
+    Hs-Source-Dirs:     examples
 
-    Main-is:            re-tutorial.lhs
+    Main-Is:            re-tutorial.lhs
 
-    Other-modules:
+    Other-Modules:
       TestKit
 
     Default-Language:   Haskell2010
     Default-Extensions: QuasiQuotes
     GHC-Options:
-        -Wall
-        -fwarn-tabs
+      -Wall
+      -fwarn-tabs
 
     Build-depends:
-      regex                                     ,
-      array                   >= 0.4            ,
-      bytestring              >= 0.10.2.0       ,
-      base                    >= 4       && < 5 ,
-      containers              >= 0.4            ,
-      directory               >= 1.2.1.0        ,
-      hashable                >= 1.2.3.3        ,
-      heredoc                 >= 0.2.0.0        ,
-      regex-base              >= 0.93.2         ,
-      regex-tdfa              >= 1.2.1          ,
-      regex-tdfa-text         >= 1.0.0.3        ,
-      regex-pcre-builtin      >= 0.94.4.8.8.35  ,
-      shelly                  >= 1.6.1.2        ,
-      smallcheck              >= 1.1.1          ,
-      tasty                   >= 0.10.1.2       ,
-      tasty-hunit             >= 0.9.2          ,
-      tasty-smallcheck        >= 0.8.0.1        ,
-      template-haskell        >= 2.7            ,
-      transformers            >= 0.2.2          ,
-      text                    >= 1.2.1.3        ,
-      time                    >= 1.5.0.1        ,
-      unordered-containers    >= 0.2.5.1
+        regex                
+      , array                >= 0.4
+      , base                 >= 4 && < 5
+      , base-compat          >= 0.6.0
+      , bytestring           >= 0.10.2.0
+      , containers           >= 0.4
+      , directory            >= 1.2.1.0
+      , hashable             >= 1.2.3.3
+      , heredoc              >= 0.2.0.0
+      , regex-base           >= 0.93.2
+      , regex-pcre-builtin   >= 0.94.4.8.8.35
+      , regex-tdfa           >= 1.2.0
+      , regex-tdfa-text      >= 1.0.0.3
+      , shelly               >= 1.6.1.2
+      , smallcheck           >= 1.1.1
+      , tasty                >= 0.10.1.2
+      , tasty-hunit          >= 0.9.2
+      , tasty-smallcheck     >= 0.8.0.1
+      , template-haskell     >= 2.7
+      , text                 >= 1.2.0.6
+      , time                 >= 1.4.2
+      , time-locale-compat   >= 0.1.0.1
+      , transformers         >= 0.2.2
+      , unordered-containers >= 0.2.5.1
+
+
+
+Test-Suite re-tutorial-os-test
+    type:               exitcode-stdio-1.0
+    Hs-Source-Dirs:     examples
+
+    Main-Is:            re-tutorial.lhs
+
+    Other-Modules:
+      TestKit
+
+    Default-Language:   Haskell2010
+    Extensions:         OverloadedStrings
+    Default-Extensions: QuasiQuotes
+    GHC-Options:
+      -Wall
+      -fwarn-tabs
+
+    Build-depends:
+        regex                
+      , array                >= 0.4
+      , base                 >= 4 && < 5
+      , base-compat          >= 0.6.0
+      , bytestring           >= 0.10.2.0
+      , containers           >= 0.4
+      , directory            >= 1.2.1.0
+      , hashable             >= 1.2.3.3
+      , heredoc              >= 0.2.0.0
+      , regex-base           >= 0.93.2
+      , regex-pcre-builtin   >= 0.94.4.8.8.35
+      , regex-tdfa           >= 1.2.0
+      , regex-tdfa-text      >= 1.0.0.3
+      , shelly               >= 1.6.1.2
+      , smallcheck           >= 1.1.1
+      , tasty                >= 0.10.1.2
+      , tasty-hunit          >= 0.9.2
+      , tasty-smallcheck     >= 0.8.0.1
+      , template-haskell     >= 2.7
+      , text                 >= 1.2.0.6
+      , time                 >= 1.4.2
+      , time-locale-compat   >= 0.1.0.1
+      , transformers         >= 0.2.2
+      , unordered-containers >= 0.2.5.1
+
+
+-- Generated from lib/rgex-master.cabal with re-gen-cabals
