packages feed

regex-do 1.3 → 1.4

raw patch · 31 files changed

+924/−920 lines, 31 files

Files

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()