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 +0/−102
- Text/Matchers/Pcre.hs +0/−26
- Text/Matchers/Pcre/Base.hsc +0/−135
- Text/Matchers/Times.hs +0/−139
- current-versions.txt +40/−38
- lib/Matchers.hs +104/−0
- lib/Matchers/Pcre.hs +24/−0
- lib/Matchers/Pcre/Base.hsc +123/−0
- lib/Matchers/Times.hs +139/−0
- lib/Matchers/Types.hs +5/−0
- matchers.cabal +12/−10
- minimum-versions.txt +10/−10
- sunlight-test.hs +1/−1
− 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 = [] }