regex-do 1.3 → 1.4
raw patch · 31 files changed
+924/−920 lines, 31 files
Files
- regex-do.cabal +16/−16
- src/Regexdo/Convert.hs +0/−13
- src/Regexdo/Format.hs +0/−72
- src/Regexdo/Pcre/Match.hs +0/−80
- src/Regexdo/Pcre/Option.hs +0/−57
- src/Regexdo/Pcre/Replace.hs +0/−233
- src/Regexdo/Pcre/Result.hs +0/−27
- src/Regexdo/Search.hs +0/−108
- src/Regexdo/Trim.hs +0/−23
- src/Regexdo/TypeDo.hs +0/−28
- src/Regexdo/TypeRegex.hs +0/−15
- src/Text/Regex/Do/Convert.hs +13/−0
- src/Text/Regex/Do/Format.hs +72/−0
- src/Text/Regex/Do/Pcre/Match.hs +74/−0
- src/Text/Regex/Do/Pcre/Option.hs +57/−0
- src/Text/Regex/Do/Pcre/Replace.hs +233/−0
- src/Text/Regex/Do/Pcre/Result.hs +27/−0
- src/Text/Regex/Do/Split.hs +108/−0
- src/Text/Regex/Do/Trim.hs +23/−0
- src/Text/Regex/Do/TypeDo.hs +36/−0
- src/Text/Regex/Do/TypeRegex.hs +15/−0
- test/Main.hs +4/−4
- test/TestRegex/Format.hs +0/−20
- test/TestRegex/Pcre.hs +0/−60
- test/TestRegex/Replace.hs +0/−88
- test/TestRegex/StringSearch.hs +0/−74
- test/TestRegex/TestFormat.hs +22/−0
- test/TestRegex/TestPcre.hs +60/−0
- test/TestRegex/TestReplace.hs +88/−0
- test/TestRegex/TestSplit.hs +74/−0
- test/TestRegex/TestTrim.hs +2/−2
regex-do.cabal view
@@ -1,7 +1,7 @@ name: regex-do-version: 1.3+version: 1.4 synopsis: PCRE wrapper-description: search, replace, format String | ByteString with PCRE regex Utf8-safe+description: format, search, replace (String | ByteString) with PCRE regex. Utf8-safe author: Imants Cekusins maintainer: Imants Cekusins category: Regex, Search, String@@ -13,16 +13,16 @@ library exposed-modules:- Regexdo.Trim- Regexdo.Pcre.Match- Regexdo.Pcre.Option- Regexdo.Pcre.Replace- Regexdo.Pcre.Result- Regexdo.Search- Regexdo.Format- Regexdo.TypeDo- Regexdo.TypeRegex- Regexdo.Convert+ Text.Regex.Do.Trim+ Text.Regex.Do.Pcre.Match+ Text.Regex.Do.Pcre.Option+ Text.Regex.Do.Pcre.Replace+ Text.Regex.Do.Pcre.Result+ Text.Regex.Do.Split+ Text.Regex.Do.Format+ Text.Regex.Do.TypeDo+ Text.Regex.Do.TypeRegex+ Text.Regex.Do.Convert other-modules: @@ -68,10 +68,10 @@ main-is: Main.hs other-modules:- TestRegex.Format- TestRegex.Pcre- TestRegex.Replace- TestRegex.StringSearch+ TestRegex.TestFormat+ TestRegex.TestPcre+ TestRegex.TestReplace+ TestRegex.TestSplit TestRegex.TestTrim build-depends: base <= 5.0,
− src/Regexdo/Convert.hs
@@ -1,13 +0,0 @@-module Regexdo.Convert where--import qualified Data.Text.Encoding as E-import qualified Data.Text as T-import Data.ByteString as B---- | both Ascii and Utf8-toByteString::String -> ByteString-toByteString = E.encodeUtf8 . T.pack---- | both Ascii and Utf8-toString::ByteString -> String-toString = T.unpack . E.decodeUtf8
− src/Regexdo/Format.hs
@@ -1,72 +0,0 @@-module Regexdo.Format- (pad,- Format(..)) where--import Prelude as P-import Regexdo.TypeDo-import Regexdo.Search as S (replace)-import Regexdo.Convert---class Format a where- format::String -> a -> String---instance Format [String] where- format = foldr_idx foldFn_idx--- ^--- === index based--- >>> format "на первое {0}, на второе {0}" ["перловка"]------ "на первое перловка, на второе перловка"------ >>> format "Polly {0} a {1}" ["got","cracker"]------ "Polly got a cracker"-----foldFn_idx::String -> (Int, String) -> String-foldFn_idx v (i,body1) = replaceOne body1 (show i) v---instance Format [(String,String)] where- format = P.foldr foldFn_map--- ^--- === key based--- key may be {any string}------ >>> format "овчинка {a} не {b}" [("a","выделки"),("b","стоит")]------ "овчинка выделки не стоит"-----foldFn_map:: (String, String) -> String -> String-foldFn_map (k,v) body1 = replaceOne body1 k v--replaceOne::String -> String -> String -> String-replaceOne body k v = toString bs1- where pat1 = Needle $ toByteString $ "{" ++ k ++ "}"- repl1 = Replacement $ toByteString v- bs1 = S.replace pat1 repl1 $ Haystack $ toByteString body---- | pad String with Char to total length of Int------ >>> pad '-' 5 "abc"--- "--abc"----pad::Char -> Int -> String -> String-pad c0 tot0 txt0 =- [const c0 p1 | p1 <- [1..(tot0 - (P.length txt0))]] ++ txt0----- fold with index-type CustomerFn a b = (a -> (Int,b) -> b)--foldr_idx :: CustomerFn a b -> b -> [a] -> b-foldr_idx fn init1 list = b1- where i0 = P.length list - 1- (-1,b1) = P.foldr (foldFn fn) (i0,init1) list--foldFn :: CustomerFn a b -> a -> (Int,b) -> (Int,b)-foldFn fn val t@(i,_)= (i-1,b1)- where b1 = fn val t
− src/Regexdo/Pcre/Match.hs
@@ -1,80 +0,0 @@-module Regexdo.Pcre.Match where--import qualified Text.Regex.Base.RegexLike as R hiding (makeRegex)-import qualified Text.Regex.Base.RegexLike as R (makeRegex)-import Regexdo.TypeDo-import Regexdo.Pcre.Option as O-import Regexdo.TypeRegex-import Data.ByteString--{- |- see "Regexdo.Pcre.Result"- for funs converting 'MatchArray' to something useful-- 'match' returns the first occurrence - if any-- -}---class Match_ctr n h =>- Match_cl n h where-- match::Needle n -> Haystack h -> Maybe MatchArray- match r0 (Haystack b0) = R.matchOnce (r_ r0) b0-- matchTest::Needle n -> Haystack h -> Bool- matchTest r0 (Haystack b0) = R.matchTest (r_ r0) b0-- matchAll::Needle n -> Haystack h -> [MatchArray]- matchAll r0 (Haystack b0) = R.matchAll (r_ r0) b0------- | tweak Regex with options-makeRegexOpts::Match_opt n =>- [O.Comp] -> [O.Exec] -> Needle n -> Regex-makeRegexOpts comp0 exec0 (Needle pat0) = rx1- where c1 = O.comp comp0- e1 = O.exec exec0- rx1 = R.makeRegexOpts c1 e1 pat0---{- |- this instance accepts regex 'String'-- >>> matchTest (Needle "^ab") (Haystack "abc")-- True--}--instance Match_cl String String--- | accepts regex 'String'-instance Match_cl String ByteString--- | accepts regex 'ByteString'-instance Match_cl ByteString ByteString--- | accepts regex 'ByteString'-instance Match_cl ByteString String--- | accepts 'Regex' made with 'makeRegexOpts'-instance Match_cl Regex String--- | accepts 'Regex' made with 'makeRegexOpts'-instance Match_cl Regex ByteString----instance Needle_ ByteString where- r_ (Needle r0) = R.makeRegex r0--instance Needle_ String where- r_ (Needle r0) = R.makeRegex r0--instance Needle_ Regex where- r_ (Needle r0) = r0----- | _ctr: constraint-type Match_ctr n h = (R.Extract h, Needle_ n, R.RegexLike Regex h)-type Match_opt n = R.RegexMaker Regex CompOption ExecOption n--class Needle_ r where- r_::Needle r -> Regex
− src/Regexdo/Pcre/Option.hs
@@ -1,57 +0,0 @@-module Regexdo.Pcre.Option (- Comp(..),- Exec(..),- comp,- exec- ) where--import Data.Bits-import qualified Text.Regex.PCRE.ByteString as B---data Comp = Blank -- ^ 'B.compBlank'- | Anchored -- ^ 'B.compAnchored'- | Caseless -- ^ 'B.compCaseless'- | Dotall -- ^ 'B.compDotAll'- | Multiline -- ^ 'B.compMultiline'- | Utf8 -- ^ 'B.compUTF8'- | Ungreedy -- ^ 'B.compUngreedy'- deriving Enum---data Exec = BlankE -- ^ 'B.execBlank'- | NotEmpty -- ^ 'B.execNotEmpty'- | Partial -- ^ 'B.execPartial'- deriving Enum---compOpt::Comp -> B.CompOption-compOpt o = case o of- Blank -> B.compBlank- Anchored -> B.compAnchored- Caseless -> B.compCaseless- Dotall -> B.compDotAll- Multiline -> B.compMultiline- Utf8 -> B.compUTF8- Ungreedy -> B.compUngreedy---comp::[Comp] -> B.CompOption-comp [] = B.compBlank-comp l = foldl (.&.) o0 l1- where l1 = compOpt <$> l- o0 = compOpt $ head l---execOpt::Exec -> B.ExecOption-execOpt o = case o of- BlankE -> B.execBlank- NotEmpty -> B.execNotEmpty- Partial -> B.execPartial---exec::[Exec] -> B.ExecOption-exec [] = B.execBlank-exec l = foldl (.&.) o0 l1- where l1 = execOpt <$> l- o0 = execOpt $ head l
− src/Regexdo/Pcre/Replace.hs
@@ -1,233 +0,0 @@-module Regexdo.Pcre.Replace(- ReplaceCase(..),- Replace_cl(..),- replaceMatch,- defaultReplacer,- getGroup,- Mr- ) where--import Data.Array as A-import Data.ByteString-import Prelude as P-import qualified Data.ByteString as B-import qualified Regexdo.Pcre.Option as O-import qualified Text.Regex.Base.RegexLike as R-import Regexdo.Convert-import Regexdo.Pcre.Match-import Regexdo.Pcre.Result-import Regexdo.TypeDo-import Regexdo.TypeRegex---type Mr a = (Match_cl Regex a, Replace_cl' a, Match_opt a)---class Replace_cl' a where- prefix::PosLen -> a -> a- suffix::PosLen -> a -> a- concat'::[a] -> a- len'::a -> Int- toByteString'::a -> ByteString- toA::ByteString -> a---class Replace_cl a where- replace::Mr a =>- [ReplaceCase] -> (Needle a, Replacement a) -> Haystack a -> a- replace cases0 (pat1,repl1) hay0 =- if isUtf8 cases0 then utfFn2- else fn2 (pat2 pat1,repl1) hay0- where fn1 = if P.elem All cases0 then rall else ronce- fn2 = if P.elem All cases0 then rall else ronce- utfFn2 = let res1 = fn1 (pat2 $ toByteString' <$> pat1, toByteString' <$> repl1) $ toByteString' <$> hay0- in toA res1- pat2 pat1 = addOpt pat1 cOpt1- cOpt1 = comp cases0--- replaceGroup::Mr a =>- [ReplaceCase] -> (Needle a, GroupReplacer a) -> Haystack a -> a- replaceGroup cases (pat1,repl1) = fn1 (pat2,repl1)- where pat2 = addOpt pat1 cOpt- cOpt = comp cases- fn1 = if P.elem All cases- then rallGroup- else ronceGroup--{- ^- == dynamic group replace- custom replacer fn returns replacement value-- >>> replacer::GroupReplacer String- replacer = defaultReplacer 1 tweak1- where tweak1 str1 = case str1 of- "101" -> "[сто один]"- "3" -> "[three]"- otherwise -> trace str1 "?"-- 'Once' vs 'All' options-- >>> replaceGroup [Once,Utf8] (Needle "\\w=(\\d{1,3})", replacer) $ Haystack "a=101 b=3 12"-- "a=[сто один] b=3 12"-- >>> replaceGroup [All,Utf8] (Needle "\\w=(\\d{1,3})", replacer) $ Haystack "a=101 b=3 12"-- "a=[сто один] b=[three] 12"--- == static replace for simple (no group) needle-- >>> replace [Once,Utf8] (Needle "менее", Replacement "более") $ Haystack "менее менее"-- "более менее"-- >>> replace [Once,Utf8] (Needle "^a\\s", Replacement "A") $ Haystack "a bc хол.гор."-- "Abc хол.гор." -}---instance Replace_cl String--instance Replace_cl' String where- prefix pl1 = P.take $ fst pl1- suffix pl1 = P.drop (pos1 + len1)- where pos1 = fst pl1- len1 = snd pl1- concat' = P.concat- toByteString' = toByteString- toA = toString- len' = P.length---instance Replace_cl B.ByteString--instance Replace_cl' B.ByteString where- prefix pl1 = B.take $ fst pl1- suffix pl1 = B.drop (pos1 + len1)- where pos1 = fst pl1- len1 = snd pl1- concat' = B.concat- toByteString' = id- toA = id- len' = B.length----- static-ronce::Mr a =>- (Needle Regex, Replacement a) -> Haystack a -> a-ronce (pat1, Replacement repl1) h1@(Haystack h0) =- let pl2 = do- let m1 = match pat1 h1- poslen m1- in case pl2 of- Nothing -> h0- Just lpl1 -> firstGroup lpl1 (repl1, h0)---rall::Mr a =>- (Needle Regex, Replacement a) -> Haystack a -> a-rall (pat1, Replacement repl1) h1@(Haystack h0) =- let lpl1 = do- let m1 = matchAll pat1 h1- poslen m1::[[PosLen]]- foldFn1 lpl1 acc1 = firstGroup lpl1 (repl1,acc1)- in P.foldr foldFn1 h0 lpl1---firstGroup::(Replace_cl' a) =>- [PosLen] -> (a,a) -> a-firstGroup (pl0:_) r1@(new0,a0) = acc_haystack $ replaceMatch pl0 (new0, acc1)- where acc1 = ReplaceAcc {- acc_haystack = a0,- position_adj = 0- }----- dynamic-{- | you can write a custom replacer. This is only one common use case.-- Replaces specified (by idx) group match with tweaked value. -}-defaultReplacer::(Replace_cl' a, R.Extract a) =>- Int -- ^ group idx- -> (a -> a) -- ^ (group match -> replacement) tweak- -> GroupReplacer a-defaultReplacer idx0 tweak0 (ma0::MatchArray) acc0 = maybe acc0 fn1 mval1- where pl1 = ma0 A.! idx0 :: (R.MatchOffset, R.MatchLength)- mval1 = getGroup acc0 ma0 idx0- fn1 str1 = replaceMatch pl1 (str2, acc0)- where str2 = tweak0 str1---{- | get group content safely-- call from your custom 'GroupReplacer' passed to 'replaceGroup'- -}-getGroup::R.Extract a =>- ReplaceAcc a -> MatchArray -> Int -> Maybe a-getGroup acc0 ma0 idx0 = if idx0 >= P.length ma0 then Nothing -- safety catch- else Just val1- where pl1 = ma0 A.! idx0 :: (R.MatchOffset, R.MatchLength)- pl2 = adjustPoslen pl1 acc0- val1 = extract pl2 $ acc_haystack acc0---adjustPoslen::PosLen -> ReplaceAcc a -> PosLen-adjustPoslen (p0,l0) acc0 = (p0 + position_adj acc0, l0)---ronceGroup::Match_cl Regex a =>- (Needle Regex, GroupReplacer a) -> Haystack a -> a-ronceGroup (pat1, repl1) h1@(Haystack h0) =- let m1 = match pat1 h1::Maybe MatchArray- in case m1 of- Nothing -> h0- Just ma1 -> let a1 = ReplaceAcc {- acc_haystack = h0,- position_adj = 0- }- in acc_haystack $ repl1 ma1 a1---rallGroup::Match_cl Regex a =>- (Needle Regex, GroupReplacer a) -> Haystack a -> a-rallGroup (pat1, repl1) h1@(Haystack h0) =- let ma1 = matchAll pat1 h1::[MatchArray]- acc1 = ReplaceAcc { acc_haystack = h0, position_adj = 0 }- in acc_haystack $ P.foldl (flip repl1) acc1 ma1---{- | call from your custom 'GroupReplacer' passed to 'replaceGroup'-- see example replacer above -}-replaceMatch::Replace_cl' a =>- PosLen -- ^ replaced- -> (a, ReplaceAcc a) -- ^ (new val, acc passed to 'GroupReplacer')- -> ReplaceAcc a -- ^ new acc-replaceMatch pl0@(_,l0) (new0, acc0) = ReplaceAcc {- acc_haystack = acc1,- position_adj = position_adj acc0 + l1 - l0- }- where pl1 = adjustPoslen pl0 acc0- prefix1 = prefix pl1 $ acc_haystack acc0- suffix1 = suffix pl1 $ acc_haystack acc0- acc1 = concat' [prefix1, new0, suffix1]- l1 = len' new0---addOpt::Match_opt a =>- Needle a -> [O.Comp] -> Needle Regex-addOpt pat1 opt1 = Needle rx1- where rx1 = makeRegexOpts opt1 [] pat1---comp::[ReplaceCase]-> [O.Comp]-comp = P.map mapFn . P.filter filterFn- where filterFn o1 = o1 `P.elem` [Utf8,Multiline]- mapFn Utf8 = O.Utf8- mapFn Multiline = O.Multiline---isUtf8::[ReplaceCase] -> Bool-isUtf8 case0 = Utf8 `P.elem` case0
− src/Regexdo/Pcre/Result.hs
@@ -1,27 +0,0 @@-module Regexdo.Pcre.Result- (poslen,- value,- oneMatchArray,- R.extract -- | 'extract' is reexport from "Text.Regex.Base.RegexLike"- ) where--import qualified Data.Array as A(elems)-import Text.Regex.Base.RegexLike as R-import Regexdo.TypeDo---poslen::Functor f =>- f MatchArray -> f [PosLen]-poslen = (A.elems <$>)----- | all matches-value::(Functor f, R.Extract a) =>- Haystack a -> f MatchArray -> f [a]-value hay0 results0 = oneMatchArray hay0 <$> results0----- | extracts all values in a MatchArray (matched group)-oneMatchArray::R.Extract a =>- Haystack a -> MatchArray -> [a]-oneMatchArray (Haystack hay1) arr1 = [R.extract tuple1 hay1 | tuple1 <- A.elems arr1]
− src/Regexdo/Search.hs
@@ -1,108 +0,0 @@-{- | wraps functions from stringsearch package-- this module uses newtypes for args plus function names are tweaked-- regex is treated as ordinary String- -}-module Regexdo.Search- (break,- breakFront,- breakEnd,- replace,- split,- splitEnd,- splitFront) where-import qualified Data.ByteString.Search as S--import Regexdo.TypeDo hiding (replace)-import Data.ByteString as B hiding (break, breakEnd, split)-import qualified Data.ByteString.Lazy as L-import Prelude hiding (break)---- ordinary: a b--- front: a \nb--- end: a\n b--{- | (front, end) : drop needle-- >>> break (Needle ":") (Haystack "0123:oid:90")-- ("0123", "oid:90")-- >>> break (Needle "\n") (Haystack "a\nbc\nde")-- ("a", "bc\\nde") -}-break::Needle ByteString -> Haystack ByteString -> (ByteString, ByteString)-break (Needle pat0) (Haystack b0) = (h1,t2)- where (h1,t1) = S.breakOn pat1 b0- len1 = B.length pat1- t2 = B.drop len1 t1- !pat1 = checkPattern pat0---{- | (front, needle + end)-- >>> breakFront (Needle "\n") (Haystack "a\nbc\nde")-- ("a", "\\nbc\\nde") -}-breakFront::Needle ByteString -> Haystack ByteString -> (ByteString, ByteString)-breakFront (Needle pat0)- (Haystack b0) = S.breakOn pat1 b0- where !pat1 = checkPattern pat0--{- | (front + needle, end)-- >>> breakEnd (Needle "\n") (Haystack "a\nbc\nde")-- ("a\\n", "bc\\nde") -}-breakEnd::Needle ByteString -> Haystack ByteString -> (ByteString, ByteString)-breakEnd (Needle pat0)- (Haystack b0) = S.breakAfter pat1 b0- where !pat1 = checkPattern pat0---{- | >>> replace (Needle "\n") (Replacement ",") (Haystack "a\nbc\nde")-- "a,bc,de" -}-replace::Needle ByteString -> Replacement ByteString -> Haystack ByteString -> ByteString-replace (Needle pat0)- (Replacement replacement)- (Haystack b0) = B.concat . L.toChunks $ l- where l = S.replace pat1 replacement b0- !pat1 = checkPattern pat0--{- | >>> split (Needle "\n") (Haystack "a\nbc\nde")-- \["a", "bc", "de"]-- >>> split (Needle " ") (Haystack "a bc de")-- \["a", "bc", "de"]-- >>> split (Needle "\\s") (Haystack "abc de fghi ")-- \["abc de fghi "] -}-split::Needle ByteString -> Haystack ByteString -> [ByteString]-split (Needle pat0)- (Haystack b0) = S.split pat1 b0- where !pat1 = checkPattern pat0--{- | >>> splitEnd (Needle "\n") (Haystack "a\nbc\nde")-- \["a\\n", "bc\\n", "de"] -}-splitEnd::Needle ByteString -> Haystack ByteString -> [ByteString]-splitEnd (Needle pat0)- (Haystack b0) = S.splitKeepEnd pat1 b0- where !pat1 = checkPattern pat0--{- | >>> splitFront (Needle "\n") (Haystack "a\nbc\nde")-- \["a", "\\nbc", "\\nde"] -}-splitFront::Needle ByteString -> Haystack ByteString -> [ByteString]-splitFront (Needle pat0)- (Haystack b0) = S.splitKeepFront pat1 b0- where !pat1 = checkPattern pat0--checkPattern::ByteString -> ByteString-checkPattern bs0 = if bs0 == B.empty then error "empty pattern"- else bs0
− src/Regexdo/Trim.hs
@@ -1,23 +0,0 @@-module Regexdo.Trim where--import Regexdo.TypeDo-import Data.Char(isSpace)-import qualified Data.ByteString as B-import Regexdo.Convert-import Regexdo.Pcre.Replace--{- | removes leading and trailing spaces and tabs -}--class Trim a where- trim::a -> a---instance Trim B.ByteString where- trim bs1 = replace [All] (rx1,repl) $ Haystack bs1- where repl = Replacement B.empty- rx1 = rxFn "(^[\\s\\t]+)|([\\s\\t]+$)"- rxFn = Needle . toByteString--instance Trim String where- trim = f . f- where f = reverse . dropWhile isSpace
− src/Regexdo/TypeDo.hs
@@ -1,28 +0,0 @@-module Regexdo.TypeDo where--import Text.Regex.Base.RegexLike---- pcre-type GroupReplacer a = (MatchArray -> ReplaceAcc a -> ReplaceAcc a) -- MatchArray -> acc -> acc---data ReplaceAcc a = ReplaceAcc {- acc_haystack::a, -- ^ wip Haystack- position_adj::Int- }----- stringsearch, Pcre.Replace-data Needle n = Needle n deriving (Functor) -- Bs, String, RegexPcre-data Haystack h = Haystack h deriving (Functor) -- Bs, String-data Replacement r = Replacement r deriving (Functor) -- Bs, String--type PosLen = (MatchOffset, MatchLength)---data ReplaceCase = Once -- ^ may be omitted- | All -- ^ if both Once and All are passed, All prevails- | Utf8- | Multiline deriving Eq--
− src/Regexdo/TypeRegex.hs
@@ -1,15 +0,0 @@--- | reexport common types from "Text.Regex.PCRE"-module Regexdo.TypeRegex (- W.Regex(..),- R.MatchArray(..),- W.CompOption(..),- W.ExecOption()- ) where--import Text.Regex.PCRE.ByteString as B (Regex)-import Text.Regex.PCRE.String as S (Regex)-import Text.Regex.Base.RegexLike as R (MatchArray)-import Text.Regex.PCRE.Wrap as W--type RegexB = B.Regex-type RegexS = S.Regex
+ src/Text/Regex/Do/Convert.hs view
@@ -0,0 +1,13 @@+module Text.Regex.Do.Convert where++import qualified Data.Text.Encoding as E+import qualified Data.Text as T+import Data.ByteString as B++-- | both Ascii and Utf8+toByteString::String -> ByteString+toByteString = E.encodeUtf8 . T.pack++-- | both Ascii and Utf8+toString::ByteString -> String+toString = T.unpack . E.decodeUtf8
+ src/Text/Regex/Do/Format.hs view
@@ -0,0 +1,72 @@+module Text.Regex.Do.Format+ (pad,+ Format(..)) where++import Prelude as P+import Text.Regex.Do.TypeDo+import Text.Regex.Do.Split as S (replace)+import Text.Regex.Do.Convert+++class Format a where+ format::String -> a -> String+++instance Format [String] where+ format = foldr_idx foldFn_idx+-- ^+-- === index based+-- >>> format "на первое {0}, на второе {0}" ["перловка"]+--+-- "на первое перловка, на второе перловка"+--+-- >>> format "Polly {0} a {1}" ["got","cracker"]+--+-- "Polly got a cracker"+--++foldFn_idx::String -> (Int, String) -> String+foldFn_idx v (i,body1) = replaceOne body1 (show i) v+++instance Format [(String,String)] where+ format = P.foldr foldFn_map+-- ^+-- === key based+-- key may be {any string}+--+-- >>> format "овчинка {a} не {b}" [("a","выделки"),("b","стоит")]+--+-- "овчинка выделки не стоит"+--++foldFn_map:: (String, String) -> String -> String+foldFn_map (k,v) body1 = replaceOne body1 k v++replaceOne::String -> String -> String -> String+replaceOne body k v = toString bs1+ where pat1 = Pattern $ toByteString $ "{" ++ k ++ "}"+ repl1 = Replacement $ toByteString v+ bs1 = S.replace pat1 repl1 $ Body $ toByteString body++-- | pad String with Char to total length of Int+--+-- >>> pad '-' 5 "abc"+-- "--abc"+--+pad::Char -> Int -> String -> String+pad c0 tot0 txt0 =+ [const c0 p1 | p1 <- [1..(tot0 - (P.length txt0))]] ++ txt0+++-- fold with index+type CustomerFn a b = (a -> (Int,b) -> b)++foldr_idx :: CustomerFn a b -> b -> [a] -> b+foldr_idx fn init1 list = b1+ where i0 = P.length list - 1+ (-1,b1) = P.foldr (foldFn fn) (i0,init1) list++foldFn :: CustomerFn a b -> a -> (Int,b) -> (Int,b)+foldFn fn val t@(i,_)= (i-1,b1)+ where b1 = fn val t
+ src/Text/Regex/Do/Pcre/Match.hs view
@@ -0,0 +1,74 @@+-- | see "Text.Regex.Base.RegexLike"+module Text.Regex.Do.Pcre.Match where++import qualified Text.Regex.Base.RegexLike as R hiding (makeRegex)+import qualified Text.Regex.Base.RegexLike as R (makeRegex)+import Text.Regex.Do.TypeDo+import Text.Regex.Do.Pcre.Option as O+import Text.Regex.Do.TypeRegex+import Data.ByteString+++{- | see "Text.Regex.Do.Pcre.Result"+ to convert 'MatchArray' to something useful+ -}++class Rx_ n h =>+ Match n h where++ matchOnce::Pattern n -> Body h -> Maybe MatchArray+ matchOnce r0 (Body b0) = R.matchOnce (r_ r0) b0++ matchTest::Pattern n -> Body h -> Bool+ matchTest r0 (Body b0) = R.matchTest (r_ r0) b0++ matchAll::Pattern n -> Body h -> [MatchArray]+ matchAll r0 (Body b0) = R.matchAll (r_ r0) b0++++-- | tweak Regex with options+makeRegexOpts::Opt_ n =>+ [O.Comp] -> [O.Exec] -> Pattern n -> Regex+makeRegexOpts comp0 exec0 (Pattern pat0) = rx1+ where c1 = O.comp comp0+ e1 = O.exec exec0+ rx1 = R.makeRegexOpts c1 e1 pat0+++{- | accepts regex 'String'++ >>> matchTest (Pattern "^ab") (Body "abc")++ True+-}+instance Match String String+-- | accepts regex 'String'+instance Match String ByteString+-- | accepts regex 'ByteString'+instance Match ByteString ByteString+-- | accepts regex 'ByteString'+instance Match ByteString String+-- | accepts 'Regex' made with 'makeRegexOpts'+instance Match Regex String+-- | accepts 'Regex' made with 'makeRegexOpts'+instance Match Regex ByteString+++++class Regex_ r where+ r_::Pattern r -> Regex+++instance Regex_ ByteString where+ r_ (Pattern r0) = R.makeRegex r0++instance Regex_ String where+ r_ (Pattern r0) = R.makeRegex r0++instance Regex_ Regex where+ r_ (Pattern r0) = r0+++type Rx_ n h = (R.Extract h, Regex_ n, R.RegexLike Regex h)
+ src/Text/Regex/Do/Pcre/Option.hs view
@@ -0,0 +1,57 @@+module Text.Regex.Do.Pcre.Option (+ Comp(..),+ Exec(..),+ comp,+ exec+ ) where++import Data.Bits+import qualified Text.Regex.PCRE.ByteString as B+++data Comp = Blank -- ^ 'B.compBlank'+ | Anchored -- ^ 'B.compAnchored'+ | Caseless -- ^ 'B.compCaseless'+ | Dotall -- ^ 'B.compDotAll'+ | Multiline -- ^ 'B.compMultiline'+ | Utf8 -- ^ 'B.compUTF8'+ | Ungreedy -- ^ 'B.compUngreedy'+ deriving Enum+++data Exec = BlankE -- ^ 'B.execBlank'+ | NotEmpty -- ^ 'B.execNotEmpty'+ | Partial -- ^ 'B.execPartial'+ deriving Enum+++compOpt::Comp -> B.CompOption+compOpt o = case o of+ Blank -> B.compBlank+ Anchored -> B.compAnchored+ Caseless -> B.compCaseless+ Dotall -> B.compDotAll+ Multiline -> B.compMultiline+ Utf8 -> B.compUTF8+ Ungreedy -> B.compUngreedy+++comp::[Comp] -> B.CompOption+comp [] = B.compBlank+comp l = foldl (.&.) o0 l1+ where l1 = compOpt <$> l+ o0 = compOpt $ head l+++execOpt::Exec -> B.ExecOption+execOpt o = case o of+ BlankE -> B.execBlank+ NotEmpty -> B.execNotEmpty+ Partial -> B.execPartial+++exec::[Exec] -> B.ExecOption+exec [] = B.execBlank+exec l = foldl (.&.) o0 l1+ where l1 = execOpt <$> l+ o0 = execOpt $ head l
+ src/Text/Regex/Do/Pcre/Replace.hs view
@@ -0,0 +1,233 @@+module Text.Regex.Do.Pcre.Replace(+ ReplaceCase(..),+ Replace(..),+ replaceMatch,+ defaultReplacer,+ getGroup,+ Mr_+ ) where+++import Data.Array as A+import Prelude as P+import Data.ByteString as B+import qualified Text.Regex.Do.Pcre.Option as O+import qualified Text.Regex.Base.RegexLike as R+import Text.Regex.Do.Convert+import Text.Regex.Do.Pcre.Match+import Text.Regex.Do.Pcre.Result+import Text.Regex.Do.TypeDo+import Text.Regex.Do.TypeRegex++++class Replace a where+ replace::Mr_ a =>+ [ReplaceCase] -> Pattern a -> Replacement a -> Body a -> a+ replace cases0 pat0 repl0 hay0 =+ if isUtf8 cases0 then utfFn2+ else fn2 (pat2 pat0,repl0) hay0+ where fn1 = if P.elem All cases0 then rall else ronce+ fn2 = if P.elem All cases0 then rall else ronce+ utfFn2 = let res1 = fn1 (pat2 $ toByteString' <$> pat0, toByteString' <$> repl0) $ toByteString' <$> hay0+ in toA res1+ pat2 pat0 = addOpt pat0 cOpt1+ cOpt1 = comp cases0+++ replaceGroup::Mr_ a =>+ [ReplaceCase] -> Pattern a -> GroupReplacer a -> Body a -> a+ replaceGroup cases0 pat0 repl0 = fn1 pat2 repl0+ where pat2 = addOpt pat0 cOpt+ cOpt = comp cases0+ fn1 = if P.elem All cases0+ then rallGroup+ else ronceGroup++{- ^+ == dynamic group replace+ custom replacer fn returns replacement value++ >>> replacer::GroupReplacer String+ replacer = defaultReplacer 1 tweak1+ where tweak1 str1 = case str1 of+ "101" -> "[сто один]"+ "3" -> "[three]"+ otherwise -> trace str1 "?"++ 'Once' vs 'All' options++ >>> replaceGroup [Once,Utf8] (Pattern "\\w=(\\d{1,3})", replacer) $ Body "a=101 b=3 12"++ "a=[сто один] b=3 12"++ >>> replaceGroup [All,Utf8] (Pattern "\\w=(\\d{1,3})", replacer) $ Body "a=101 b=3 12"++ "a=[сто один] b=[three] 12"+++ == static replace for simple (no group) needle++ >>> replace [Once,Utf8] (Pattern "менее", Replacement "более") $ Body "менее менее"++ "более менее"++ >>> replace [Once,Utf8] (Pattern "^a\\s", Replacement "A") $ Body "a bc хол.гор."++ "Abc хол.гор." -}+++instance Replace String+instance Replace B.ByteString+++class Replace_ a where+ prefix::PosLen -> a -> a+ suffix::PosLen -> a -> a+ concat'::[a] -> a+ len'::a -> Int+ toByteString'::a -> ByteString+ toA::ByteString -> a+++instance Replace_ String where+ prefix pl1 = P.take $ fst pl1+ suffix pl1 = P.drop (pos1 + len1)+ where pos1 = fst pl1+ len1 = snd pl1+ concat' = P.concat+ toByteString' = toByteString+ toA = toString+ len' = P.length++++instance Replace_ B.ByteString where+ prefix pl1 = B.take $ fst pl1+ suffix pl1 = B.drop (pos1 + len1)+ where pos1 = fst pl1+ len1 = snd pl1+ concat' = B.concat+ toByteString' = id+ toA = id+ len' = B.length+++-- static+ronce::Mr_ a =>+ (Pattern Regex, Replacement a) -> Body a -> a+ronce (pat1, Replacement repl1) h1@(Body h0) =+ let pl2 = let m1 = matchOnce pat1 h1+ in poslen m1+ in case pl2 of+ Nothing -> h0+ Just lpl1 -> firstGroup lpl1 (repl1, h0)+++rall::Mr_ a =>+ (Pattern Regex, Replacement a) -> Body a -> a+rall (pat1, Replacement repl1) h1@(Body h0) =+ let lpl1 = let m1 = matchAll pat1 h1+ in poslen m1::[[PosLen]]+ foldFn1 lpl1 acc1 = firstGroup lpl1 (repl1,acc1)+ in P.foldr foldFn1 h0 lpl1+++firstGroup::(Replace_ a) =>+ [PosLen] -> (a,a) -> a+firstGroup (pl0:_) r1@(new0,a0) = acc $ replaceMatch pl0 (new0, acc1)+ where acc1 = ReplaceAcc {+ acc = a0,+ pos_adj = 0+ }+++-- dynamic+{- | you can write a custom replacer. This is only one common use case.++ Replaces specified (by idx) group match with tweaked value. -}+defaultReplacer::(Replace_ a, R.Extract a) =>+ Int -- ^ group idx+ -> (a -> a) -- ^ (group match -> replacement) tweak+ -> GroupReplacer a+defaultReplacer idx0 tweak0 (ma0::MatchArray) acc0 = maybe acc0 fn1 mval1+ where pl1 = ma0 A.! idx0 :: (R.MatchOffset, R.MatchLength)+ mval1 = getGroup acc0 ma0 idx0+ fn1 str1 = replaceMatch pl1 (str2, acc0)+ where str2 = tweak0 str1+++{- | get group content safely++ call from your custom 'GroupReplacer' passed to 'replaceGroup'+ -}+getGroup::R.Extract a =>+ ReplaceAcc a -> MatchArray -> Int -> Maybe a+getGroup acc0 ma0 idx0 = if idx0 >= P.length ma0 then Nothing -- safety catch+ else Just val1+ where pl1 = ma0 A.! idx0 :: (R.MatchOffset, R.MatchLength)+ pl2 = adjustPoslen pl1 acc0+ val1 = extract pl2 $ acc acc0+++adjustPoslen::PosLen -> ReplaceAcc a -> PosLen+adjustPoslen (p0,l0) acc0 = (p0 + pos_adj acc0, l0)+++ronceGroup::Match Regex a =>+ Pattern Regex -> GroupReplacer a -> Body a -> a+ronceGroup pat0 repl0 h1@(Body h0) =+ let m1 = matchOnce pat0 h1::Maybe MatchArray+ in case m1 of+ Nothing -> h0+ Just ma1 -> let a1 = ReplaceAcc {+ acc = h0,+ pos_adj = 0+ }+ in acc $ repl0 ma1 a1+++rallGroup::Match Regex a =>+ Pattern Regex -> GroupReplacer a -> Body a -> a+rallGroup pat0 repl0 b1@(Body b0) =+ let ma1 = matchAll pat0 b1::[MatchArray]+ acc1 = ReplaceAcc { acc = b0, pos_adj = 0 }+ in acc $ P.foldl (flip repl0) acc1 ma1+++{- | call from your custom 'GroupReplacer' passed to 'replaceGroup'++ see example replacer above -}+replaceMatch::Replace_ a =>+ PosLen -- ^ replaceable, unadjusted+ -> (a, ReplaceAcc a) -- ^ (new val, acc passed to 'GroupReplacer')+ -> ReplaceAcc a -- ^ new acc+replaceMatch pl0@(_,l0) (new0, acc0) = ReplaceAcc {+ acc = acc1,+ pos_adj = pos_adj acc0 + l1 - l0+ }+ where pl1 = adjustPoslen pl0 acc0+ prefix1 = prefix pl1 $ acc acc0+ suffix1 = suffix pl1 $ acc acc0+ acc1 = concat' [prefix1, new0, suffix1]+ l1 = len' new0+++addOpt::Opt_ a =>+ Pattern a -> [O.Comp] -> Pattern Regex+addOpt pat0 opt0 = Pattern rx1+ where rx1 = makeRegexOpts opt0 [] pat0+++comp::[ReplaceCase]-> [O.Comp]+comp = P.map mapFn . P.filter filterFn+ where filterFn o1 = o1 `P.elem` [Utf8,Multiline]+ mapFn Utf8 = O.Utf8+ mapFn Multiline = O.Multiline+++isUtf8::[ReplaceCase] -> Bool+isUtf8 case0 = Utf8 `P.elem` case0+++type Mr_ a = (Match Regex a, Replace_ a, Opt_ a)
+ src/Text/Regex/Do/Pcre/Result.hs view
@@ -0,0 +1,27 @@+module Text.Regex.Do.Pcre.Result+ (poslen,+ allMatches,+ groupMatch,+ R.extract -- | 'extract' is reexport from "Text.Regex.Base.RegexLike"+ ) where++import qualified Data.Array as A(elems)+import Text.Regex.Base.RegexLike as R+import Text.Regex.Do.TypeDo++-- | match offset, length+poslen::Functor f =>+ f MatchArray -> f [PosLen]+poslen = (A.elems <$>)+++-- | all groups+allMatches::(Functor f, R.Extract a) =>+ Body a -> f MatchArray -> f [a]+allMatches hay0 results0 = groupMatch hay0 <$> results0+++-- | matches for one group+groupMatch::R.Extract a =>+ Body a -> MatchArray -> [a]+groupMatch (Body hay1) arr1 = [R.extract tuple1 hay1 | tuple1 <- A.elems arr1]
+ src/Text/Regex/Do/Split.hs view
@@ -0,0 +1,108 @@+{- | see "Data.ByteString.Search" package++ this module uses newtypes for args++ regex is treated as ordinary String+ -}+module Text.Regex.Do.Split+ (break,+ breakFront,+ breakEnd,+ replace,+ split,+ splitEnd,+ splitFront) where++import qualified Data.ByteString.Search as S+import Text.Regex.Do.TypeDo hiding (replace)+import Data.ByteString as B hiding (break, breakEnd, split)+import qualified Data.ByteString.Lazy as L+import Prelude hiding (break)++-- ordinary: a b+-- front: a \nb+-- end: a\n b++{- | (front, end) : drop needle++ >>> break (Pattern ":") (Body "0123:oid:90")++ ("0123", "oid:90")++ >>> break (Pattern "\n") (Body "a\nbc\nde")++ ("a", "bc\\nde") -}+break::Pattern ByteString -> Body ByteString -> (ByteString, ByteString)+break (Pattern pat0) (Body b0) = (h1,t2)+ where (h1,t1) = S.breakOn pat1 b0+ len1 = B.length pat1+ t2 = B.drop len1 t1+ !pat1 = checkPattern pat0+++{- | (front, needle + end)++ >>> breakFront (Pattern "\n") (Body "a\nbc\nde")++ ("a", "\\nbc\\nde") -}+breakFront::Pattern ByteString -> Body ByteString -> (ByteString, ByteString)+breakFront (Pattern pat0)+ (Body b0) = S.breakOn pat1 b0+ where !pat1 = checkPattern pat0++{- | (front + needle, end)++ >>> breakEnd (Pattern "\n") (Body "a\nbc\nde")++ ("a\\n", "bc\\nde") -}+breakEnd::Pattern ByteString -> Body ByteString -> (ByteString, ByteString)+breakEnd (Pattern pat0)+ (Body b0) = S.breakAfter pat1 b0+ where !pat1 = checkPattern pat0+++{- | >>> replace (Pattern "\n") (Replacement ",") (Body "a\nbc\nde")++ "a,bc,de" -}+replace::Pattern ByteString -> Replacement ByteString -> Body ByteString -> ByteString+replace (Pattern pat0)+ (Replacement replacement)+ (Body b0) = B.concat . L.toChunks $ l+ where l = S.replace pat1 replacement b0+ !pat1 = checkPattern pat0++{- | >>> split (Pattern "\n") (Body "a\nbc\nde")++ \["a", "bc", "de"]++ >>> split (Pattern " ") (Body "a bc de")++ \["a", "bc", "de"]++ >>> split (Pattern "\\s") (Body "abc de fghi ")++ \["abc de fghi "] -}+split::Pattern ByteString -> Body ByteString -> [ByteString]+split (Pattern pat0)+ (Body b0) = S.split pat1 b0+ where !pat1 = checkPattern pat0++{- | >>> splitEnd (Pattern "\n") (Body "a\nbc\nde")++ \["a\\n", "bc\\n", "de"] -}+splitEnd::Pattern ByteString -> Body ByteString -> [ByteString]+splitEnd (Pattern pat0)+ (Body b0) = S.splitKeepEnd pat1 b0+ where !pat1 = checkPattern pat0++{- | >>> splitFront (Pattern "\n") (Body "a\nbc\nde")++ \["a", "\\nbc", "\\nde"] -}+splitFront::Pattern ByteString -> Body ByteString -> [ByteString]+splitFront (Pattern pat0)+ (Body b0) = S.splitKeepFront pat1 b0+ where !pat1 = checkPattern pat0++checkPattern::ByteString -> ByteString+checkPattern bs0 = if bs0 == B.empty then error "empty pattern"+ else bs0
+ src/Text/Regex/Do/Trim.hs view
@@ -0,0 +1,23 @@+module Text.Regex.Do.Trim where++import Text.Regex.Do.TypeDo+import Data.Char(isSpace)+import qualified Data.ByteString as B+import Text.Regex.Do.Convert+import Text.Regex.Do.Pcre.Replace++{- | removes leading and trailing spaces and tabs -}++class Trim a where+ trim::a -> a+++instance Trim B.ByteString where+ trim bs1 = replace [All] rx1 repl1 $ Body bs1+ where repl1 = Replacement B.empty+ rx1 = rxFn "(^[\\s\\t]+)|([\\s\\t]+$)"+ rxFn = Pattern . toByteString++instance Trim String where+ trim = f . f+ where f = reverse . dropWhile isSpace
+ src/Text/Regex/Do/TypeDo.hs view
@@ -0,0 +1,36 @@+module Text.Regex.Do.TypeDo where++import Text.Regex.Base.RegexLike as R+import Text.Regex.Do.TypeRegex+++-- pcre+type GroupReplacer a = (MatchArray -> ReplaceAcc a -> ReplaceAcc a) -- MatchArray -> acc -> acc+++data ReplaceAcc a = ReplaceAcc {+ acc::a, -- ^ Body with some replacements made+ pos_adj::Int {- ^ position adjustment: group replacement length may differ from replaced text length -}+ }+++-- | Needle+data Pattern n = Pattern n deriving (Functor) -- Bs, String, RegexPcre++-- | Haystack+data Body h = Body h deriving (Functor) -- Bs, String++data Replacement r = Replacement r deriving (Functor) -- Bs, String++-- | Offset, Length+type PosLen = (MatchOffset, MatchLength)+++data ReplaceCase = Once -- ^ may be omitted+ | All -- ^ if both Once and All are passed, All prevails+ | Utf8+ | Multiline deriving Eq++++type Opt_ n = R.RegexMaker Regex CompOption ExecOption n
+ src/Text/Regex/Do/TypeRegex.hs view
@@ -0,0 +1,15 @@+-- | reexport common types from "Text.Regex.PCRE"+module Text.Regex.Do.TypeRegex (+ W.Regex(..),+ R.MatchArray(..),+ W.CompOption(..),+ W.ExecOption()+ ) where++import Text.Regex.PCRE.ByteString as B (Regex)+import Text.Regex.PCRE.String as S (Regex)+import Text.Regex.Base.RegexLike as R (MatchArray)+import Text.Regex.PCRE.Wrap as W++type RegexB = B.Regex+type RegexS = S.Regex
test/Main.hs view
@@ -1,9 +1,9 @@ module Main where -import qualified TestRegex.Format as F-import qualified TestRegex.Pcre as P-import qualified TestRegex.Replace as R-import qualified TestRegex.StringSearch as S+import qualified TestRegex.TestFormat as F+import qualified TestRegex.TestPcre as P+import qualified TestRegex.TestReplace as R+import qualified TestRegex.TestSplit as S import qualified TestRegex.TestTrim as T
− test/TestRegex/Format.hs
@@ -1,20 +0,0 @@-{-# LANGUAGE NoOverloadedStrings #-}-module TestRegex.Format where--import Test.Hspec-import Regexdo.Format---main::IO()-main = hspec $ do- describe "Habase.Bin.Format" $ do- it "list arg 0,0 repl []" $ do- format "на первое {0}, на второе {0}" ([]::[String]) `shouldBe` "на первое {0}, на второе {0}"- it "list arg 0,0" $ do- format "на первое {0}, на второе {0}" ["перловка"] `shouldBe` "на первое перловка, на второе перловка"- it "list arg 0,1" $ do- format "Polly {0} a {1}" ["gets","cracker"] `shouldBe` "Polly gets a cracker"- it "map arg" $ do- format "овчинка {a} не {b}" [("a","выделки"),("b","стоит")] `shouldBe` "овчинка выделки не стоит"- it "pad" $ do- pad '-' 5 "abc" `shouldBe` "--abc"
− test/TestRegex/Pcre.hs
@@ -1,60 +0,0 @@-{-# LANGUAGE FlexibleContexts, NoOverloadedStrings #-}-module TestRegex.Pcre where--import Test.Hspec-import Regexdo.TypeDo-import Regexdo.Pcre.Match as M-import qualified Regexdo.Pcre.Result as R-import Regexdo.Convert----main::IO()-main = do- test " ?String " Needle id M.match- test " [String] " Needle id M.matchAll- test " ?Bs " (Needle . b) (b <$>) M.match- test " [Bs] " (Needle . b) (b <$>) M.matchAll- hspec $ do- describe " matchTest " $ do- it " matchTest " $ do- M.matchTest (Needle "^ша") (Haystack "шапка") `shouldBe` True- M.matchTest (Needle "^cd") (Haystack "abcde") `shouldBe` False- M.matchTest (Needle "^ab") (Haystack "abc") `shouldBe` True--n = "d1"-h = Haystack "abcd1efg d1hij"-b = toByteString---test testCase patternCtor bodyCtor matchFn = hspec $ do- describe testCase $ do- it " val " $ do- R.value h res `shouldSatisfy` check- it " tup " $- R.poslen res `shouldSatisfy` check- it " pl " $- R.poslen res `shouldSatisfy` check- where res = matchFn pat $ bodyCtor h- pat = patternCtor n----class Functor f => Pred f x where- check::f x -> Bool--instance Pred Maybe [String] where- check Nothing = False- check (Just _) = True--instance Pred [] [String] where- check [] = False- check (h:t) = True--instance Pred Maybe [PosLen] where- check Nothing = False- check (Just _) = True--instance Pred [] [PosLen] where- check [] = False- check (h:t) = True
− test/TestRegex/Replace.hs
@@ -1,88 +0,0 @@-{-# LANGUAGE BangPatterns, NoOverloadedStrings #-}-module TestRegex.Replace where--import Test.Hspec-import Regexdo.TypeDo--import Regexdo.Pcre.Replace-import Regexdo.Convert-import Data.ByteString as B-import Debug.Trace---main::IO()-main = do- onceUtf8- latinOnceAll- groupReplace- doc---doc::IO()-doc = hspec $ do- describe "Pcre.Replace doc" $ do- it "replaceGroup 1" $ do- replaceGroup [Once,Utf8] (Needle "\\w=(\\d{1,3})", replacer) (Haystack "a=101 b=3 12")- `shouldBe` "a=[сто один] b=3 12"- it "replaceGroup 2" $ do- replaceGroup [All,Utf8] (Needle "\\w=(\\d{1,3})", replacer) (Haystack "a=101 b=3 12")- `shouldBe` "a=[сто один] b=[three] 12"- it "replace 3" $ do- replace [Once,Utf8] (Needle "менее", Replacement "более") (Haystack "менее менее")- `shouldBe` "более менее"- it "replace 4" $ do- replace [Once,Utf8] (Needle "^a\\s", Replacement "A") (Haystack "a bc хол.гор.")- `shouldBe` "Abc хол.гор."---onceUtf8::IO()-onceUtf8 = hspec $ do- describe "Pcre.Replace Once Utf8" $ do- it "^a\\s" $ do- replace [Once,Utf8] (Needle "^a\\s", Replacement "A") (Haystack "a bc хол.гор.") `shouldBe` "Abc хол.гор."- it "^b\\s" $ do- replace [Once,Utf8] (Needle "^b\\s", Replacement "A") (Haystack "a bc хол.гор.") `shouldBe` "a bc хол.гор."---latinOnceAll::IO()-latinOnceAll = hspec $ do- describe "Pcre.Replace" $ do- it "Once" $ do- runFn [Once] `shouldBe` toByteString "a=R1 b=11 12"- it "All" $ do- runFn [All] `shouldBe` toByteString "a=R1 b=R1 12"- where runFn opts =- let rx1 = pattern "(?<==)(\\d{2})"- body = Haystack $ toByteString haystack- haystack = "a=10 b=11 12"- repl1 = replacement "R1"- in replace opts (rx1,repl1) body---pattern::String -> Needle ByteString-pattern = Needle . toByteString---replacement::String -> Replacement ByteString-replacement = Replacement . toByteString---groupReplace::IO()-groupReplace = hspec $ do- describe "Pcre.Replace group" $ do- it "Once" $ do- runFn1 [Once,Utf8] `shouldBe` "a=[сто один] b=3 12"- it "All" $ do- runFn1 [All,Utf8] `shouldBe` "a=[сто один] b=[three] 12"- where runFn1 opts1 =- let rx1 = Needle "\\w=(\\d{1,3})"- body1 = Haystack "a=101 b=3 12"- in replaceGroup opts1 (rx1,replacer) body1---replacer::GroupReplacer String-replacer = defaultReplacer 1 tweak1- where tweak1 str1 = case str1 of- "101" -> "[сто один]"- "3" -> "[three]"- otherwise -> trace str1 "?"
− test/TestRegex/StringSearch.hs
@@ -1,74 +0,0 @@-module TestRegex.StringSearch where--import Prelude hiding(break)-import Test.Hspec-import Control.Exception (evaluate)-import Regexdo.TypeDo-import Regexdo.Search as S-import qualified Data.ByteString as B-import Regexdo.Convert---main::IO()-main = hspec $ do- describe "Habase.Regex.StringSearch.Search" $ do- it "break :" $ do- break (Needle ":") (Haystack "0123:oid:90") `shouldBe` ("0123", "oid:90")- it "break" $ do- break (Needle "\n") (Haystack "a\nbc\nde") `shouldBe` ("a", "bc\nde")- it "break front" $ do- breakFront (Needle "\n") (Haystack "a\nbc\nde") `shouldBe` ("a", "\nbc\nde")- it "break end" $ do- breakEnd (Needle "\n") (Haystack "a\nbc\nde") `shouldBe` ("a\n", "bc\nde")- it "replace" $ do- S.replace (Needle "\n") (Replacement ",") (Haystack "a\nbc\nde") `shouldBe` "a,bc,de"- it "split" $ do- split (Needle "\n") (Haystack "a\nbc\nde") `shouldBe` ["a", "bc", "de"]- it "split_sp" $ do- split (Needle " ") (Haystack "a bc de") `shouldBe` ["a", "bc", "de"]- it "split end" $ do- splitEnd (Needle "\n") (Haystack "a\nbc\nde") `shouldBe` ["a\n", "bc\n", "de"]- it "split front" $ do- splitFront (Needle "\n") (Haystack "a\nbc\nde") `shouldBe` ["a", "\nbc", "\nde"]- it "split regex" $ do- split (Needle "\\s") (Haystack "abc de fghi ") `shouldBe` ["abc de fghi "]--- describe "StringSearch.Search zerolength" $ do- it "break" $ do- evaluate (errFn break) `shouldThrow` anyException- it "break front" $ do- evaluate (errFn breakFront) `shouldThrow` anyException- it "break end" $ do- evaluate (errFn breakEnd) `shouldThrow` anyException- it "replace" $ do- evaluate (S.replace (Needle B.empty) with body) `shouldThrow` anyException- it "split" $ do- evaluate (errFn split) `shouldThrow` anyException- it "split end" $ do- evaluate (errFn splitEnd) `shouldThrow` anyException- it "split front" $ do- evaluate (errFn splitFront) `shouldThrow` anyException-- describe "StringSearch.Search break delim not found" $ do- it "delim not found" $ do- break_nf `shouldBe` ( b "a\nbc\nde", B.empty)-- where pat = Needle "\n"- pat_sp = Needle " "- body = Haystack "a\nbc\nde"- body_sp = Haystack "a bc de"- with = Replacement ","- break1 = break pat body- breakFront1 = breakFront pat body- breakEnd1 = breakEnd pat body- replace1 = S.replace pat with body- split1 = split pat body- split_sp1 = split pat_sp body_sp- splitFront1 = splitFront pat body- splitEnd1 = splitEnd pat body- errFn fn1 = fn1 (Needle B.empty) body- b = toByteString- -- break delim not found- pat_nf = Needle ":"- break_nf = break pat_nf body
+ test/TestRegex/TestFormat.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE NoOverloadedStrings #-}+module TestRegex.TestFormat where++import Test.Hspec+import Text.Regex.Do.Format+++main::IO()+main = hspec $ do+ describe "Habase.Bin.Format" $ do+ it "list arg 0,0 repl []" $ do+ format "на первое {0}, на второе {0}" ([]::[String]) `shouldBe` "на первое {0}, на второе {0}"+ it "list arg 0,0" $ do+ format "на первое {0}, на второе {0}" ["перловка"] `shouldBe` "на первое перловка, на второе перловка"+ it "list arg 0,1" $ do+ format "Polly {0} a {1}" ["gets","cracker"] `shouldBe` "Polly gets a cracker"+ it "map arg" $ do+ format "овчинка {a} не {b}" [("a","выделки"),("b","стоит")] `shouldBe` "овчинка выделки не стоит"+ it "pad" $+ pad '-' 5 "abc" `shouldBe` "--abc"+ it "pad" $+ pad '-' 3 "abcde" `shouldBe` "abcde"
+ test/TestRegex/TestPcre.hs view
@@ -0,0 +1,60 @@+{-# LANGUAGE FlexibleContexts, NoOverloadedStrings #-}+module TestRegex.TestPcre where++import Test.Hspec+import Text.Regex.Do.TypeDo as M+import Text.Regex.Do.Pcre.Match as M+import qualified Text.Regex.Do.Pcre.Result as R+import Text.Regex.Do.Convert++++main::IO()+main = do+ test " ?String " Pattern id M.matchOnce+ test " [String] " Pattern id M.matchAll+ test " ?Bs " (Pattern . b) (b <$>) M.matchOnce+ test " [Bs] " (Pattern . b) (b <$>) M.matchAll+ hspec $ do+ describe " matchTest " $ do+ it " matchTest " $ do+ M.matchTest (Pattern "^ша") (Body "шапка") `shouldBe` True+ M.matchTest (Pattern "^cd") (Body "abcde") `shouldBe` False+ M.matchTest (Pattern "^ab") (Body "abc") `shouldBe` True++n = "d1"+h = Body "abcd1efg d1hij"+b = toByteString+++test testCase patternCtor bodyCtor matchFn = hspec $ do+ describe testCase $ do+ it " val " $ do+ R.allMatches h res `shouldSatisfy` check+ it " tup " $+ R.poslen res `shouldSatisfy` check+ it " pl " $+ R.poslen res `shouldSatisfy` check+ where res = matchFn pat $ bodyCtor h+ pat = patternCtor n++++class Functor f => Pred f x where+ check::f x -> Bool++instance Pred Maybe [String] where+ check Nothing = False+ check (Just _) = True++instance Pred [] [String] where+ check [] = False+ check (h:t) = True++instance Pred Maybe [PosLen] where+ check Nothing = False+ check (Just _) = True++instance Pred [] [PosLen] where+ check [] = False+ check (h:t) = True
+ test/TestRegex/TestReplace.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE BangPatterns, NoOverloadedStrings #-}+module TestRegex.TestReplace where++import Test.Hspec+import Text.Regex.Do.TypeDo++import Text.Regex.Do.Pcre.Replace+import Text.Regex.Do.Convert+import Data.ByteString as B+import Debug.Trace+++main::IO()+main = do+ onceUtf8+ latinOnceAll+ groupReplace+ doc+++doc::IO()+doc = hspec $ do+ describe "Pcre.Replace doc" $ do+ it "replaceGroup 1" $ do+ replaceGroup [Once,Utf8] (Pattern "\\w=(\\d{1,3})") replacer (Body "a=101 b=3 12")+ `shouldBe` "a=[сто один] b=3 12"+ it "replaceGroup 2" $ do+ replaceGroup [All,Utf8] (Pattern "\\w=(\\d{1,3})") replacer (Body "a=101 b=3 12")+ `shouldBe` "a=[сто один] b=[three] 12"+ it "replace 3" $ do+ replace [Once,Utf8] (Pattern "менее") (Replacement "более") (Body "менее менее")+ `shouldBe` "более менее"+ it "replace 4" $ do+ replace [Once,Utf8] (Pattern "^a\\s") (Replacement "A") (Body "a bc хол.гор.")+ `shouldBe` "Abc хол.гор."+++onceUtf8::IO()+onceUtf8 = hspec $ do+ describe "Pcre.Replace Once Utf8" $ do+ it "^a\\s" $ do+ replace [Once,Utf8] (Pattern "^a\\s") (Replacement "A") (Body "a bc хол.гор.") `shouldBe` "Abc хол.гор."+ it "^b\\s" $ do+ replace [Once,Utf8] (Pattern "^b\\s") (Replacement "A") (Body "a bc хол.гор.") `shouldBe` "a bc хол.гор."+++latinOnceAll::IO()+latinOnceAll = hspec $ do+ describe "Pcre.Replace" $ do+ it "Once" $ do+ runFn [Once] `shouldBe` toByteString "a=text1 b=11 12"+ it "All" $ do+ runFn [All] `shouldBe` toByteString "a=text1 b=text1 12"+ where runFn opts =+ let rx1 = pattern "(?<==)(\\d{2})"+ body1 = Body $ toByteString haystack1+ haystack1 = "a=10 b=11 12"+ repl1 = replacement "text1"+ in replace opts rx1 repl1 body1+++pattern::String -> Pattern ByteString+pattern = Pattern . toByteString+++replacement::String -> Replacement ByteString+replacement = Replacement . toByteString+++groupReplace::IO()+groupReplace = hspec $ do+ describe "Pcre.Replace group" $ do+ it "Once" $ do+ runFn1 [Once,Utf8] `shouldBe` "a=[сто один] b=3 12"+ it "All" $ do+ runFn1 [All,Utf8] `shouldBe` "a=[сто один] b=[three] 12"+ where runFn1 opts1 =+ let rx1 = Pattern "\\w=(\\d{1,3})"+ body1 = Body "a=101 b=3 12"+ in replaceGroup opts1 rx1 replacer body1+++replacer::GroupReplacer String+replacer = defaultReplacer 1 tweak1+ where tweak1 str1 = case str1 of+ "101" -> "[сто один]"+ "3" -> "[three]"+ otherwise -> trace str1 "?"
+ test/TestRegex/TestSplit.hs view
@@ -0,0 +1,74 @@+module TestRegex.TestSplit where++import Prelude hiding(break)+import Test.Hspec+import Control.Exception (evaluate)+import Text.Regex.Do.TypeDo+import Text.Regex.Do.Split as S+import qualified Data.ByteString as B+import Text.Regex.Do.Convert+++main::IO()+main = hspec $ do+ describe "Habase.Regex.StringSearch.Search" $ do+ it "break :" $ do+ break (Pattern ":") (Body "0123:oid:90") `shouldBe` ("0123", "oid:90")+ it "break" $ do+ break (Pattern "\n") (Body "a\nbc\nde") `shouldBe` ("a", "bc\nde")+ it "break front" $ do+ breakFront (Pattern "\n") (Body "a\nbc\nde") `shouldBe` ("a", "\nbc\nde")+ it "break end" $ do+ breakEnd (Pattern "\n") (Body "a\nbc\nde") `shouldBe` ("a\n", "bc\nde")+ it "replace" $ do+ S.replace (Pattern "\n") (Replacement ",") (Body "a\nbc\nde") `shouldBe` "a,bc,de"+ it "split" $ do+ split (Pattern "\n") (Body "a\nbc\nde") `shouldBe` ["a", "bc", "de"]+ it "split_sp" $ do+ split (Pattern " ") (Body "a bc de") `shouldBe` ["a", "bc", "de"]+ it "split end" $ do+ splitEnd (Pattern "\n") (Body "a\nbc\nde") `shouldBe` ["a\n", "bc\n", "de"]+ it "split front" $ do+ splitFront (Pattern "\n") (Body "a\nbc\nde") `shouldBe` ["a", "\nbc", "\nde"]+ it "split regex" $ do+ split (Pattern "\\s") (Body "abc de fghi ") `shouldBe` ["abc de fghi "]+++ describe "StringSearch.Search zerolength" $ do+ it "break" $ do+ evaluate (errFn break) `shouldThrow` anyException+ it "break front" $ do+ evaluate (errFn breakFront) `shouldThrow` anyException+ it "break end" $ do+ evaluate (errFn breakEnd) `shouldThrow` anyException+ it "replace" $ do+ evaluate (S.replace (Pattern B.empty) with body) `shouldThrow` anyException+ it "split" $ do+ evaluate (errFn split) `shouldThrow` anyException+ it "split end" $ do+ evaluate (errFn splitEnd) `shouldThrow` anyException+ it "split front" $ do+ evaluate (errFn splitFront) `shouldThrow` anyException++ describe "StringSearch.Search break delim not found" $ do+ it "delim not found" $ do+ break_nf `shouldBe` ( b "a\nbc\nde", B.empty)++ where pat = Pattern "\n"+ pat_sp = Pattern " "+ body = Body "a\nbc\nde"+ body_sp = Body "a bc de"+ with = Replacement ","+ break1 = break pat body+ breakFront1 = breakFront pat body+ breakEnd1 = breakEnd pat body+ replace1 = S.replace pat with body+ split1 = split pat body+ split_sp1 = split pat_sp body_sp+ splitFront1 = splitFront pat body+ splitEnd1 = splitEnd pat body+ errFn fn1 = fn1 (Pattern B.empty) body+ b = toByteString+ -- break delim not found+ pat_nf = Pattern ":"+ break_nf = break pat_nf body
test/TestRegex/TestTrim.hs view
@@ -4,8 +4,8 @@ import Test.Hspec import Debug.Trace import qualified Data.Text as T (strip, pack, unpack)-import Regexdo.Trim-import Regexdo.Convert+import Text.Regex.Do.Trim+import Text.Regex.Do.Convert main::IO()