packages feed

regex 0.0.0.2 → 0.1.0.0

raw patch · 38 files changed

+2158/−916 lines, 38 filesdep +base-compatdep +http-conduitdep +time-locale-compatdep ~basedep ~regex-tdfadep ~textnew-component:exe:re-gen-cabalsnew-component:exe:re-prepnew-component:exe:re-testsPVP ok

version bump matches the API change (PVP)

Dependencies added: base-compat, http-conduit, time-locale-compat

Dependency ranges changed: base, regex-tdfa, text, time, transformers

API changes (from Hackage documentation)

- Text.RE.Internal.NamedCaptures: instance Monad m => Serial m Token
- Text.RE.Internal.NamedCaptures: namedCapturesTestTree :: TestTree
- Text.RE.Internal.PreludeMacros: PM_decimal :: PreludeMacro
- Text.RE.Internal.PreludeMacros: PM_integer :: PreludeMacro
- Text.RE.Internal.PreludeMacros: PM_natural :: PreludeMacro
- Text.RE.Internal.PreludeMacros: PM_natural_hex :: PreludeMacro
+ Text.RE: (!$$) :: Match a -> CaptureID -> a
+ Text.RE: (!$$?) :: Match a -> CaptureID -> Maybe a
+ Text.RE: (!$) :: Match a -> CaptureID -> Capture a
+ Text.RE: (!$?) :: Match a -> CaptureID -> Maybe (Capture a)
+ Text.RE: ALL :: Context
+ Text.RE: Alert :: Severity
+ Text.RE: Block :: Mode
+ Text.RE: BlockInsensitive :: SimpleRegexOptions
+ Text.RE: BlockSensitive :: SimpleRegexOptions
+ Text.RE: CID_name :: CaptureName -> CaptureID
+ Text.RE: CID_ordinal :: CaptureOrdinal -> CaptureID
+ Text.RE: Capture :: !a -> !a -> !Int -> !Int -> Capture a
+ Text.RE: CaptureName :: Text -> CaptureName
+ Text.RE: CaptureOrdinal :: Int -> CaptureOrdinal
+ Text.RE: Crit :: Severity
+ Text.RE: Debug :: Severity
+ Text.RE: Delete :: LineEdit s
+ Text.RE: EDIT_fun :: Context -> (LineNo -> Match s -> Location -> Capture s -> m (Maybe s)) -> Edit m s
+ Text.RE: EDIT_gen :: (LineNo -> Matches s -> m (LineEdit s)) -> Edit m s
+ Text.RE: EDIT_phi :: (Phi s) -> Edit m s
+ Text.RE: EDIT_tpl :: s -> Edit m s
+ Text.RE: Emerg :: Severity
+ Text.RE: Err :: Severity
+ Text.RE: Info :: Severity
+ Text.RE: Location :: Int -> CaptureOrdinal -> Location
+ Text.RE: MacroID :: String -> MacroID
+ Text.RE: Match :: !a -> !CaptureNames -> !(Array CaptureOrdinal (Capture a)) -> Match a
+ Text.RE: Matches :: !a -> ![Match a] -> Matches a
+ Text.RE: MultilineInsensitive :: SimpleRegexOptions
+ Text.RE: MultilineSensitive :: SimpleRegexOptions
+ Text.RE: NoEdit :: LineEdit s
+ Text.RE: Notice :: Severity
+ Text.RE: Options :: !Mode -> !(Macros r) -> !c -> !e -> Options_ r c e
+ Text.RE: Phi :: Context -> (Location -> a -> a) -> Phi a
+ Text.RE: Pipe :: [(re, Edit m s)] -> Edits m re s
+ Text.RE: ReplaceWith :: s -> LineEdit s
+ Text.RE: Replace_ :: (a -> Int) -> ((a -> a) -> Capture a -> a) -> Replace_ a
+ Text.RE: SUB :: Context
+ Text.RE: Select :: [(re, Edit m s)] -> Edits m re s
+ Text.RE: Simple :: Mode
+ Text.RE: TOP :: Context
+ Text.RE: Warning :: Severity
+ Text.RE: ZeroBasedLineNo :: Int -> LineNo
+ Text.RE: _MacroID :: MacroID -> String
+ Text.RE: _loc_capture :: Location -> CaptureOrdinal
+ Text.RE: _loc_match :: Location -> Int
+ Text.RE: _options_comp :: Options_ r c e -> !c
+ Text.RE: _options_exec :: Options_ r c e -> !e
+ Text.RE: _options_macs :: Options_ r c e -> !(Macros r)
+ Text.RE: _options_mode :: Options_ r c e -> !Mode
+ Text.RE: _phi_context :: Phi a -> Context
+ Text.RE: _phi_phi :: Phi a -> Location -> a -> a
+ Text.RE: _r_length :: Replace_ a -> a -> Int
+ Text.RE: _r_subst :: Replace_ a -> (a -> a) -> Capture a -> a
+ Text.RE: alex :: IsRegex re s => [(re, Match s -> Maybe t)] -> t -> s -> [t]
+ Text.RE: alex' :: Replace s => (re -> s -> Match s) -> [(re, Match s -> Maybe t)] -> t -> s -> [t]
+ Text.RE: allMatches :: Matches a -> ![Match a]
+ Text.RE: anyMatches :: Matches a -> Bool
+ Text.RE: appendNewline :: Replace a => a -> a
+ Text.RE: applyEdit :: (IsRegex re s, Monad m, Functor m) => (s -> s) -> LineNo -> re -> Edit m s -> s -> m (Maybe s)
+ Text.RE: applyEdits :: (IsRegex re s, Monad m, Functor m) => LineNo -> Edits m re s -> s -> m s
+ Text.RE: applyLineEdit :: Monoid s => (s -> s) -> LineEdit s -> Maybe s
+ Text.RE: capture :: CaptureID -> Match a -> Capture a
+ Text.RE: captureLength :: Capture a -> !Int
+ Text.RE: captureMaybe :: CaptureID -> Match a -> Maybe (Capture a)
+ Text.RE: captureNames :: Match a -> !CaptureNames
+ Text.RE: captureOffset :: Capture a -> !Int
+ Text.RE: capturePrefix :: Extract a => Capture a -> a
+ Text.RE: captureSource :: Capture a -> !a
+ Text.RE: captureSuffix :: Extract a => Capture a -> a
+ Text.RE: captureText :: CaptureID -> Match a -> a
+ Text.RE: captureTextMaybe :: CaptureID -> Match a -> Maybe a
+ Text.RE: capturedText :: Capture a -> !a
+ Text.RE: class IsOption o r c e | e -> r, c -> e, e -> c, r -> c, c -> r, r -> e
+ Text.RE: class Replace s => IsRegex re s
+ Text.RE: class (Extract a, Monoid a) => Replace a where textify = pack . unpack_ detextify = pack_ . unpack appendNewline = (<> pack_ "") subst f m@(Capture {..}) = capturePrefix m <> f capturedText <> captureSuffix m
+ Text.RE: countMatches :: Matches a -> Int
+ Text.RE: data Capture a
+ Text.RE: data CaptureID
+ Text.RE: data Context
+ Text.RE: data Edit m s
+ Text.RE: data Edits m re s
+ Text.RE: data LineEdit s
+ Text.RE: data Location
+ Text.RE: data Match a
+ Text.RE: data Matches a
+ Text.RE: data Mode
+ Text.RE: data Options_ r c e
+ Text.RE: data Phi a
+ Text.RE: data Replace_ a
+ Text.RE: data Severity
+ Text.RE: data SimpleRegexOptions
+ Text.RE: detextify :: Replace a => Text -> a
+ Text.RE: emptyMacros :: Macros r
+ Text.RE: expandMacros :: (r -> String) -> Mode -> Macros r -> String -> String
+ Text.RE: expandMacros' :: (MacroID -> Maybe String) -> String -> String
+ Text.RE: findCaptureID :: CaptureID -> CaptureNames -> Int
+ Text.RE: firstLine :: LineNo
+ Text.RE: getCaptureName :: CaptureName -> Text
+ Text.RE: getCaptureOrdinal :: CaptureOrdinal -> Int
+ Text.RE: getLineNo :: LineNo -> Int
+ Text.RE: getZeroBasedLineNo :: LineNo -> Int
+ Text.RE: grep :: IsRegex re ByteString => re -> FilePath -> IO ()
+ Text.RE: grepLines :: IsRegex re ByteString => re -> FilePath -> IO [Line]
+ Text.RE: grepScript :: IsRegex re s => GrepScript re s t -> [s] -> [t]
+ Text.RE: hasCaptured :: Capture a -> Bool
+ Text.RE: isTopLocation :: Location -> Bool
+ Text.RE: length_ :: Replace a => a -> Int
+ Text.RE: lineNo :: Int -> LineNo
+ Text.RE: linesMatched :: [Line] -> [Line]
+ Text.RE: mainCaptures :: Matches a -> [Capture a]
+ Text.RE: makeOptions :: IsOption o r c e => o -> Options_ r c e
+ Text.RE: matchArray :: Match a -> !(Array CaptureOrdinal (Capture a))
+ Text.RE: matchCapture :: Match a -> Maybe (Capture a)
+ Text.RE: matchCaptures :: Match a -> Maybe (Capture a, [Capture a])
+ Text.RE: matchMany :: IsRegex re s => re -> s -> Matches s
+ Text.RE: matchOnce :: IsRegex re s => re -> s -> Match s
+ Text.RE: matchSource :: Match a -> !a
+ Text.RE: matched :: Match a -> Bool
+ Text.RE: matchedText :: Match a -> Maybe a
+ Text.RE: matches :: Matches a -> [a]
+ Text.RE: matchesSource :: Matches a -> !a
+ Text.RE: newtype CaptureName
+ Text.RE: newtype CaptureOrdinal
+ Text.RE: newtype LineNo
+ Text.RE: newtype MacroID
+ Text.RE: noCaptureNames :: CaptureNames
+ Text.RE: noMatch :: a -> Match a
+ Text.RE: pack_ :: Replace a => String -> a
+ Text.RE: parseDate :: Replace a => a -> Maybe Day
+ Text.RE: parseDateTime :: Replace a => a -> Maybe UTCTime
+ Text.RE: parseDateTime8601 :: Replace a => a -> Maybe UTCTime
+ Text.RE: parseDateTimeCLF :: Replace a => a -> Maybe UTCTime
+ Text.RE: parseDouble :: Replace a => a -> Maybe Double
+ Text.RE: parseHex :: Replace a => a -> Maybe Int
+ Text.RE: parseIPv4Address :: Replace a => a -> Maybe IPV4Address
+ Text.RE: parseInteger :: Replace a => a -> Maybe Int
+ Text.RE: parseSeverity :: Replace a => a -> Maybe Severity
+ Text.RE: parseShortMonth :: Replace a => a -> Maybe Int
+ Text.RE: parseSimpleString :: Replace a => a -> Maybe Text
+ Text.RE: parseSlashesDate :: Replace a => a -> Maybe Day
+ Text.RE: parseString :: Replace a => a -> Maybe Text
+ Text.RE: parseTimeOfDay :: Replace a => a -> Maybe TimeOfDay
+ Text.RE: parseTimeZone :: Replace a => a -> Maybe TimeZone
+ Text.RE: parse_tpl :: Replace a => a -> Match a -> Location -> Capture a -> Maybe a
+ Text.RE: regexSource :: IsRegex re s => re -> String
+ Text.RE: replace :: Replace a => Match a -> a -> a
+ Text.RE: replaceAll :: Replace a => a -> Matches a -> a
+ Text.RE: replaceAllCaptures :: Replace a => Phi a -> Matches a -> a
+ Text.RE: replaceAllCaptures' :: Replace a => Context -> (Match a -> Location -> Capture a -> Maybe a) -> Matches a -> a
+ Text.RE: replaceAllCapturesM :: (Extract a, Monad m) => Replace_ a -> Context -> (Match a -> Location -> Capture a -> m (Maybe a)) -> Matches a -> m a
+ Text.RE: replaceAllCaptures_ :: Extract a => Replace_ a -> Context -> (Match a -> Location -> Capture a -> Maybe a) -> Matches a -> a
+ Text.RE: replaceCaptures :: Replace a => Phi a -> Match a -> a
+ Text.RE: replaceCaptures' :: Replace a => Context -> (Match a -> Location -> Capture a -> Maybe a) -> Match a -> a
+ Text.RE: replaceCapturesM :: (Monad m, Extract a) => Replace_ a -> Context -> (Match a -> Location -> Capture a -> m (Maybe a)) -> Match a -> m a
+ Text.RE: replaceCaptures_ :: Extract a => Replace_ a -> Context -> (Match a -> Location -> Capture a -> Maybe a) -> Match a -> a
+ Text.RE: replace_ :: Replace a => Replace_ a
+ Text.RE: sed :: IsRegex re ByteString => SedScript re -> FilePath -> FilePath -> IO ()
+ Text.RE: sed' :: (IsRegex re ByteString, Monad m, Functor m) => Edits m re ByteString -> ByteString -> m ByteString
+ Text.RE: severityKeywords :: Severity -> (Text, [Text])
+ Text.RE: shortMonthArray :: Array Int Text
+ Text.RE: subst :: Replace a => (a -> a) -> Capture a -> a
+ Text.RE: textify :: Replace a => a -> Text
+ Text.RE: type CaptureNames = HashMap CaptureName CaptureOrdinal
+ Text.RE: type GrepScript re s t = [(re, LineNo -> Matches s -> Maybe t)]
+ Text.RE: type IPV4Address = (Word8, Word8, Word8, Word8)
+ Text.RE: type Macros r = HashMap MacroID r
+ Text.RE: type SedScript re = Edits IO re ByteString
+ Text.RE: unpack_ :: Replace a => a -> String
+ Text.RE.Capture: (!$$) :: Match a -> CaptureID -> a
+ Text.RE.Capture: (!$$?) :: Match a -> CaptureID -> Maybe a
+ Text.RE.Capture: (!$) :: Match a -> CaptureID -> Capture a
+ Text.RE.Capture: (!$?) :: Match a -> CaptureID -> Maybe (Capture a)
+ Text.RE.Capture: emptyMatchArray :: Array CaptureOrdinal (Capture a)
+ Text.RE.Capture: noMatch :: a -> Match a
+ Text.RE.Internal.NamedCaptures: BS :: Char -> Token
+ Text.RE.Internal.NamedCaptures: Bra :: Token
+ Text.RE.Internal.NamedCaptures: ECap :: (Maybe String) -> Token
+ Text.RE.Internal.NamedCaptures: Other :: Char -> Token
+ Text.RE.Internal.NamedCaptures: PCap :: Token
+ Text.RE.Internal.NamedCaptures: PGrp :: Token
+ Text.RE.Internal.NamedCaptures: data Token
+ Text.RE.Internal.NamedCaptures: formatTokens :: [Token] -> String
+ Text.RE.Internal.NamedCaptures: formatTokens' :: FormatTokenOptions -> [Token] -> String
+ Text.RE.Internal.NamedCaptures: formatTokens0 :: [Token] -> String
+ Text.RE.Internal.NamedCaptures: idFormatTokenOptions :: FormatTokenOptions
+ Text.RE.Internal.NamedCaptures: scan :: String -> [Token]
+ Text.RE.Internal.NamedCaptures: validToken :: Token -> Bool
+ Text.RE.Internal.PreludeMacros: PM_frac :: PreludeMacro
+ Text.RE.Internal.PreludeMacros: PM_hex :: PreludeMacro
+ Text.RE.Internal.PreludeMacros: PM_id_ :: PreludeMacro
+ Text.RE.Internal.PreludeMacros: PM_int :: PreludeMacro
+ Text.RE.Internal.PreludeMacros: PM_nat :: PreludeMacro
+ Text.RE.Tools.Grep: linesMatched :: [Line] -> [Line]
- Text.RE.Capture: Match :: !a -> CaptureNames -> !(Array CaptureOrdinal (Capture a)) -> Match a
+ Text.RE.Capture: Match :: !a -> !CaptureNames -> !(Array CaptureOrdinal (Capture a)) -> Match a
- Text.RE.Capture: Matches :: !a -> [Match a] -> Matches a
+ Text.RE.Capture: Matches :: !a -> ![Match a] -> Matches a
- Text.RE.Capture: allMatches :: Matches a -> [Match a]
+ Text.RE.Capture: allMatches :: Matches a -> ![Match a]
- Text.RE.Capture: captureNames :: Match a -> CaptureNames
+ Text.RE.Capture: captureNames :: Match a -> !CaptureNames
- Text.RE.Parsers: parseSimpleString :: Replace a => a -> Maybe String
+ Text.RE.Parsers: parseSimpleString :: Replace a => a -> Maybe Text
- Text.RE.Parsers: parseString :: Replace a => a -> Maybe String
+ Text.RE.Parsers: parseString :: Replace a => a -> Maybe Text
- Text.RE.Parsers: severityKeywords :: Severity -> (String, [String])
+ Text.RE.Parsers: severityKeywords :: Severity -> (Text, [Text])
- Text.RE.Parsers: shortMonthArray :: Array Int String
+ Text.RE.Parsers: shortMonthArray :: Array Int Text

