packages feed

matchers 0.18.0.0 → 0.20.0.0

raw patch · 13 files changed

+458/−461 lines, 13 filesdep ~bytestringdep ~parsecdep ~prednote

Dependency ranges changed: bytestring, parsec, prednote, text, time

Files

− Text/Matchers.hs
@@ -1,102 +0,0 @@-module Text.Matchers-  ( CaseSensitive(..)-  , pcre-  , within-  , exact-  , anyTime-  , time-  ) where--import Data.Text (Text, pack, unpack, toCaseFold, isInfixOf)-import qualified Text.Parsec as P-import qualified Data.Time as Time-import Text.Matchers.Times (dateTime)-import Text.Matchers.Pcre as PCRE-import qualified Data.Prednote.Predbox as R--data CaseSensitive = Sensitive | Insensitive deriving (Eq, Ord, Show)--descSensitive :: CaseSensitive -> String-descSensitive c = case c of-  Sensitive -> " (case sensitive)"-  Insensitive -> " (case insensitive)"---- | Uses the PCRE regular expression engine.-pcre-  :: CaseSensitive--  -> Text-  -- ^ Pattern--  -> Either Text (R.Predbox Text)-  -- ^ The Predbox if the pattern is good; if the pattern is bad,-  -- returns an error message.--pcre c t = case PCRE.compile (c == Insensitive) t of-  Left e -> Left . pack $ e-  Right r ->-    let mrDesc = pack $ "matches the PCRE pattern \""-          ++ unpack t ++ "\"" ++ descSensitive c-        mr = maybe False id . PCRE.exec r-    in return $ R.predicate mrDesc mr---- | Matcher that succeeds if the pattern text is found anywhere--- within the subject.-within-  :: CaseSensitive--  -> Text-  -- ^ The pattern--  -> R.Predbox Text-within cs t = R.predicate mrDesc mr-  where-    mrDesc = pack $ "contains the text \"" ++ unpack t-             ++ "\"" ++ descSensitive cs-    mr = txtMatch isInfixOf cs t---- | Matcher that succeeds if the pattern text exactly matches the--- subject (with case sensitivity as appropriate.)-exact :: CaseSensitive -> Text -> R.Predbox Text-exact cs t = R.predicate mrDesc mr-  where-    mrDesc = pack $ "matches the text \"" ++ unpack t-             ++ "\"" ++ descSensitive cs-    mr = txtMatch (==) cs t--txtMatch :: (Text -> Text -> Bool)-            -> CaseSensitive-            -> Text-            -> Text -> Bool-txtMatch f c p t = pat `f` txt where-  txt = flipCase t-  pat = flipCase p-  flipCase = case c of-    Sensitive -> id-    Insensitive -> toCaseFold---- | Matches any valid time.-anyTime :: R.Predbox Text-anyTime = R.predicate mrDesc mr-  where-    mrDesc = pack "any valid time"-    mr x = case P.parse dateTime "" x of-      Left _ -> False-      Right _ -> True---- | If the given ordering is @r@, the given time is @t@, and the--- time of the subject is @s@, the Predbox returns @compare s t == r@.--- Always returns False if the subject is not a valid time.-time-  :: Ordering-  -- ^ @r@-  -> Time.UTCTime-  -- ^ @t@-  -> R.Predbox Text-time ord ti = R.compareByMaybe desc (pack "time") mr ord-  where-    desc = pack . show $ ti-    mr x = case P.parse dateTime "" x of-      Left _ -> Nothing-      Right g -> Just $ (g `compare` ti)-
− Text/Matchers/Pcre.hs
@@ -1,26 +0,0 @@-{-# LANGUAGE Trustworthy #-}-module Text.Matchers.Pcre-  ( B.Caseless-  , B.Regex-  , B.reCaseless-  , B.rePattern-  , compile-  , exec-  ) where--import qualified Text.Matchers.Pcre.Base as B-import qualified Data.Text as X-import System.IO.Unsafe (unsafePerformIO)--compile-  :: B.Caseless-  -> X.Text-  -> Either String B.Regex-compile cl x = unsafePerformIO $ B.compile cl x--exec-  :: B.Regex-  -> X.Text-  -> Maybe Bool-exec r x = unsafePerformIO $ B.exec r x-
− Text/Matchers/Pcre/Base.hsc
@@ -1,135 +0,0 @@-{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}--module Text.Matchers.Pcre.Base-  ( caseless-  , PCRE-  , PCRE_Extra-  , c_free-  , c_pcre_compile-  , c_pcre_exec-  , Caseless-  , pcre_compile-  , pcre_exec-  , Regex-  , reCaseless-  , rePattern-  , compile-  , exec-  ) where--import Foreign.Storable-import Foreign.C-import Foreign.Marshal.Alloc-import Foreign.Marshal.Array-import Foreign.ForeignPtr.Safe-import Foreign.Ptr-import Data.ByteString-import Data.Text-import Data.Text.Encoding--#include <pcre.h>-#include <stdlib.h>--caseless :: CInt-caseless = #const PCRE_CASELESS--data PCRE--instance Show PCRE where-  show _ = "PCRE"--data PCRE_Extra--instance Show PCRE_Extra where-  show _ = "PCRE_Extra"--foreign import ccall unsafe "stdlib.h &free"-  c_free :: FunPtr (Ptr a -> IO ())--foreign import ccall unsafe "pcre.h pcre_compile"-  c_pcre_compile-    :: CString-    -- ^ Pattern-    -> CInt-    -- ^ Options-    -> Ptr CString-    -- ^ OUT error message-    -> Ptr CInt-    -- ^ OUT Error offset-    -> Ptr CUChar-    -- ^ Pointer to character table. Use NULL for default.-    -> IO (Ptr PCRE)--foreign import ccall unsafe "pcre.h pcre_exec"-  c_pcre_exec-    :: Ptr PCRE-    -- ^ Regex-    -> Ptr PCRE_Extra-    -- ^ Result of study-    -> CString-    -- ^ Subject-    -> CInt-    -- ^ Length of subject string.  (Apparently it does not have to be-    -- null terminated?)-    -> CInt-    -- ^ Start at this offset in the subject string.-    -> CInt-    -- ^ Options-    -> Ptr CInt-    -- ^ OUT Output vector.  Information about matching substrings is-    -- stored in this array.-    -> CInt-    -- ^ Output vector size-    -> IO CInt-    -- ^ One more than the highest numbered pair that has been set.--type Caseless = Bool--pcre_compile-  :: Caseless-  -> Text-  -- ^ Pattern-  -> IO (Either String (Ptr PCRE))-  -- ^ Errors are indicated with a Left with the error message.-pcre_compile cl pat-  = useAsCString (encodeUtf8 pat) $ \patC ->-    alloca $ \ptrMsg ->-    alloca $ \ptrOffset -> do-      let cOpt = if cl then caseless else 0-      ptrPcre <- c_pcre_compile patC cOpt ptrMsg ptrOffset nullPtr-      if ptrPcre == nullPtr-        then do-          ptrErr <- peek ptrMsg-          msg <- peekCAString ptrErr-          return . Left $ msg-        else return . Right $ ptrPcre-          -  -pcre_exec :: Ptr PCRE -> Text -> IO (Maybe Bool)-pcre_exec ptr txt-  = useAsCStringLen (encodeUtf8 txt) $ \(ptrSubj, len) ->-    allocaArray 30 $ \array -> do-      r <- c_pcre_exec ptr nullPtr ptrSubj (fromIntegral len)-                       0 0 array 30-      return $ case () of-        _ | r == (-1) -> Just False-          | r < (-1) -> Nothing-          | otherwise -> Just True-        -data Regex = Regex-  { reCaseless :: Caseless-  , rePattern :: Text-  , _rePtr :: ForeignPtr PCRE-  } deriving Show--compile :: Caseless -> Text -> IO (Either String Regex)-compile cl pat = do-  ei <- pcre_compile cl pat-  case ei of-    Left e -> return . Left $ e-    Right ptr -> do-      fp <- newForeignPtr c_free ptr-      return . Right $ Regex cl pat fp--exec :: Regex -> Text -> IO (Maybe Bool)-exec (Regex _ _ fp) s = withForeignPtr fp $ \p -> pcre_exec p s
− Text/Matchers/Times.hs
@@ -1,139 +0,0 @@--- | Time parsers.------ "Text.Matchers" allows you to perform matching based on times.--- Times are parsed using the parsers in this module.-module Text.Matchers.Times where--import Data.Fixed-import Data.Maybe-import Control.Applicative-import Control.Monad-import qualified Data.Time as Time-import Text.Parsec (satisfy)-import qualified Text.Parsec as P-import Text.Parsec.Text (Parser)---- | A four-digit year.-year :: Parser Integer-year = read <$> replicateM 4 P.digit---- | A two-digit month (exactly 2 digits.)-month :: Parser Int-month = read <$> replicateM 2 P.digit---- | A two-digit day (exactly 2 digits.)-day :: Parser Int-day = read <$> replicateM 2 P.digit---- | A valid Gregorian day, in YYYY-MM-DD format.  Each separator--- may be a hyphen or a slash.  Fails if the day is not valid.-pDate :: Parser Time.Day-pDate = p >>= failOnErr-  where-    p = Time.fromGregorianValid-        <$> year  <* satisfy dateSep-        <*> month <* satisfy dateSep-        <*> day-    failOnErr = maybe (fail "could not parse date") return---- | Date separator (slash or hyphen).-dateSep :: Char -> Bool-dateSep c = c == '/' || c == '-'--digit :: Char -> Bool-digit c = c >= '0' && c <= '9'--colon :: Char -> Bool-colon = (== ':')---- | Two digits for the hour (exactly two digits).  Must be between--- 0 and 23.-hours :: Parser Int-hours = p >>= (maybe (fail "could not parse hours") return)-  where-    p = f <$> satisfy digit <*> satisfy digit-    f d1 d2 =-      let r = read [d1,d2]-      in if r < 0 || r > 23-         then Nothing-         else Just r----- | Two digits for the minutes (exactly two digits).  Must be--- between 0 and 59.-minutes :: Parser Int-minutes = p >>= maybe (fail "could not parse minutes") return-  where-    p = f <$ satisfy colon <*> satisfy digit <*> satisfy digit-    f d1 d2 =-      let r = read [d1, d2]-      in if r < 0 || r > 59-         then Nothing-         else Just r---- | Two digits for seconds (exactly two digits).  Must be between 0--- and 59; there are no leap seconds.-seconds :: Parser Pico-seconds = p >>= maybe (fail "could not parse seconds") return-  where-    p = f <$ satisfy colon <*> satisfy digit <*> satisfy digit-    f d1 d2 =-      let r = read [d1, d2] :: Int-      in if r < 0 || r > 59-         then Nothing-         else Just . fromIntegral $ r---- | Hours and minutes, separated by colons, with optional seconds.-time :: Parser Time.TimeOfDay-time = f <$> hours <*> minutes <*> optional seconds-  where-    f h m ms = Time.TimeOfDay h m (fromMaybe 0 ms)---- | Time zone sign, plus or minus.-tzSign :: Parser (Int -> Int)-tzSign = (id <$ satisfy plus) <|> (negate <$ satisfy minus)-  where-    plus = (== '+')-    minus = (== '-')---- | Time zone offset, exactly 4 digits.-tzNumber :: Parser Int-tzNumber = read <$> replicateM 4 (satisfy digit)---- | Time zone; that is, sign and offset.  Both the sign and offset--- are required.  The number of minutes may not exceed 840.-timeZone :: Parser Time.TimeZone-timeZone = p >>= maybe (fail "could not parse time zone") return-  where-    p = f <$> tzSign <*> tzNumber-    f s = minsToOffset . s-    minsToOffset m = if abs m > 840-                     then Nothing-                     else Just (Time.TimeZone m False "")---- | Space or tab.-white :: Char -> Bool-white c = c == ' ' || c == '\t'---- | Time of day, with optional time zone.-timeWithZone :: Parser (Time.TimeOfDay, Maybe Time.TimeZone)-timeWithZone =-  (,) <$> time <* many (satisfy white) <*> optional timeZone----- | Day, followed by optional whitespace, followed by optional time--- with zone.-dateTime :: Parser Time.UTCTime-dateTime =-  f <$> pDate <* many (satisfy white) <*> optional timeWithZone-  where-    f d mayTwithZ = Time.zonedTimeToUTC zt-      where-        zt = Time.ZonedTime lt tz-        lt = Time.LocalTime d tod-        (tod, tz) = case mayTwithZ of-          Nothing -> (Time.midnight, Time.utc)-          Just (t, mayZ) -> case mayZ of-            Nothing -> (t, Time.utc)-            Just z -> (t, z)-
current-versions.txt view
@@ -1,48 +1,50 @@ This package was tested to work with these dependency versions and compiler version. These are the default versions fetched by cabal install.-Tested as of: 2014-03-02 02:11:53.267528 UTC-Path to compiler: ghc-7.6.3-Compiler description: 7.6.3+Tested as of: 2014-07-17 02:09:19.042404 UTC+Path to compiler: ghc-7.8.3+Compiler description: 7.8.3 -/opt/ghc-7.6.3/lib/ghc-7.6.3/package.conf.d:-    Cabal-1.16.0-    array-0.4.0.1-    base-4.6.0.1+/opt/ghc/7.8.3/lib/ghc-7.8.3/package.conf.d:+    Cabal-1.18.1.3+    array-0.5.0.0+    base-4.7.0.1     bin-package-db-0.0.0.0-    binary-0.5.1.1-    bytestring-0.10.0.2-    containers-0.5.0.0-    deepseq-1.3.0.1-    directory-1.2.0.1-    filepath-1.3.0.1-    (ghc-7.6.3)-    ghc-prim-0.3.0.0-    (haskell2010-1.1.1.0)-    (haskell98-2.0.0.2)-    hoopl-3.9.0.0-    hpc-0.6.0.0-    integer-gmp-0.5.0.0-    old-locale-1.0.0.5-    old-time-1.1.0.1-    pretty-1.1.1.0-    process-1.1.0.2+    binary-0.7.1.0     rts-1.0-    template-haskell-2.8.0.0-    time-1.4.0.1-    unix-2.6.0.1+    bytestring-0.10.4.0+    containers-0.5.5.1+    deepseq-1.3.0.2+    directory-1.2.1.0+    filepath-1.3.0.2+    (ghc-7.8.3)+    ghc-prim-0.3.1.0+    haskeline-0.7.1.2+    (haskell2010-1.1.2.0)+    (haskell98-2.0.0.3)+    hoopl-3.10.0.1+    hpc-0.6.0.1+    integer-gmp-0.5.1.0+    old-locale-1.0.0.6+    old-time-1.1.0.2+    pretty-1.1.1.1+    process-1.2.0.0+    template-haskell-2.9.0.0+    terminfo-0.4.0.0+    time-1.4.2+    transformers-0.3.0.0+    unix-2.7.0.1+    xhtml-3000.2.1 -/home/massysett/matchers/sunlight-26440/db:-    contravariant-0.4.4-    matchers-0.18.0.0-    mtl-2.1.2+/home/massysett/matchers/sunlight-7904/db:+    contravariant-0.6+    matchers-0.20.0.0+    mtl-2.2.1     parsec-3.1.5-    prednote-0.22.0.0-    rainbow-0.6.0.4+    prednote-0.24.0.0+    rainbow-0.14.0.2     split-0.2.2-    tagged-0.7-    terminfo-0.4.0.0-    text-1.1.0.0-    transformers-0.3.0.0-    transformers-compat-0.1.1.1+    text-1.1.1.3+    transformers-0.4.1.0+    transformers-compat-0.3.3.4 
+ lib/Matchers.hs view
@@ -0,0 +1,104 @@+{-# LANGUAGE OverloadedStrings #-}+module Matchers+  ( CaseSensitive(..)+  , pcre+  , within+  , exact+  , anyTime+  , time+  ) where++import Data.Text (Text, pack, toCaseFold, isInfixOf)+import qualified Text.Parsec as P+import qualified Data.Time as Time+import Matchers.Times (dateTime)+import Matchers.Pcre as PCRE+import qualified Prednote as R+import qualified Prednote.Comparisons as R+import Matchers.Types+import Data.Monoid++pcre+  :: CaseSensitive+  -> Text+  -- ^ Pattern+  -> Either String (R.Pred Text)+pcre cs txt = fmap f $ compile cs txt+  where+    f pc = R.predicate st dyn pd+      where+        st = "matches the PCRE regular expression "+          <> txt <> " - " <> s+        s = case cs of+          Sensitive -> "case sensitive"+          Insensitive -> "case insensitive"+        dyn x = "text " <> pack (show x) <> " - " <> st+        pd x = case exec pc x of+          Nothing -> False+          Just b -> b++within+  :: CaseSensitive+  -> Text+  -- ^ Pattern+  -> R.Pred Text+within cs txt = txtMatch isInfixOf st cs txt+  where+    st = "contains the text " <> pack (show txt)++exact+  :: CaseSensitive+  -> Text+  -> R.Pred Text+exact cs txt = txtMatch (==) st cs txt+  where+    st = "exactly matches the text " <> pack (show txt)++txtMatch+  :: (Text -> Text -> Bool)+  -> Text+  -- ^ Static label+  -> CaseSensitive+  -> Text+  -- ^ Pattern+  -> R.Pred Text+txtMatch f lbl c p = R.predicate st dyn pd+  where+    st = lbl <> " - " <> cs+    (cs, flipCase) = case c of+      Sensitive -> ("case sensitive", id)+      Insensitive -> ("case insensitive", toCaseFold)+    dyn txt = "text " <> pack (show txt) <> " - " <> st+    pd t = f pat txt+      where+        txt = flipCase t+        pat = flipCase p+++-- | Matches any valid time.+anyTime :: R.Pred Text+anyTime = R.predicate st dyn pd+  where+    st = "is any valid date or time"+    dyn x = "text " <> pack (show x) <> " - " <> st+    pd x = case P.parse dateTime "" x of+      Left _ -> False+      Right _ -> True++-- | If the given ordering is @r@, the given time is @t@, and the+-- time of the subject is @s@, the Predbox returns @compare s t == r@.+-- Always returns False if the subject is not a valid time.+time+  :: Time.UTCTime+  -- ^ @t@+  -> Ordering+  -- ^ @r@+  -> R.Pred Text+time ti ord = R.compareByMaybe "time" descRhs descLhs cmp ord+  where+    descRhs = pack . show $ ti+    descLhs = pack . show+    cmp x = case P.parse dateTime "" x of+      Left _ -> Nothing+      Right g -> Just $ (g `compare` ti)+
+ lib/Matchers/Pcre.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE Trustworthy #-}+module Matchers.Pcre+  ( B.PCRE+  , compile+  , exec+  ) where++import qualified Matchers.Pcre.Base as B+import qualified Data.Text as X+import System.IO.Unsafe (unsafePerformIO)+import Matchers.Types++compile+  :: CaseSensitive+  -> X.Text+  -> Either String B.PCRE+compile cl x = unsafePerformIO $ B.compile cl x++exec+  :: B.PCRE+  -> X.Text+  -> Maybe Bool+exec r x = unsafePerformIO $ B.exec r x+
+ lib/Matchers/Pcre/Base.hsc view
@@ -0,0 +1,123 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}++module Matchers.Pcre.Base+  ( PCRE+  , compile+  , exec+  ) where++import Foreign.Storable+import Foreign.C+import Foreign.Marshal.Alloc+import Foreign.Marshal.Array+import Foreign.ForeignPtr.Safe+import Foreign.Ptr+import Data.ByteString+import Data.Text+import Data.Text.Encoding+import Matchers.Types++#include <pcre.h>+#include <stdlib.h>++caseless :: CInt+caseless = #const PCRE_CASELESS++data PCREData++instance Show PCREData where+  show _ = "PCREData"++data PCRE_Extra++instance Show PCRE_Extra where+  show _ = "PCRE_Extra"++foreign import ccall unsafe "stdlib.h &free"+  c_free :: FunPtr (Ptr a -> IO ())++foreign import ccall unsafe "pcre.h pcre_compile"+  c_pcre_compile+    :: CString+    -- ^ Pattern+    -> CInt+    -- ^ Options+    -> Ptr CString+    -- ^ OUT error message+    -> Ptr CInt+    -- ^ OUT Error offset+    -> Ptr CUChar+    -- ^ Pointer to character table. Use NULL for default.+    -> IO (Ptr PCREData)++foreign import ccall unsafe "pcre.h pcre_exec"+  c_pcre_exec+    :: Ptr PCREData+    -- ^ Regex++    -> Ptr PCRE_Extra+    -- ^ Result of study.  Just pass NULL if you did not study the+    -- pattern.++    -> CString+    -- ^ Subject+    -> CInt+    -- ^ Length of subject string.  (Apparently it does not have to be+    -- null terminated?)+    -> CInt+    -- ^ Start at this offset in the subject string.+    -> CInt+    -- ^ Options+    -> Ptr CInt+    -- ^ OUT Output vector.  Information about matching substrings is+    -- stored in this array.+    -> CInt+    -- ^ Output vector size+    -> IO CInt+    -- ^ One more than the highest numbered pair that has been set.++pcre_compile+  :: CaseSensitive+  -> Text+  -- ^ Pattern+  -> IO (Either String (Ptr PCREData))+  -- ^ Errors are indicated with a Left with the error message.+pcre_compile cl pat+  = useAsCString (encodeUtf8 pat) $ \patC ->+    alloca $ \ptrMsg ->+    alloca $ \ptrOffset -> do+      let cOpt = if cl == Insensitive then caseless else 0+      ptrPcre <- c_pcre_compile patC cOpt ptrMsg ptrOffset nullPtr+      if ptrPcre == nullPtr+        then do+          ptrErr <- peek ptrMsg+          msg <- peekCAString ptrErr+          return . Left $ msg+        else return . Right $ ptrPcre+          +  +pcre_exec :: Ptr PCREData -> Text -> IO (Maybe Bool)+pcre_exec ptr txt+  = useAsCStringLen (encodeUtf8 txt) $ \(ptrSubj, len) ->+    allocaArray 30 $ \array -> do+      r <- c_pcre_exec ptr nullPtr ptrSubj (fromIntegral len)+                       0 0 array 30+      return $ case () of+        _ | r == (-1) -> Just False+          | r < (-1) -> Nothing+          | otherwise -> Just True+        +newtype PCRE = PCRE (ForeignPtr PCREData)+  deriving Show++compile :: CaseSensitive -> Text -> IO (Either String PCRE)+compile cl pat = do+  ei <- pcre_compile cl pat+  case ei of+    Left e -> return . Left $ e+    Right ptr -> do+      fp <- newForeignPtr c_free ptr+      return . Right $ PCRE fp++exec :: PCRE -> Text -> IO (Maybe Bool)+exec (PCRE fp) s = withForeignPtr fp $ \p -> pcre_exec p s
+ lib/Matchers/Times.hs view
@@ -0,0 +1,139 @@+-- | Time parsers.+--+-- "Matchers" allows you to perform matching based on times.+-- Times are parsed using the parsers in this module.+module Matchers.Times where++import Data.Fixed+import Data.Maybe+import Control.Applicative+import Control.Monad+import qualified Data.Time as Time+import Text.Parsec (satisfy)+import qualified Text.Parsec as P+import Text.Parsec.Text (Parser)++-- | A four-digit year.+year :: Parser Integer+year = read <$> replicateM 4 P.digit++-- | A two-digit month (exactly 2 digits.)+month :: Parser Int+month = read <$> replicateM 2 P.digit++-- | A two-digit day (exactly 2 digits.)+day :: Parser Int+day = read <$> replicateM 2 P.digit++-- | A valid Gregorian day, in YYYY-MM-DD format.  Each separator+-- may be a hyphen or a slash.  Fails if the day is not valid.+pDate :: Parser Time.Day+pDate = p >>= failOnErr+  where+    p = Time.fromGregorianValid+        <$> year  <* satisfy dateSep+        <*> month <* satisfy dateSep+        <*> day+    failOnErr = maybe (fail "could not parse date") return++-- | Date separator (slash or hyphen).+dateSep :: Char -> Bool+dateSep c = c == '/' || c == '-'++digit :: Char -> Bool+digit c = c >= '0' && c <= '9'++colon :: Char -> Bool+colon = (== ':')++-- | Two digits for the hour (exactly two digits).  Must be between+-- 0 and 23.+hours :: Parser Int+hours = p >>= (maybe (fail "could not parse hours") return)+  where+    p = f <$> satisfy digit <*> satisfy digit+    f d1 d2 =+      let r = read [d1,d2]+      in if r < 0 || r > 23+         then Nothing+         else Just r+++-- | Two digits for the minutes (exactly two digits).  Must be+-- between 0 and 59.+minutes :: Parser Int+minutes = p >>= maybe (fail "could not parse minutes") return+  where+    p = f <$ satisfy colon <*> satisfy digit <*> satisfy digit+    f d1 d2 =+      let r = read [d1, d2]+      in if r < 0 || r > 59+         then Nothing+         else Just r++-- | Two digits for seconds (exactly two digits).  Must be between 0+-- and 59; there are no leap seconds.+seconds :: Parser Pico+seconds = p >>= maybe (fail "could not parse seconds") return+  where+    p = f <$ satisfy colon <*> satisfy digit <*> satisfy digit+    f d1 d2 =+      let r = read [d1, d2] :: Int+      in if r < 0 || r > 59+         then Nothing+         else Just . fromIntegral $ r++-- | Hours and minutes, separated by colons, with optional seconds.+time :: Parser Time.TimeOfDay+time = f <$> hours <*> minutes <*> optional seconds+  where+    f h m ms = Time.TimeOfDay h m (fromMaybe 0 ms)++-- | Time zone sign, plus or minus.+tzSign :: Parser (Int -> Int)+tzSign = (id <$ satisfy plus) <|> (negate <$ satisfy minus)+  where+    plus = (== '+')+    minus = (== '-')++-- | Time zone offset, exactly 4 digits.+tzNumber :: Parser Int+tzNumber = read <$> replicateM 4 (satisfy digit)++-- | Time zone; that is, sign and offset.  Both the sign and offset+-- are required.  The number of minutes may not exceed 840.+timeZone :: Parser Time.TimeZone+timeZone = p >>= maybe (fail "could not parse time zone") return+  where+    p = f <$> tzSign <*> tzNumber+    f s = minsToOffset . s+    minsToOffset m = if abs m > 840+                     then Nothing+                     else Just (Time.TimeZone m False "")++-- | Space or tab.+white :: Char -> Bool+white c = c == ' ' || c == '\t'++-- | Time of day, with optional time zone.+timeWithZone :: Parser (Time.TimeOfDay, Maybe Time.TimeZone)+timeWithZone =+  (,) <$> time <* many (satisfy white) <*> optional timeZone+++-- | Day, followed by optional whitespace, followed by optional time+-- with zone.+dateTime :: Parser Time.UTCTime+dateTime =+  f <$> pDate <* many (satisfy white) <*> optional timeWithZone+  where+    f d mayTwithZ = Time.zonedTimeToUTC zt+      where+        zt = Time.ZonedTime lt tz+        lt = Time.LocalTime d tod+        (tod, tz) = case mayTwithZ of+          Nothing -> (Time.midnight, Time.utc)+          Just (t, mayZ) -> case mayZ of+            Nothing -> (t, Time.utc)+            Just z -> (t, z)+
+ lib/Matchers/Types.hs view
@@ -0,0 +1,5 @@+module Matchers.Types where++data CaseSensitive = Sensitive | Insensitive+  deriving (Eq, Ord, Show)+
matchers.cabal view
@@ -1,5 +1,5 @@ Name: matchers-Version: 0.18.0.0+Version: 0.20.0.0 Cabal-version: >=1.8 Build-Type: Simple License: BSD3@@ -26,19 +26,21 @@ Library     Build-depends:           base >=4.5.0.0 && < 5-        , bytestring >=0.9.2.1-        , parsec >= 3.1.2-        , prednote >= 0.22.0.0-        , text >=0.11.2.0-        , time >=1.4+        , bytestring >=0.9.2.1 && < 0.11+        , parsec >= 3.1.2 && < 3.2+        , text >=0.11.2.0 && < 1.2+        , time >=1.4 && < 1.5+        , prednote >= 0.24.0.0 && < 0.25       Exposed-modules:-        Text.Matchers-      , Text.Matchers.Pcre-      , Text.Matchers.Pcre.Base-      , Text.Matchers.Times+        Matchers+      , Matchers.Pcre+      , Matchers.Pcre.Base+      , Matchers.Times+      , Matchers.Types     extra-libraries: pcre     ghc-options: -Wall+   hs-source-dirs: lib
minimum-versions.txt view
@@ -1,7 +1,7 @@ This package was tested to work with these dependency versions and compiler version. These are the minimum versions given in the .cabal file.-Tested as of: 2014-03-02 02:11:53.267528 UTC+Tested as of: 2014-07-17 02:09:19.042404 UTC Path to compiler: ghc-7.4.1 Compiler description: 7.4.1 @@ -33,17 +33,17 @@     time-1.4     unix-2.5.1.0 -/home/massysett/matchers/sunlight-26440/db:-    contravariant-0.4.4-    matchers-0.18.0.0-    mtl-2.1.2+/home/massysett/matchers/sunlight-7904/db:+    contravariant-0.6+    matchers-0.20.0.0+    mtl-2.2.1     parsec-3.1.2-    prednote-0.22.0.0-    rainbow-0.6.0.4+    prednote-0.24.0.0+    rainbow-0.14.0.2     split-0.2.2-    tagged-0.7+    tagged-0.7.2     terminfo-0.4.0.0     text-0.11.2.0-    transformers-0.3.0.0-    transformers-compat-0.1.1.1+    transformers-0.4.1.0+    transformers-compat-0.3.3.4 
sunlight-test.hs view
@@ -8,7 +8,7 @@   { tiDescription = Nothing   , tiCabal = "cabal"   , tiLowest = ghc "7.4.1"-  , tiDefault = [ ghc "7.4.1", ghc "7.6.3" ]+  , tiDefault = [ ghc "7.4.1", ghc "7.6.3", ghc "7.8.3" ]   , tiTest = []   }