regex-do (empty) → 1.0
raw patch · 19 files changed
+977/−0 lines, 19 filesdep +QuickCheckdep +arraydep +basesetup-changed
Dependencies added: QuickCheck, array, base, bytestring, hspec, regex-base, regex-do, regex-pcre, stringsearch, text
Files
- PublicDomain +24/−0
- Setup.hs +3/−0
- regex-do.cabal +80/−0
- src/Regexdo/Convert.hs +13/−0
- src/Regexdo/Format.hs +72/−0
- src/Regexdo/Pcre/Match.hs +76/−0
- src/Regexdo/Pcre/Option.hs +57/−0
- src/Regexdo/Pcre/Replace.hs +195/−0
- src/Regexdo/Pcre/Result.hs +27/−0
- src/Regexdo/Search.hs +108/−0
- src/Regexdo/Trim.hs +24/−0
- src/Regexdo/TypeDo.hs +15/−0
- src/Regexdo/TypeRegex.hs +15/−0
- test/Main.hs +17/−0
- test/TestRegex/Format.hs +18/−0
- test/TestRegex/Pcre.hs +59/−0
- test/TestRegex/Replace.hs +82/−0
- test/TestRegex/StringSearch.hs +74/−0
- test/TestRegex/TestTrim.hs +18/−0
+ PublicDomain view
@@ -0,0 +1,24 @@+This is free and unencumbered software released into the public domain.++Anyone is free to copy, modify, publish, use, compile, sell, or+distribute this software, either in source code form or as a compiled+binary, for any purpose, commercial or non-commercial, and by any+means.++In jurisdictions that recognize copyright laws, the author or authors+of this software dedicate any and all copyright interest in the+software to the public domain. We make this dedication for the benefit+of the public at large and to the detriment of our heirs and+successors. We intend this dedication to be an overt act of+relinquishment in perpetuity of all present and future rights to this+software under copyright law.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR+OTHER DEALINGS IN THE SOFTWARE.++For more information, please refer to <http://unlicense.org>
+ Setup.hs view
@@ -0,0 +1,3 @@+import Distribution.Simple++main = defaultMain
+ regex-do.cabal view
@@ -0,0 +1,80 @@+name: regex-do+version: 1.0+synopsis: PCRE regex funs+description: Convenience functions to search, replace, format String | ByteString with PCRE regex+author: Imants Cekusins+maintainer: Imants Cekusins+category: Regex, Search, String+license: PublicDomain+license-file: PublicDomain+cabal-version: >=1.10+build-type: Simple+homepage: https://github.com/ciez/regex-do++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++ ghc-options: -fwarn-unused-imports+ + build-depends: base >=4.8 && <4.9,+ regex-base >= 0.93.2,+ regex-pcre >= 0.94.4,+ stringsearch >= 0.3.6.6,+ bytestring >= 0.10.6.0,+ array >= 0.5.1.0,+ text+++ hs-source-dirs: src+ default-language: Haskell2010+ default-extensions: FlexibleInstances+ MultiParamTypeClasses+ BangPatterns+ InstanceSigs+ OverloadedStrings+ FlexibleContexts+ ConstraintKinds+ ++test-suite spec+ default-language:Haskell2010+ type: exitcode-stdio-1.0+ ghc-options: -fwarn-unused-imports+ hs-source-dirs: test, src+ default-extensions: FlexibleInstances+ MultiParamTypeClasses+ BangPatterns+ InstanceSigs+ OverloadedStrings+ FlexibleContexts+ ConstraintKinds+++ main-is: Main.hs+ other-modules:+ TestRegex.Format+ TestRegex.Pcre+ TestRegex.Replace+ TestRegex.StringSearch+ TestRegex.TestTrim++ build-depends: base >= 4.8,+ hspec >= 2.1.7,+ QuickCheck >= 2.8.1,+ regex-base >= 0.93.2,+ regex-pcre >= 0.94.4,+ stringsearch >= 0.3.6.6,+ bytestring >= 0.10.6.0,+ array >= 0.5.1.0,+ text,+ regex-do
+ src/Regexdo/Convert.hs view
@@ -0,0 +1,13 @@+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 view
@@ -0,0 +1,72 @@+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 view
@@ -0,0 +1,76 @@+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 occurence - 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+-- | this instance accepts regex 'String'+instance Match_cl String ByteString+-- | this instance accepts regex 'ByteString'+instance Match_cl ByteString ByteString+-- | this instance accepts regex 'ByteString'+instance Match_cl ByteString String+-- | this instance accepts 'Regex' made with 'makeRegexOpts'+instance Match_cl Regex String+-- | this instance accepts 'Regex' made with 'makeRegexOpts'+instance Match_cl Regex ByteString+++class Needle_ r where+ r_::Needle r -> Regex++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
+ src/Regexdo/Pcre/Option.hs view
@@ -0,0 +1,57 @@+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 view
@@ -0,0 +1,195 @@+module Regexdo.Pcre.Replace(+ ReplaceCase(..),+ Replace_cl(..),+ replaceGroup,+ replaceMatch+ ) where++import qualified Data.ByteString as B+import qualified Text.Regex.Base.RegexLike as R++import Regexdo.TypeDo+import Regexdo.TypeRegex+import Regexdo.Pcre.Match+import Regexdo.Pcre.Result+import qualified Regexdo.Pcre.Option as O+import Regexdo.Convert++data ReplaceCase = Once | All | Utf8 | Multiline deriving Eq++type Mm a = (Match_cl Regex a, Match_opt a)+type Rm a = (Replace_cl' a, Match_cl Regex a)+++addOpt::Match_opt a =>+ Needle a -> [O.Comp] -> Needle Regex+addOpt pat1 opt1 = Needle rx1+ where rx1 = makeRegexOpts opt1 [] pat1++++ronce::Rm a =>+ (Needle Regex, Replacement a) -> Haystack a -> a+ronce (pat1, Replacement repl1) body1@(Haystack bs_str1) =+ let pl2 = do+ let m1 = match pat1 body1+ poslen m1+ in case pl2 of+ Nothing -> bs_str1+ Just pl_arr -> firstGroup pl_arr (repl1,bs_str1)+++rall::Rm a =>+ (Needle Regex, Replacement a) -> Haystack a -> a+rall (pat1, Replacement repl1) body1@(Haystack bs_str1) =+ let pl_arr_arr1 = do+ let m1 = matchAll pat1 body1+ poslen m1+ folderFn pl_arr acc1 = firstGroup pl_arr (repl1,acc1)+ in foldr folderFn bs_str1 pl_arr_arr1++++firstGroup::Replace_cl' a =>+ [PosLen] -> (a,a) -> a+firstGroup (pl1:_) r1@(repl1,bs_str1) = replaceMatch pl1 r1+++-- | use in your custom 'GroupReplacer' passed to 'replaceGroup'+--+-- see example replacer above+--+replaceMatch::Replace_cl' a =>+ (R.MatchOffset, R.MatchLength) ->+ (a, a) -- ^ (new val, acc passed to 'GroupReplacer')+ -> a+replaceMatch pl1 (repl1, bs_str1) =+ concat' [prefix1,repl1,suffix1]+ where prefix1 = prefix pl1 bs_str1+ suffix1 = suffix pl1 bs_str1+++{- | == dynamic group replace+ custom replacer fn returns replacement value++ >>> replacer::GroupReplacer String+ replacer marr1 acc1 = case val1 of+ "101" -> fn1 "[A]"+ "3" -> fn1 "[Be]"+ where ol1 = marr1 ! 3 :: (MatchOffset, MatchLength)+ val1 = extract ol1 acc1+ fn1 str1 = replaceMatch ol1 (str1,acc1)++ see 'extract'++ below test compares 'Once' vs 'All' options++ >>> groupReplace::IO()+ groupReplace = hspec $ do+ describe "Pcre.Replace group" $ do+ it "Once" $ do+ runFn1 [Once] `shouldBe` "a=[A] b=3 12"+ it "All" $ do+ runFn1 [All] `shouldBe` "a=[A] b=[Be] 12"+ where runFn1 opts1 =+ let rx1 = Needle "(\\w)(=)(\\d{1,3})"+ body1 = Haystack "a=101 b=3 12"+ in replaceGroup opts1 (rx1,replacer) body1+-}+replaceGroup::Mm 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 elem All cases+ then rallGroup+ else ronceGroup+++ronceGroup::Match_cl Regex a =>+ (Needle Regex, GroupReplacer a) -> Haystack a -> a+ronceGroup (pat1, repl1) body1@(Haystack bs_str1) =+ let m1 = match pat1 body1+ in case m1 of+ Nothing -> bs_str1+ Just marr1 -> repl1 marr1 bs_str1+++rallGroup::Match_cl Regex a =>+ (Needle Regex, GroupReplacer a) -> Haystack a -> a+rallGroup (pat1, repl1) body1@(Haystack bs_str1) =+ let marrList1 = matchAll pat1 body1+ in foldr repl1 bs_str1 marrList1++++class Replace_cl a where+ replace::[ReplaceCase] -> (Needle a, Replacement a) -> Haystack a -> a+++class Replace_cl' a where+ prefix::PosLen -> a -> a+ suffix::PosLen -> a -> a+ concat'::[a] -> a+++{- |+ >>> replace [Once,Utf8] (Needle "поп", Replacement "крестьянин") (Haystack "у попа была собака")++ "у крестьянина была собака"++ >>> replace [Once,Utf8] (Needle "^a\\s", Replacement "A") (Haystack "a bc хол.гор.")++ "Abc хол.гор."++ -}++instance Replace_cl String where+ replace::[ReplaceCase] -> (Needle String, Replacement String) -> Haystack String -> String+ replace cases0 (pat1,repl1) hay0 = if isUtf8 cases0 then+ let res1 = fn1 (pat2 $ toByteString <$> pat1, toByteString <$> repl1) $ toByteString <$> hay0+ in toString res1+ else fn2 (pat2 pat1,repl1) hay0+ where pat2 pat1 = addOpt pat1 cOpt+ cOpt = comp cases0+ fn1 = if elem All cases0 then rall else ronce+ fn2 = if elem All cases0 then rall else ronce+++instance Replace_cl' String where+ prefix pl1 = take $ fst pl1+ suffix pl1 = drop (pos1 + len1)+ where pos1 = fst pl1+ len1 = snd pl1+ concat' = concat++++instance Replace_cl B.ByteString where+ replace::[ReplaceCase] -> (Needle B.ByteString, Replacement B.ByteString) ->+ Haystack B.ByteString -> B.ByteString+ replace cases0 (pat1,repl1) hay0 = fn1 (pat2,repl1) hay0+ where pat2 = addOpt pat1 cOpt+ cOpt = comp cases0+ fn1 = if elem All cases0+ then rall+ else ronce+++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+++comp::[ReplaceCase]-> [O.Comp]+comp = map mapFn . filter filterFn+ where filterFn o1 = o1 `elem` [Utf8,Multiline]+ mapFn Utf8 = O.Utf8+ mapFn Multiline = O.Multiline+++isUtf8::[ReplaceCase] -> Bool+isUtf8 case0 = Utf8 `elem` case0
+ src/Regexdo/Pcre/Result.hs view
@@ -0,0 +1,27 @@+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 view
@@ -0,0 +1,108 @@+{- | from stringsearch package++ this module uses newtypes for args plus function names are tweaked++ regex is treated as ordinary String. Do not use regex.+ -}+module Regexdo.Search+ (break,+ breakFront,+ breakEnd,+ replace,+ split,+ splitEnd,+ splitFront) where+import qualified Data.ByteString.Search as S++import Regexdo.TypeDo+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++{- | lose 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 view
@@ -0,0 +1,24 @@+module Regexdo.Trim where++import Regexdo.Pcre.Replace(replace,ReplaceCase(All))+import Regexdo.TypeDo+import Data.Char(isSpace)+import qualified Data.ByteString as B+import Regexdo.Convert+++{- | 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 view
@@ -0,0 +1,15 @@+{-# LANGUAGE DeriveFunctor #-}+module Regexdo.TypeDo where++import Text.Regex.Base.RegexLike++-- pcre+type GroupReplacer acc = (MatchArray -> acc -> acc) -- MatchArray -> acc -> acc+++-- 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)
+ src/Regexdo/TypeRegex.hs view
@@ -0,0 +1,15 @@+-- | 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
+ test/Main.hs view
@@ -0,0 +1,17 @@+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.TestTrim as T++++main::IO()+main = do+ F.main+ P.main+ R.main+ S.main+ T.main
+ test/TestRegex/Format.hs view
@@ -0,0 +1,18 @@+{-# 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" $ 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 view
@@ -0,0 +1,59 @@+{-# LANGUAGE FlexibleContexts, NoOverloadedStrings #-}+module TestRegex.Pcre where++import Test.Hspec+import Regexdo.TypeDo+import qualified 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 view
@@ -0,0 +1,82 @@+{-# LANGUAGE BangPatterns, NoOverloadedStrings #-}+module TestRegex.Replace where++import Test.Hspec+import Data.Array((!))+import Regexdo.TypeDo++import Regexdo.Pcre.Replace+import Regexdo.Convert+import Data.ByteString as B+import Text.Regex.Base.RegexLike+++main::IO()+main = do+ onceUtf8+ latinOnceAll+ groupReplace+ doc+++doc::IO()+doc = hspec $ do+ describe "Pcre.Replace doc" $ do+ it "replace" $ do+ replace [Once,Utf8] (Needle "поп", Replacement "крестьянин") (Haystack "у попа была собака") `shouldBe` "у крестьянина была собака"++++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] `shouldBe` "a=[A] b=3 12"+ it "All" $ do+ runFn1 [All] `shouldBe` "a=[A] b=[Be] 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 marr1 acc1 = case val1 of+ "101" -> fn1 "[A]"+ "3" -> fn1 "[Be]"+ where ol1 = marr1 ! 3 :: (MatchOffset, MatchLength)+ val1 = extract ol1 acc1+-- !val2 = trace (show val1) val1+ fn1 str1 = replaceMatch ol1 (str1,acc1)
+ test/TestRegex/StringSearch.hs view
@@ -0,0 +1,74 @@+module TestRegex.StringSearch where++import Prelude hiding(break)+import Test.Hspec+import Control.Exception (evaluate)+import Regexdo.TypeDo+import Regexdo.Search+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+ 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 (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 = 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/TestTrim.hs view
@@ -0,0 +1,18 @@+module TestRegex.TestTrim where++import Test.Hspec+import Debug.Trace+import qualified Data.Text as T (strip, pack, unpack)+import Regexdo.Trim+import Regexdo.Convert+++main::IO()+main = hspec $ do+ describe "Habase.Bin.Bistro" $ do+ it "trim" $ trace (show trimmed1) trimmed1 `shouldBe` (toByteString trimmed)+ it "trim 2" $+ trim sTrim `shouldBe` "aiy \n pdsodfg987"+ where sTrim = " aiy \n pdsodfg987 "+ trimmed1 = trim $ toByteString sTrim+ trimmed = (T.unpack . T.strip . T.pack) sTrim