Files

+ README.markdown view
@@ -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)
− README.md
@@ -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).
Text/RE.hs view
@@ -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.
Text/RE/Capture.lhs view
@@ -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}
Text/RE/Edit.lhs view
@@ -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
Text/RE/Internal/NamedCaptures.lhs view
@@ -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}
Text/RE/Internal/PreludeMacros.hs view
@@ -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
Text/RE/PCRE.hs view
@@ -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
Text/RE/PCRE/ByteString.hs view
@@ -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   ( (*=~)
Text/RE/PCRE/ByteString/Lazy.hs view
@@ -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   ( (*=~)
Text/RE/PCRE/RE.hs view
@@ -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
Text/RE/PCRE/Sequence.hs view
@@ -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   ( (*=~)
Text/RE/PCRE/String.hs view
@@ -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   ( (*=~)
Text/RE/Parsers.hs view
@@ -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"    []
Text/RE/Replace.lhs view
@@ -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
Text/RE/TDFA.hs view
@@ -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
Text/RE/TDFA/ByteString.hs view
@@ -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   ( (*=~)
Text/RE/TDFA/ByteString/Lazy.hs view
@@ -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   ( (*=~)
Text/RE/TDFA/RE.hs view
@@ -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
Text/RE/TDFA/Sequence.hs view
@@ -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   ( (*=~)
Text/RE/TDFA/String.hs view
@@ -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   ( (*=~)
Text/RE/TDFA/Text.hs view
@@ -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   ( (*=~)
Text/RE/TDFA/Text/Lazy.hs view
@@ -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   ( (*=~)
Text/RE/TestBench.lhs view
@@ -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]     ]
Text/RE/Tools/Grep.lhs view
@@ -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}
Text/RE/Tools/Lex.lhs view
@@ -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]
Text/RE/Tools/Sed.lhs view
@@ -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
changelog view
@@ -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
examples/TestKit.lhs view
@@ -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 =
+ examples/re-gen-cabals.lhs view
@@ -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}
examples/re-gen-modules.lhs view
@@ -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 ()
examples/re-include.lhs view
@@ -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}  
examples/re-nginx-log-processor.lhs view
@@ -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
− examples/re-pp.lhs
@@ -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}
+ examples/re-prep.lhs view
@@ -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}
examples/re-tests.lhs view
@@ -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}
examples/re-tutorial.lhs view
@@ -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
regex.cabal view
@@ -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