regex-do 2.6.2 → 3.0
raw patch · 41 files changed
+1480/−1635 lines, 41 filesdep +tagged
Dependencies added: tagged
Files
- changelog.md +8/−0
- regex-do.cabal +19/−16
- src/Text/Regex/Do/Convert.hs +0/−33
- src/Text/Regex/Do/Format.hs +0/−132
- src/Text/Regex/Do/Match/Latin.hs +163/−0
- src/Text/Regex/Do/Match/Matchf.hs +66/−0
- src/Text/Regex/Do/Match/Option.hs +143/−0
- src/Text/Regex/Do/Match/Regex.hs +65/−0
- src/Text/Regex/Do/Match/Result.hs +22/−0
- src/Text/Regex/Do/Match/Utf8.hs +215/−0
- src/Text/Regex/Do/Pcre/Ascii/Match.hs +0/−86
- src/Text/Regex/Do/Pcre/Ascii/MatchHint.hs +0/−92
- src/Text/Regex/Do/Pcre/Ascii/Replace.hs +0/−152
- src/Text/Regex/Do/Pcre/Matchf.hs +0/−39
- src/Text/Regex/Do/Pcre/Option.hs +0/−143
- src/Text/Regex/Do/Pcre/Utf8/Match.hs +0/−99
- src/Text/Regex/Do/Pcre/Utf8/MatchHint.hs +0/−75
- src/Text/Regex/Do/Pcre/Utf8/Replace.hs +0/−180
- src/Text/Regex/Do/Replace/Fast.hs +25/−0
- src/Text/Regex/Do/Replace/Latin.hs +84/−0
- src/Text/Regex/Do/Replace/Open.hs +150/−0
- src/Text/Regex/Do/Replace/Template.hs +149/−0
- src/Text/Regex/Do/Replace/Utf8.hs +119/−0
- src/Text/Regex/Do/ReplaceOpen.hs +0/−147
- src/Text/Regex/Do/Result.hs +0/−22
- src/Text/Regex/Do/Split.hs +73/−87
- src/Text/Regex/Do/Trim.hs +8/−9
- src/Text/Regex/Do/Type/Convert.hs +31/−0
- src/Text/Regex/Do/Type/Do.hs +3/−47
- src/Text/Regex/Do/Type/Extract.hs +0/−11
- src/Text/Regex/Do/Type/MatchHint.hs +2/−6
- src/Text/Regex/Do/Type/Regex.hs +0/−121
- test/Main.hs +2/−1
- test/TestRegex/TestFormat.hs +11/−8
- test/TestRegex/TestMakeRegexM.hs +5/−6
- test/TestRegex/TestPcre.hs +30/−30
- test/TestRegex/TestReplace.hs +25/−32
- test/TestRegex/TestReplaceOpen.hs +6/−4
- test/TestRegex/TestReplaceUtf.hs +19/−19
- test/TestRegex/TestSplit.hs +36/−37
- test/TestRegex/TestTrim.hs +1/−1
changelog.md view
@@ -1,3 +1,11 @@+##### 3.0+ *API overhaul*+ minimize use of newtypes+ regex-constructing functions catch error, return Either String a+ Format is now Replace.Template+ fix bug in ReplaceOpen.getGroup + hide Matchf+ ##### 2.6.2 compatible with 2.6.1
regex-do.cabal view
@@ -1,5 +1,5 @@ name: regex-do-version: 2.6.2+version: 3.0 synopsis: PCRE wrapper description: format, search, replace (String | ByteString) with PCRE regex. Utf8-safe author: Imants Cekusins@@ -19,27 +19,26 @@ library exposed-modules: Text.Regex.Do.Trim- Text.Regex.Do.Pcre.Option- Text.Regex.Do.Pcre.Utf8.Replace+ Text.Regex.Do.Match.Option+ Text.Regex.Do.Replace.Utf8 Text.Regex.Do.Split- Text.Regex.Do.Format+ Text.Regex.Do.Replace.Template Text.Regex.Do.Type.Do- Text.Regex.Do.Type.Reexport- Text.Regex.Do.Convert+ Text.Regex.Do.Type.Convert Text.Regex.Do.Pad- Text.Regex.Do.Pcre.Ascii.MatchHint- Text.Regex.Do.ReplaceOpen+ Text.Regex.Do.Replace.Open Text.Regex.Do.Type.Extract- Text.Regex.Do.Type.Regex+ Text.Regex.Do.Match.Regex Text.Regex.Do.Type.MatchHint- Text.Regex.Do.Pcre.Ascii.Match- Text.Regex.Do.Pcre.Ascii.Replace- Text.Regex.Do.Pcre.Utf8.Match- Text.Regex.Do.Pcre.Utf8.MatchHint- Text.Regex.Do.Pcre.Matchf-+ Text.Regex.Do.Match.Latin+ Text.Regex.Do.Replace.Latin+ Text.Regex.Do.Match.Utf8+ Text.Regex.Do.Replace.Fast other-modules:- Text.Regex.Do.Result+ Text.Regex.Do.Match.Result+ Text.Regex.Do.Match.Matchf+ Text.Regex.Do.Type.Reexport+ ghc-options: -fwarn-unused-imports build-depends: base <= 5.0,@@ -47,6 +46,7 @@ regex-pcre, stringsearch, bytestring,+ tagged, mtl, array, text@@ -64,6 +64,7 @@ ScopedTypeVariables DeriveFunctor TypeFamilies+ FunctionalDependencies test-suite spec@@ -81,6 +82,7 @@ ScopedTypeVariables DeriveFunctor TypeFamilies+ FunctionalDependencies main-is: Main.hs@@ -99,6 +101,7 @@ QuickCheck, regex-base, regex-pcre,+ tagged, stringsearch, mtl, bytestring,
− src/Text/Regex/Do/Convert.hs
@@ -1,33 +0,0 @@-module Text.Regex.Do.Convert where--import qualified Data.Text.Encoding as E-import qualified Data.Text as T-import Data.ByteString as B-import Text.Regex.Do.Type.Do-import Text.Regex.Base.RegexLike as R-import Data.Array as A-import Prelude as P----- | both Ascii and Utf8-toByteString::String -> ByteString-toByteString = E.encodeUtf8 . T.pack--toByteString'::String -> Utf8_ ByteString-toByteString' = Utf8_ . toByteString---- | both Ascii and Utf8-toString::ByteString -> String-toString = T.unpack . E.decodeUtf8----class ToArray a where- toArray::a -> MatchArray--instance ToArray MatchArray where- toArray = id--instance ToArray [PosLen] where- toArray [] = listArray (0,0) []- toArray lpl0 = listArray (1, P.length lpl0) lpl0
− src/Text/Regex/Do/Format.hs
@@ -1,132 +0,0 @@-{- | ==== placeholder syntax:-- * index based-- { Int }-- * key based-- { 'String' | 'ByteString' | 'Text' }-- other placeholders may be implemented with-- "Text.Regex.Do.Pcre.Ascii.Replace" or "Text.Regex.Do.Pcre.Utf8.Replace" -}--module Text.Regex.Do.Format- (Format(..),- ReplaceOne(..),- Formatable) where--import Prelude as P-import Text.Regex.Do.Type.Do-import Text.Regex.Do.Split as S (replace)-import Text.Regex.Do.Convert-import Data.ByteString as B-import Data.Text as T---type Formatable a = (Format a [a], Format a [(a,a)])--{- | ==== implemented a:-- * 'String'- * 'ByteString'- * 'Text' -}--class Format a arg where- format::a -- ^ text to format e.g. "today is {0}"- -> arg -- ^ replacement: [a] or [(a,a)]- -> a -- ^ formatted text---instance ReplaceOne Int a =>- Format a [a] where- format = foldr_idx foldFn_idx-{- ^ === index based- >>> format "на первое {0}, на второе {0}" ["перловка"]-- "на первое перловка, на второе перловка"-- >>> format "Polly {0} a {1}" ["got","cracker"]-- "Polly got a cracker"--}--foldFn_idx::ReplaceOne k v =>- v -> (k, v) -> v-foldFn_idx v0 (i0, body1) = replaceOne body1 i0 v0----instance ReplaceOne a a =>- Format a [(a, a)] where- format = P.foldr foldFn_map-{- ^=== key based- key may be {any a}-- >>> format "овчинка {a} не {b}" [("a","выделки"),("b","стоит")]-- "овчинка выделки не стоит"--}----foldFn_map::ReplaceOne k v =>- (k, v) -> v -> v-foldFn_map (k0, v0) body1 = replaceOne body1 k0 v0------ fold with index-type CustomerFn a b = (a -> (Int,b) -> b)--foldr_idx::CustomerFn a b -> b -> [a] -> b-foldr_idx fn0 init1 list0 = b1- where i0 = P.length list0 - 1- (-1,b1) = P.foldr (foldFn fn0) (i0,init1) list0---foldFn::CustomerFn a b -> a -> (Int, b) -> (Int, b)-foldFn fn0 val0 t0@(i0, _) = (i0 - 1, b1)- where b1 = fn0 val0 t0---class ReplaceOne idx a where- replaceOne::a -> idx -> a -> a---instance ReplaceOne Int String where- replaceOne body0 k0 v0 = toString bs1- where pat1 = Pattern $ toByteString $ "{" ++ (show k0) ++ "}"- repl1 = Replacement $ toByteString v0- bs1 = S.replace pat1 repl1 $ Body $ toByteString body0---instance ReplaceOne String String where- replaceOne body0 k0 v0 = toString bs1- where pat1 = Pattern $ toByteString $ "{" ++ k0 ++ "}"- repl1 = Replacement $ toByteString v0- bs1 = S.replace pat1 repl1 $ Body $ toByteString body0---instance ReplaceOne Int ByteString where- replaceOne body0 k0 v0 = S.replace pat1 repl1 $ Body body0- where pat1 = Pattern $ toByteString $ "{" ++ (show k0) ++ "}"- repl1 = Replacement v0---instance ReplaceOne ByteString ByteString where- replaceOne body0 k0 v0 = S.replace pat1 repl1 $ Body body0- where pat1 = Pattern $ B.concat [toByteString "{", k0, toByteString "}"]- repl1 = Replacement v0----instance ReplaceOne Int Text where- replaceOne body0 k0 v0 = T.replace pat1 v0 body0- where pat1 = T.pack $ "{" ++ (show k0) ++ "}"---instance ReplaceOne Text Text where- replaceOne body0 k0 v0 = T.replace pat1 v0 body0- where pat1 = T.concat [T.pack "{", k0, T.pack "}"]
+ src/Text/Regex/Do/Match/Latin.hs view
@@ -0,0 +1,163 @@+{- | although sometimes funs in Ascii modules work with non-ascii text+ (as some examples show),+ for reliable results with Utf8 pattern or body,+ use "Text.Regex.Do.Pcre.Match.Utf8"++ see also "Text.Regex.Base.RegexLike" -}++module Text.Regex.Do.Match.Latin+ (MatchOnce(..),+ MatchAll(..),+ R.extract -- | 'extract' is reexport from "Text.Regex.Base.RegexLike"+ ) where++import qualified Text.Regex.Base.RegexLike as R hiding (makeRegex)+import Text.Regex.Do.Type.Do+import Text.Regex.Do.Match.Matchf as F+import Text.Regex.PCRE.Wrap()+import Text.Regex.Do.Type.MatchHint+import Text.Regex.Do.Match.Regex as R+import Text.Regex.Do.Type.Reexport as Re+import Data.Tagged+++{- | === API changes: + + Once is hinted with '~?' + + All is hinted with '~*' ++ All regex-computing instances catch regex errors, return 'Either' 'String' out ('Left' String is the error message)+ + * pattern: 'String', 'ByteString', 'Regex'+ + String | ByteString pattern may contains regex++ * body: 'String', 'ByteString'+ * out: out | E out++ * 'Bool': test if regex matches+ * ['String']+ * ['ByteString']+ * ['PosLen']+++ precompiled Regex may be used as pattern too. see "Text.Regex.Do.Pcre.Match.Utf8" -}+class MatchOnce pattern body out where+ (~?)::pattern -> body -> out++{- | * pattern: 'String', 'ByteString', 'Regex'+ * body: 'String', 'ByteString'+ * out: out | E out++ * [['String']]+ * [['ByteString']]+ * [['PosLen']]+-}+class MatchAll pattern body out where+ (~*)::pattern -> body -> out+++instance R.RegexLike Re.Regex b => MatchOnce Re.Regex b [b] where+ (~?) pat0 body0 = once pat0 (Tagged body0)+-- ^ always succeeds +++instance (R.Regex b, R.RegexLike Re.Regex b) => + MatchOnce b b (E [b]) where + (~?) pat0 body0 = withRegex pat0 (Tagged body0) once+{- ^ >>> "^all" ~? "all the time"::E [String]+ + Right \["all"] -}++instance (R.Regex b, R.RegexLike Re.Regex b) =>+ MatchOnce b b (E Bool) where+ (~?) pat0 body0 = withRegex pat0 (tagB body0) test+ where tagB::b -> Tagged Test b+ tagB = Tagged+{- ^ test++ >>> "chilly" ~? "it's chilly inside, chilly outside"::E Bool++ Right True -}+ ++instance R.RegexLike Re.Regex b =>+ MatchOnce Re.Regex b Bool where+ (~?) pat0 body0 = test pat0 (tagB body0) + where tagB::b -> Tagged Test b+ tagB = Tagged +{- ^ test.++always succeeds -} +++instance R.RegexLike Re.Regex b =>+ MatchAll Re.Regex b [[b]] where+ (~*) pat0 body0 = F.all pat0 (Tagged body0)+-- ^ always succeeds +++instance (R.Regex b, R.RegexLike Re.Regex b) =>+ MatchAll b b (E [[b]]) where+ (~*) pat0 body0 = withRegex pat0 (Tagged body0) F.all +{- ^ @ +"chilly" ~* "it's chilly inside, chilly outside"::E [[ByteString]]++Right \[\["chilly"],["chilly"]] + @ -}+++instance R.RegexLike Re.Regex b =>+ MatchOnce Re.Regex b [PosLen] where+ (~?) pat0 body0 = r1 + where tagOne::b -> Tagged Once b+ tagOne = Tagged+ Right r1 = poslen_ (Right pat0) (tagOne body0)+-- ^ always succeeds +++instance (R.Regex b, R.RegexLike Re.Regex b) =>+ MatchOnce b b (E [PosLen]) where+ (~?) pat0 body0 = withRegex' pat0 (tagOne body0) poslen_+ where tagOne::b -> Tagged Once b+ tagOne = Tagged+ +{-^ >>> "à" ~? "tourner à gauche"::E [PosLen]++ Right \[(8,2)] -}+++instance R.RegexLike Re.Regex b =>+ MatchAll Re.Regex b [[PosLen]] where+ (~*) pat0 body0 = r1 + where tagAll::b -> Tagged All b+ tagAll = Tagged+ Right r1 = poslen_ (Right pat0) (tagAll body0)+-- ^ always succeeds +++instance (R.Regex b, R.RegexLike Re.Regex b) =>+ MatchAll b b (E [[PosLen]]) where+ (~*) pat0 body0 = withRegex' pat0 (tagAll body0) poslen_+ where tagAll::b -> Tagged All b+ tagAll = Tagged++++withRegex::(R.Regex a, R.RegexLike Re.Regex b) =>+ a -> -- pattern + hint b -> -- body+ (Re.Regex -> hint b -> out) -> + E out+withRegex p0 b0 fn0 = makeRegex p0 >>= \p1 ->+ Right $ fn0 p1 b0+++withRegex'::(R.Regex a, Matchf hint) =>+ a -> hint b ->+ (E Re.Regex -> hint b -> P hint) ->+ P hint+withRegex' p0 b0 fn0 = + let er1 = makeRegex p0 + in fn0 er1 b0
+ src/Text/Regex/Do/Match/Matchf.hs view
@@ -0,0 +1,66 @@+-- | __internal__ module, exposed only to show the instances+module Text.Regex.Do.Match.Matchf where++import Text.Regex.Do.Type.Do+import Text.Regex.Do.Type.Reexport as R+import Text.Regex.Do.Match.Result as R+import Text.Regex.Base.RegexLike as R+import Text.Regex.Do.Type.MatchHint+import Data.Tagged+import Data.ByteString as B +++type R_ b = R.RegexLike R.Regex b+++class Matchf hint where+ type H hint+ type P hint+ marray_::R_ b => E R.Regex -> hint b -> H hint+ poslen_::R_ b => E R.Regex -> hint b -> P hint+ + +instance Matchf (Tagged Once) where+ type H (Tagged Once) = E (Maybe MatchArray)+ type P (Tagged Once) = E [PosLen]+ marray_ ep0 (Tagged b0) = ep0 >>= \ep1 -> Right $ R.matchOnce ep1 b0 + poslen_ ep0 (Tagged b0) = ep0 >>= \ep1 -> + let mpl1 = R.poslen $ R.matchOnce ep1 b0::Maybe [PosLen]+ in Right $ maybe [] id mpl1 +++instance Matchf (Tagged All) where+ type H (Tagged All) = E [MatchArray]+ type P (Tagged All) = E [[PosLen]]+ marray_ ep0 (Tagged b0) = ep0 >>= \ep1 -> Right $ R.matchAll ep1 b0+ poslen_ ep0 (Tagged b0) = ep0 >>= \ep1 -> Right $ R.poslen $ R.matchAll ep1 b0+++once::(R_ b, R.Extract b) =>+ R.Regex -> Tagged Once b -> [b] -- ^ matched content+once p0 t0@(Tagged b0) = maybe [] id $ R.allMatches (Body b0) r1 + where Right r1 = marray_ (Right p0) t0 +++all::(R_ b, R.Extract b) =>+ R.Regex -> Tagged All b -> [[b]] -- ^ matched content+all p0 t0@(Tagged b0) = R.allMatches (Body b0) r1 + where Right r1 = marray_ (Right p0) t0+++test::(R_ b, R.Extract b) =>+ R.Regex -> Tagged Test b -> Bool -- ^ matched content+test p0 t0@(Tagged b0) = R.matchTest p0 b0++++tagOnce::b -> Tagged Once b+tagOnce = Tagged++tagAll::b -> Tagged All b+tagAll = Tagged+++checkPattern::ByteString -> ByteString+checkPattern bs0 = if bs0 == B.empty then error "empty pattern"+ else bs0
+ src/Text/Regex/Do/Match/Option.hs view
@@ -0,0 +1,143 @@+module Text.Regex.Do.Match.Option (+ Comp(..),+ Exec(..),+ comp,+ exec+ ) where++import Data.Bits+import qualified Text.Regex.PCRE.ByteString as B+++-- | <http://www.pcre.org/pcre.txt pcre man pages>++data Comp = Blank {- ^ 'B.compBlank'++ clears default options: extended,caseSensitive,multiline regex+ -}++ | Anchored {- ^ 'B.compAnchored'++ the pattern is forced to be "anchored", that is, it+ is constrained to match only at the first matching point in the string+ that is being searched (the "subject string").++ This effect can also be achieved by appropriate constructs in the pattern itself. -}++ | Caseless {- ^ 'B.compCaseless'++ letters in the pattern match both upper and lower case letters.++ It is equivalent to Perl's /i option, and it can be changed within a pattern by a (?i) option setting.++ In UTF-8 mode, PCRE always understands the concept of case for characters whose values are+ less than 128, so caseless matching is always possible. For characters with higher values, the concept of case is supported if PCRE is compiled with Unicode property support.+ If you want to use caseless matching for characters 128 and above, you must ensure+ that PCRE is compiled with Unicode property support as well as with UTF-8 support. -}++ | Dotall {- ^ 'B.compDotAll'++ a dot metacharacter in the pattern matches a character of any value,+ including one that indicates a newline.++ However, it only ever matches one character, even if newlines are coded as CRLF.++ Without this option, a dot does not match when the current position is+ at a newline.++ This option is equivalent to Perl's /s option, and it can be changed within a pattern by a (?s) option setting.++ A negative class such as [^a] always matches newline characters, independent of the setting of this option. -}++ | Multiline {- ^ 'B.compMultiline'++ By default, for the purposes of matching "start of line" and "end of+ line", PCRE treats the subject string as consisting of a single line of+ characters, even if it actually contains newlines. The "start of line"+ metacharacter (^) matches only at the start of the string, and the "end+ of line" metacharacter ($) matches only at the end of the string, or+ before a terminating newline (except when PCRE_DOLLAR_ENDONLY is set).+ Note, however, that unless PCRE_DOTALL is set, the "any character"+ metacharacter (.) does not match at a newline. This behaviour (for ^,+ $, and dot) is the same as Perl.++ When PCRE_MULTILINE it is set, the "start of line" and "end of line"+ constructs match immediately following or immediately before internal+ newlines in the subject string, respectively, as well as at the very+ start and end.++ This is equivalent to Perl's /m option, and it can be+ changed within a pattern by a (?m) option setting.++ If there are no newlines in a subject string, or no occurrences of ^ or $ in a pattern,+ setting PCRE_MULTILINE has no effect. -}++ | Utf8 {- ^ 'B.compUTF8'++ This option causes PCRE to regard both the pattern and the subject as+ strings of UTF-8 characters instead of single-byte strings. However, it+ is available only when PCRE is built to include UTF support. If not,+ the use of this option provokes an error. Details of how this option+ changes the behaviour of PCRE are given in the pcreunicode page. -}++ | Ungreedy {- ^ 'B.compUngreedy'++ This option inverts the "greediness" of the quantifiers so that they+ are not greedy by default, but become greedy if followed by "?".++ It can also be set by a (?U) option setting within the pattern. -}+ deriving (Eq,Ord,Enum)+++data Exec = BlankE {- ^ 'B.execBlank'++ clears default options: extended,caseSensitive,multiline regex -}+ | NotEmpty {- ^ 'B.execNotEmpty'++ An empty string is not considered to be a valid match if this option is+ set. If there are alternatives in the pattern, they are tried. If all+ the alternatives match the empty string, the entire match fails. For+ example, if the pattern++ a?b?++ is applied to a string not beginning with "a" or "b", it matches an+ empty string at the start of the subject. With PCRE_NOTEMPTY set, this+ match is not valid, so PCRE searches further into the string for occurrences of "a" or "b". -}++ | Partial {- ^ 'B.execPartial'++ see PCREPARTIAL(3) in <http://www.pcre.org/pcre.txt pcre man pages> -}+ deriving (Eq,Ord,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/Match/Regex.hs view
@@ -0,0 +1,65 @@+module Text.Regex.Do.Match.Regex+ (Regex(..),+ E(..)) where++import qualified Text.Regex.Base.RegexLike as R+import qualified Text.Regex.Do.Type.Reexport as R+import Data.ByteString+import Text.Regex.Do.Type.Do+import Text.Regex.Do.Match.Option+import Data.List as L+++++class Regex a where+ makeRegex::a -> E R.Regex+ makeRegexOpt::a -> [Comp] -> [Exec] -> E R.Regex+++instance Regex ByteString where+ makeRegex p0 = rre $ R.makeRegexM p0 + makeRegexOpt p0 o0 e0 = rre $ makeRegexOptsM p0 o0 e0 +++instance Regex String where+ makeRegex p0 = rre $ R.makeRegexM p0+ makeRegexOpt p0 o0 e0 = rre $ makeRegexOptsM p0 o0 e0 +++instance Regex R.Regex where+ makeRegex p0 = pure p0+ makeRegexOpt p0 _ _ = pure p0+++makeRegexOptsM::(Monad m, Opt_ a) =>+ a -> [Comp] -> [Exec] ->+ m R.Regex+makeRegexOptsM pat0 comp0 exec0 = rx1+ where c1 = comp comp0+ e1 = exec exec0+ rx1 = R.makeRegexOptsM c1 e1 pat0+++-- | internal type+type Opt_ a = R.RegexMaker R.Regex R.CompOption R.ExecOption a+++rre::RegexResult a -> Either String a+rre (RegexResult e0) = either (Left . (L.intercalate " ")) Right e0+++{- | catches regex construction __errors__ -}+newtype RegexResult a = RegexResult (Either [String] a) deriving (Functor)++instance Applicative RegexResult where+ pure = RegexResult . Right+ (<*>) (RegexResult (Left e1)) (RegexResult (Left e2)) = RegexResult $ Left $ e1 ++ e2+ (<*>) (RegexResult (Right fn0)) (RegexResult (Left e1)) = RegexResult $ Left e1+ (<*>) (RegexResult (Left e1)) (RegexResult (Right r1)) = RegexResult $ Left e1+ (<*>) (RegexResult (Right fn0)) (RegexResult (Right a0)) = pure $ fn0 a0++instance Monad RegexResult where+ (>>=) (RegexResult (Left e1)) fn0 = RegexResult $ Left e1+ (>>=) (RegexResult (Right a0)) fn0 = fn0 a0+ fail s0 = RegexResult $ Left [s0]
+ src/Text/Regex/Do/Match/Result.hs view
@@ -0,0 +1,22 @@+module Text.Regex.Do.Match.Result where++import qualified Data.Array as A(elems)+import Text.Regex.Base.RegexLike as R+import Text.Regex.Do.Type.Do++-- | match offset, length+poslen::Functor f =>+ f MatchArray -> f [PosLen]+poslen = (A.elems <$>)+++-- | all groups+allMatches::(Functor f, R.Extract b) =>+ Body b -> f MatchArray -> f [b]+allMatches hay0 results0 = groupMatch hay0 <$> results0+++-- | matches for one group+groupMatch::R.Extract b =>+ Body b -> MatchArray -> [b]+groupMatch (Body b0) a0 = [R.extract tuple1 b0 | tuple1 <- A.elems a0]
+ src/Text/Regex/Do/Match/Utf8.hs view
@@ -0,0 +1,215 @@+{- | see "Text.Regex.Base.RegexLike" ++ see "Text.Regex.Do.Pcre.Match.Latin" for API changes++ __'toByteString'__ converts String to utf8 'ByteString' -}+module Text.Regex.Do.Match.Utf8+ (MatchOnce(..),+ MatchAll(..),+ R.extract -- | 'extract' is reexport from "Text.Regex.Base.RegexLike"+ ) where++import Data.Tagged+import qualified Text.Regex.Base.RegexLike as R hiding (makeRegex)+import Text.Regex.Do.Type.Do+import Text.Regex.Do.Match.Matchf as F+import Text.Regex.PCRE.Wrap()+import Text.Regex.Do.Match.Regex as T+import Text.Regex.Do.Type.MatchHint+import Text.Regex.Do.Match.Option+import Text.Regex.Do.Type.Reexport as Re+import Data.ByteString+import Text.Regex.Do.Type.Convert+++{- | * pattern: 'String', 'ByteString', 'Regex' compile 'Re.Regex' with 'Utf8' opt++ String | ByteString pattern may contains regex+ + * body: 'String', 'ByteString'+ * out: out | E out++ * 'Bool' : test if regex matches+ * ['String'] + * ['ByteString']+ * ['PosLen'] -}+class MatchOnce pattern body out where+ (~?)::pattern -> body -> out+++{- | * pattern: 'String', 'ByteString', 'Re.Regex' compile 'Re.Regex' with 'Utf8' opt+ * body: 'String', 'ByteString'+ * out:++ * [['String']]+ * [['ByteString']]+ * [['PosLen']] -}+class MatchAll pattern body out where+ (~*)::pattern -> body -> out+++{- | b: 'String', 'ByteString' ++ always succeeds ++==== precompiled regex as pattern++@ +let rx1 = makeRegexOpt (toByteString "左") [Utf8] [] -- add options as needed+ m1 = rx1 -? (toByteString "100メートル左折後、左")::[ByteString]+m1 `shouldBe` [toByteString "左"] +@ -}++instance R.RegexLike Re.Regex b => + MatchOnce Re.Regex b [b] where+ (~?) pat0 body0 = once pat0 (Tagged body0)+++instance R.RegexLike Re.Regex b => + MatchOnce Re.Regex b Bool where+ (~?) pat0 body0 = test pat0 (Tagged body0)+{- ^ b: 'String', 'ByteString' ++always succeeds -}+++instance R.RegexLike Re.Regex b =>+ MatchOnce Re.Regex b [PosLen] where+ (~?) pat0 body0 = r1+ where tagOne::b -> Tagged Once b+ tagOne = Tagged + Right r1 = poslen_ (Right pat0) (tagOne body0)+{- ^ b: 'String', 'ByteString' ++always succeeds -}+++instance MatchOnce String String (E [String]) where+ (~?) pat0 body0 = withRegex pat0 (tagB body0) once+ where tagB::b -> Tagged Once b+ tagB = Tagged+{- ^ >>> ("^熱"::String) ~? ("熱い午後"::String)::E [String]++Right \["熱"] -}+++instance MatchOnce ByteString ByteString (E [ByteString]) where+ (~?) pat0 body0 = withRegex pat0 (tagB body0) once+ where tagB::b -> Tagged Once b+ tagB = Tagged+++instance MatchOnce String String (E Bool) where+ (~?) pat0 body0 = withRegex pat0 (tagB body0) test+ where tagB::b -> Tagged Test b+ tagB = Tagged+{- ^ test++>>> ("в"::String) ~? ("тихо в лесу"::String)::E Bool++Right True -}++instance MatchOnce ByteString ByteString (E Bool) where+ (~?) pat0 body0 = withRegex pat0 (tagB body0) test+ where tagB::b -> Tagged Test b+ tagB = Tagged+++instance MatchOnce ByteString ByteString (E [PosLen]) where+ (~?) pat0 body0 = withRegex' pat0 (tagOne body0) poslen_+ where tagOne::b -> Tagged Once b+ tagOne = Tagged+++instance MatchOnce String String (E [PosLen]) where+ (~?) pat0 body0 = withRegex' pat0 (tagOne body0) poslen_+ where tagOne::b -> Tagged Once b+ tagOne = Tagged+++instance R.RegexLike Re.Regex b =>+ MatchAll Re.Regex b [[b]] where+ (~*) pat0 body0 = F.all pat0 (Tagged body0)+{- ^ b: 'String', 'ByteString' ++always succeeds -}++++instance MatchAll ByteString ByteString (E [[ByteString]]) where+ (~*) pat0 body0 = withRegex pat0 (Tagged body0) F.all+++instance MatchAll String String (E [[String]]) where+ (~*) pat0 body0 = withRegex pat0 (Tagged body0) F.all+{- ^ >>> ("лес"::String) ~* ("Залесью, залесью…"::String)::E [[String]]++Right \[["лес"],["лес"]] -}+++instance R.RegexLike Re.Regex b =>+ MatchAll Re.Regex b [[PosLen]] where+ (~*) pat0 body0 = r1+ where tagOne::b -> Tagged All b+ tagOne = Tagged+ Right r1 = poslen_ (Right pat0) (tagOne body0)+{- ^ b: 'String', 'ByteString' ++always succeeds -}++++instance MatchAll String String (E [[PosLen]]) where+ (~*) pat0 body0 = withRegex' pat0 (tagAll body0) poslen_+ where tagAll::b -> Tagged All b+ tagAll = Tagged+++instance MatchAll ByteString ByteString (E [[PosLen]]) where+ (~*) pat0 body0 = withRegex' pat0 (tagAll body0) poslen_+ where tagAll::b -> Tagged All b+ tagAll = Tagged++++class WithRegex a out' out where+ withRegex::(T.Regex a, R.RegexLike Re.Regex a, Functor hint) =>+ a -> -- pattern + hint a -> -- body+ (Re.Regex -> hint ByteString -> out') ->+ E out+++instance WithRegex ByteString out out where+ withRegex p0 b0 fn0 = makeRegexOpt p0 [Utf8] [] >>= \p1 ->+ Right $ fn0 p1 b0+++instance WithRegex String [ByteString] [String] where+ withRegex p0 b0 fn0 = makeRegexOpt p1 [Utf8] [] >>= \p2 ->+ Right $ toString <$> (fn0 p2 b1)+ where p1 = toByteString p0+ b1 = toByteString <$> b0+++instance WithRegex String [[ByteString]] [[String]] where+ withRegex p0 b0 fn0 = makeRegexOpt p1 [Utf8] [] >>= \p2 ->+ Right $ [(toString <$>)] <*> (fn0 p2 b1)+ where p1 = toByteString p0+ b1 = toByteString <$> b0+++instance WithRegex String Bool Bool where+ withRegex p0 b0 fn0 = makeRegexOpt p1 [Utf8] [] >>= \p2 ->+ Right $ fn0 p2 b1+ where p1 = toByteString p0+ b1 = toByteString <$> b0+++withRegex'::(T.Regex a, Matchf hint) =>+ a -> hint b ->+ (E Re.Regex -> hint b -> P hint) ->+ P hint+withRegex' p0 b0 fn0 =+ let er1 = makeRegexOpt p0 [Utf8] []+ in fn0 er1 b0
− src/Text/Regex/Do/Pcre/Ascii/Match.hs
@@ -1,86 +0,0 @@-{- | although sometimes funs in Ascii modules work with non-ascii text- (as some examples show),- for reliable results with Utf8 pattern or body,- use "Text.Regex.Do.Pcre.Utf8.Match"-- see also "Text.Regex.Base.RegexLike" and "Text.Regex.Do.Pcre.Ascii.MatchHint" -}--module Text.Regex.Do.Pcre.Ascii.Match- (Match(..),- (=~),- R.extract -- | 'extract' is reexport from "Text.Regex.Base.RegexLike"- ) where--import qualified Text.Regex.Base.RegexLike as R hiding (makeRegex)-import Text.Regex.Do.Type.Do-import Text.Regex.Do.Pcre.Matchf as F-import Text.Regex.PCRE.Wrap()-import Text.Regex.Do.Type.Regex-import Text.Regex.Do.Type.MatchHint---{- | short version of 'match': arg without newtypes-- is borrowed from "Text.Regex.PCRE.Wrap" -}-(=~)::Match a b out =>- a -- ^ pattern- -> b -- ^ body- -> out-(=~) p0 b0 = match (Pattern p0) (Body b0)----{- | * a: 'String', 'ByteString', 'Regex'- * b: 'String', 'ByteString'- * out:-- * ['String'], [['String']]- * ['ByteString'], [['ByteString']]- * 'Bool'- * ['PosLen'], [['PosLen']]--- precompiled Regex may be used as pattern too. see "Text.Regex.Do.Pcre.Utf8.Match"-- See also "Text.Regex.Do.Pcre.Ascii.MatchHint"-- to catch regex construction __errors__, precompile 'Regex' with 'makeRegexM' or 'makeRegexOptM' -}--class Match a b out where- match::Pattern a -> Body b -> out------- | match once-instance Rx_ a b => Match a b [b] where- match p0 = once (makeRegex' p0)-{- ^ >>> "^all" =~ "all the time"::[String]-- \["all"\] -}-instance Rx_ a b => Match a b Bool where- match p0 (Body b0) = R.matchTest (makeRegex p0) b0-{- ^ test-- >>> "chilly" =~ "it's chilly inside, chilly outside"::Bool-- True -}---- | match all-instance Rx_ a b => Match a b [[b]] where- match p0 = F.all (makeRegex' p0)-{- ^ >>> "chilly" =~ "it's chilly inside, chilly outside"::[[ByteString]]-- \[["chilly"\],\["chilly"\]] -}---- | match once-instance Rx_ a b => Match a b [PosLen] where- match p0 b0 = maybe [] id $ poslen_ (Once $ makeRegex' p0) b0-{- ^ >>> "à" =~ "tourner à gauche"::[PosLen]-- \[(8,2)\] -}---- | match all-instance Rx_ a b => Match a b [[PosLen]] where- match p0 = poslen_ $ All $ makeRegex' p0-
− src/Text/Regex/Do/Pcre/Ascii/MatchHint.hs
@@ -1,92 +0,0 @@-{- | this module uses- <https://cdepillabout.github.io/haskell-type-families-presentation/#/ TypeFamilies>-- this module is similar to "Text.Regex.Do.Pcre.Ascii.Match". The differences are:-- * "Text.Regex.Do.Pcre.Ascii.Match" is more flexible:-- accepts 'Pattern' Regex,-- accepts 'Pattern' and 'Body' of different types-- * "Text.Regex.Do.Pcre.Ascii.Match" needs to infer result type-- this module:-- * 'Pattern' and 'Body' are of the same type-- * 'Hint' and inferrable 'Pattern' or 'Body' type determine the instance-- the result type is determined by the hint-- * handy when working with 'OverloadedStrings', in other cases when compiler needs a hint -}--module Text.Regex.Do.Pcre.Ascii.MatchHint where--import Text.Regex.Do.Type.Do hiding (Once,All)-import Text.Regex.PCRE.Wrap()-import qualified Text.Regex.Do.Pcre.Ascii.Match as M-import Text.Regex.Do.Type.MatchHint-import Data.ByteString---{- | * hint: 'Once', 'All', 'Test', 'PosLen'', 'PosLen_'- * a: 'String', 'ByteString'--}---class (Hint hint, M.Match a a (F hint a)) =>- MatchHint hint a where- type F hint a- match::hint (Pattern a) -> Body a -> F hint a- match h0 = M.match $ unhint h0--(=~)::MatchHint hint a =>- hint a -- ^ hint & pattern- -> a -- ^ body- -> F hint a -- ^ type defined by the instance, determined by the hint-(=~) h0 = (M.=~) $ unhint h0---instance MatchHint Test String where- type F Test String = Bool---instance MatchHint PosLen' String where- type F PosLen' String = [PosLen]--{- ^ >>> PosLen' ("и"::String) =~ "бывает и хуже"-- \[(13,2)\] -}--instance MatchHint PosLen_ String where- type F PosLen_ String = [[PosLen]]--instance MatchHint Once String where- type F Once String = [String]--{- ^ >>> Once ("^all"::String) =~ "all the time"-- \["all"\] -}--instance MatchHint All String where- type F All String = [[String]]--instance MatchHint Test ByteString where- type F Test ByteString = Bool--{- ^ >>> Test ("в"::ByteString) =~ "тихо в лесу"-- True -}--instance MatchHint PosLen' ByteString where- type F PosLen' ByteString = [PosLen]--instance MatchHint PosLen_ ByteString where- type F PosLen_ ByteString = [[PosLen]]--instance MatchHint Once ByteString where- type F Once ByteString = [ByteString]--instance MatchHint All ByteString where- type F All ByteString = [[ByteString]]
− src/Text/Regex/Do/Pcre/Ascii/Replace.hs
@@ -1,152 +0,0 @@-{- | for reliable results with Utf8 pattern or body,- use "Text.Regex.Do.Pcre.Utf8.Replace" -}--module Text.Regex.Do.Pcre.Ascii.Replace- (Replace(..),- Replace'(),- Repl_) where--import Text.Regex.Base.RegexLike as R-import Prelude as P-import Text.Regex.Do.Type.Do-import Text.Regex.Do.Type.Reexport as R-import Text.Regex.Do.Pcre.Matchf-import qualified Text.Regex.Do.ReplaceOpen as O-import Text.Regex.Do.Type.Regex as T-import Text.Regex.Do.Type.Extract-import Text.Regex.Do.Type.MatchHint-import Text.Regex.Do.Pcre.Option as O--{- | 'All' | 'Once' needs to be specified once with either pat, repl or body-- * pat: a: 'String' | 'ByteString' | 'Regex'-- * a- * ('All' | 'Once' (a))- * ('All' | 'Once' ('Pattern' a))-- to catch regex construction __errors__, precompile 'Regex' with 'makeRegexM' or 'makeRegexOptM'-- * repl: b: 'String' | 'ByteString'-- * ('Replacement' b)- * ('GroupReplacer' b)- * ('All' | 'Once' ('Replacement' b))- * ('All' | 'Once' ('GroupReplacer' b))-- * body: b: 'String' | 'ByteString'-- * b- * 'Body' b- * ('All' | 'Once' (b))-- * out:-- * 'String' | 'ByteString'- -}-class Replace pat repl body out where- replace::pat -> repl -> body -> out---instance (T.Regex a, Hint all, Replace' all a repl b) =>- Replace (all (Pattern a)) (repl b) (Body b) b where- replace = replace'-{- ^ full typed arg-- >>> replace (Once (Pattern "^a\\s")) (Replacement "A") (Body "a bc") -}---instance (T.Regex a, Hint all, Replace' all a repl b, Functor all) =>- Replace (all a) (repl b) b b where- replace p0 r0 b0 = replace' (Pattern <$> p0) r0 $ Body b0-{- ^ hint 'Pattern'-- >>> replace (Once "^a\\s") (Replacement "A") "a bc" -}---instance (T.Regex a, Hint all, Replace' all a repl b) =>- Replace a (all(repl b)) b b where- replace p0 r0 b0 = replace' p1 (unhint r0) $ Body b0- where p1 = swap r0 $ Pattern p0-{- ^ hint repl-- >>> replace "^a\\s" (Once (Replacement "A")) "a bc" -}---instance (T.Regex a, Replace' Once a repl b) =>- Replace a (repl b) (Once b) b where- replace p0 r0 b0 = replace' p1 r0 $ Body $ unhint b0- where p1 = swap b0 $ Pattern p0-{- ^ hint 'Body'-- >>> replace "^a\\s" (Replacement "A") $ Once "a bc" -}---instance (T.Regex a, Replace' All a repl b) =>- Replace a (repl b) (All b) b where- replace p0 r0 b0 = replace' p1 r0 $ Body $ unhint b0- where p1 = swap b0 $ Pattern p0--- ^ hint 'Body'---{- | internal class & instances-- use 'replace' instead -}-class Replace' all a repl b where- replace'::all (Pattern a) -> repl b -> Body b -> b---type Repl_ f rx r a = (T.Regex rx,- R.RegexLike R.Regex a,- Extract' a,- O.ReplaceOpen f r)--replace_ fn0 p0 r0 b0 =- let ma1 = fn0 p1 b0- p1 = T.makeRegex' <$> p0- in O.replace ma1 r0 b0----instance Repl_ Maybe a repl b => Replace' Once a repl b where- replace' = replace_ marray_--{- ^ === static replace for simple (no group) needle-- for no-regex 'ByteString' replacement see "Text.Regex.Do.Split"-- >>> replace (Once (Pattern "^a\\s")) (Replacement "A") (Body "a bc")-- \"Abc\"-- === dynamic group replace-- >>> replace (Once (Pattern "\\w=(\\d{1,3})")) replacer $ Body "a=101 b=3 12"-- "a=[1 0 1] b=3 12" -}---instance Repl_ [] a repl b => Replace' All a repl b where- replace' = replace_ marray_---{- ^ to tweak regex with 'O.Comp' or 'O.Exec', see "Text.Regex.Do.Type.Regex"-- === dynamic group replace-- custom replacer fn returns replacement value. See 'O.defaultReplacer'-- >>> replacer::GroupReplacer String- replacer = defaultReplacer 1 tweak1- where tweak1 str1 = case str1 of- "101" -> "[1 0 1]"- "3" -> "[ 3 ]"- otherwise -> trace str1 "?"--- >>> replace (All (Pattern "\\w=(\\d{1,3})")) replacer $ Body "a=101 b=3 12"-- "a=[1 0 1] b=[ 3 ] 12" -}--dum_::Comp-dum_ = Blank
− src/Text/Regex/Do/Pcre/Matchf.hs
@@ -1,39 +0,0 @@--- | __internal__ module, exposed only to show the instances-module Text.Regex.Do.Pcre.Matchf where--import Text.Regex.Do.Type.Do-import Text.Regex.Do.Type.Reexport as R-import Text.Regex.Do.Result as R-import Text.Regex.Base.RegexLike as R-import Text.Regex.Do.Type.MatchHint--type R_ b = R.RegexLike R.Regex b---class Matchf hint b where- type H hint- type P hint- marray_::R_ b => hint (Pattern R.Regex) -> Body b -> H hint- poslen_::R_ b => hint (Pattern R.Regex) -> Body b -> P hint--instance Matchf Once b where- type H Once = Maybe MatchArray- type P Once = Maybe [PosLen]- marray_ (Once (Pattern p0)) (Body b0) = R.matchOnce p0 b0- poslen_ r0 b0 = R.poslen $ marray_ r0 b0--instance Matchf All b where- type H All = [MatchArray]- type P All = [[PosLen]]- marray_ (All (Pattern p0)) (Body b0) = R.matchAll p0 b0- poslen_ r0 b0 = R.poslen $ marray_ r0 b0---once::(R_ b, R.Extract b) =>- Pattern R.Regex -> Body b -> [b] -- ^ matched content-once p0 b0 = maybe [] id $ R.allMatches b0 $ marray_ (Once p0) b0---all::(R_ b, R.Extract b) =>- Pattern R.Regex -> Body b -> [[b]] -- ^ matched content-all p0 b0 = R.allMatches b0 $ marray_ (All p0) b0
− src/Text/Regex/Do/Pcre/Option.hs
@@ -1,143 +0,0 @@-module Text.Regex.Do.Pcre.Option (- Comp(..),- Exec(..),- comp,- exec- ) where--import Data.Bits-import qualified Text.Regex.PCRE.ByteString as B----- | <http://www.pcre.org/pcre.txt pcre man pages>--data Comp = Blank {- ^ 'B.compBlank'-- clears default options: extended,caseSensitive,multiline regex- -}-- | Anchored {- ^ 'B.compAnchored'-- the pattern is forced to be "anchored", that is, it- is constrained to match only at the first matching point in the string- that is being searched (the "subject string").-- This effect can also be achieved by appropriate constructs in the pattern itself. -}-- | Caseless {- ^ 'B.compCaseless'-- letters in the pattern match both upper and lower case letters.-- It is equivalent to Perl's /i option, and it can be changed within a pattern by a (?i) option setting.-- In UTF-8 mode, PCRE always understands the concept of case for characters whose values are- less than 128, so caseless matching is always possible. For characters with higher values, the concept of case is supported if PCRE is compiled with Unicode property support.- If you want to use caseless matching for characters 128 and above, you must ensure- that PCRE is compiled with Unicode property support as well as with UTF-8 support. -}-- | Dotall {- ^ 'B.compDotAll'-- a dot metacharacter in the pattern matches a character of any value,- including one that indicates a newline.-- However, it only ever matches one character, even if newlines are coded as CRLF.-- Without this option, a dot does not match when the current position is- at a newline.-- This option is equivalent to Perl's /s option, and it can be changed within a pattern by a (?s) option setting.-- A negative class such as [^a] always matches newline characters, independent of the setting of this option. -}-- | Multiline {- ^ 'B.compMultiline'-- By default, for the purposes of matching "start of line" and "end of- line", PCRE treats the subject string as consisting of a single line of- characters, even if it actually contains newlines. The "start of line"- metacharacter (^) matches only at the start of the string, and the "end- of line" metacharacter ($) matches only at the end of the string, or- before a terminating newline (except when PCRE_DOLLAR_ENDONLY is set).- Note, however, that unless PCRE_DOTALL is set, the "any character"- metacharacter (.) does not match at a newline. This behaviour (for ^,- $, and dot) is the same as Perl.-- When PCRE_MULTILINE it is set, the "start of line" and "end of line"- constructs match immediately following or immediately before internal- newlines in the subject string, respectively, as well as at the very- start and end.-- This is equivalent to Perl's /m option, and it can be- changed within a pattern by a (?m) option setting.-- If there are no newlines in a subject string, or no occurrences of ^ or $ in a pattern,- setting PCRE_MULTILINE has no effect. -}-- | Utf8 {- ^ 'B.compUTF8'-- This option causes PCRE to regard both the pattern and the subject as- strings of UTF-8 characters instead of single-byte strings. However, it- is available only when PCRE is built to include UTF support. If not,- the use of this option provokes an error. Details of how this option- changes the behaviour of PCRE are given in the pcreunicode page. -}-- | Ungreedy {- ^ 'B.compUngreedy'-- This option inverts the "greediness" of the quantifiers so that they- are not greedy by default, but become greedy if followed by "?".-- It can also be set by a (?U) option setting within the pattern. -}- deriving (Eq,Ord,Enum)---data Exec = BlankE {- ^ 'B.execBlank'-- clears default options: extended,caseSensitive,multiline regex -}- | NotEmpty {- ^ 'B.execNotEmpty'-- An empty string is not considered to be a valid match if this option is- set. If there are alternatives in the pattern, they are tried. If all- the alternatives match the empty string, the entire match fails. For- example, if the pattern-- a?b?-- is applied to a string not beginning with "a" or "b", it matches an- empty string at the start of the subject. With PCRE_NOTEMPTY set, this- match is not valid, so PCRE searches further into the string for occurrences of "a" or "b". -}-- | Partial {- ^ 'B.execPartial'-- see PCREPARTIAL(3) in <http://www.pcre.org/pcre.txt pcre man pages> -}- deriving (Eq,Ord,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/Utf8/Match.hs
@@ -1,99 +0,0 @@-{- | see "Text.Regex.Base.RegexLike" and "Text.Regex.Do.Pcre.Utf8.MatchHint"-- similar to "Text.Regex.Do.Pcre.Ascii.Match"-- 'Pattern' & 'Body' are wrapped in 'Utf8_' encoding tag.- This tag adds clarity, prevents calling Ascii functions by mistake.-- __'toByteString''__ converts String to 'Utf8_' 'ByteString' -}-module Text.Regex.Do.Pcre.Utf8.Match- (Match(..),- (=~),- R.extract -- | 'extract' is reexport from "Text.Regex.Base.RegexLike"- ) where--import Text.Regex.Do.Type.Reexport as R-import qualified Text.Regex.Base.RegexLike as R hiding (makeRegex)-import Text.Regex.Do.Type.Do-import Text.Regex.Do.Pcre.Matchf as F-import Text.Regex.PCRE.Wrap()-import Text.Regex.Do.Type.Regex as T-import Text.Regex.Do.Type.MatchHint-import Text.Regex.Do.Pcre.Option-import Text.Regex.Do.Convert-import Data.ByteString----- | synonym for 'match'. arg without newtypes-(=~)::Match Utf8_ a b out =>- a -- ^ pattern- -> b -- ^ body- -> out-(=~) p0 b0 = match (Pattern $ Utf8_ p0) (Body $ Utf8_ b0)----{- | * enc: 'Utf8_'- * a: 'String', 'ByteString', 'Regex'-- to catch regex construction __errors__, precompile 'Regex' with 'makeRegexM' or 'makeRegexOptM'-- * b: 'String', 'ByteString'- * out:-- * ['String'], [['String']]- * ['ByteString'], [['ByteString']]- * 'Bool'- * ['PosLen'], [['PosLen']] -}--class Match enc a b out where- match::Pattern (enc a) -> Body (enc b) -> out---{- | match once-- ==== precompiled regex as pattern-- >>> let rx1 = makeRegexOpt' (Pattern $ toByteString' "左") [] [] -- add options as needed- rx2 = Utf8_ <$> rx1- m1 = U.match rx2 (Body $ toByteString' "100メートル左折後、左")::[ByteString]- m1 `shouldBe` [toByteString "左"] -}--instance Rx_ a b => Match Utf8_ a b [b] where- match p0 b0 = once (mr_ p0) $ val <$> b0----instance Rx_ a b => Match Utf8_ a b Bool where- match p0 (Body b0) = R.matchTest (makeRegexOpt p0 [Utf8] []) $ val b0-{- ^ test. Note that a and b may be different types e.g. 'ByteString' and 'String'-- >>> toByteString "в" =~ ("тихо в лесу"::String)::Bool-- True -}---- | match all-instance Rx_ a b => Match Utf8_ a b [[b]] where- match p0 b0 = F.all (mr_ p0) $ val <$> b0-{- ^ >>> ("well"::String) =~ ("all is well that ends well"::String)::[[String]]-- \[["well"\],\["well"\]] -}---- | match once-instance Rx_ a b => Match Utf8_ a b [PosLen] where- match p0 b0 = maybe [] id $ poslen_ (Once $ mr_ p0) $ val <$> b0-{- ^ >>> ("и"::String) =~ ("бывает и хуже"::String)::[PosLen]-- \[(13,2)\] -}---- | match all-instance Rx_ a b => Match Utf8_ a b [[PosLen]] where- match p0 b0 = poslen_ (All $ mr_ p0) $ val <$> b0---mr_::T.Regex a => Pattern a -> Pattern R.Regex-mr_ p0 = makeRegexOpt' p0 [Utf8] []---dum_::String -> Utf8_ ByteString-dum_ = toByteString'
− src/Text/Regex/Do/Pcre/Utf8/MatchHint.hs
@@ -1,75 +0,0 @@--- | see "Text.Regex.Do.Pcre.Ascii.MatchHint" about MatchHint vs Match---module Text.Regex.Do.Pcre.Utf8.MatchHint- (MatchHint(..),- (=~)) where--import Text.Regex.Do.Type.Do hiding (Once,All)-import Text.Regex.PCRE.Wrap()-import qualified Text.Regex.Do.Pcre.Utf8.Match as M-import Text.Regex.Do.Type.MatchHint-import Data.ByteString---{- | * hint: 'Once', 'All', 'Test', 'PosLen'', 'PosLen_'- * a: 'String', 'ByteString'- * enc: 'Utf8_'--}--class (Hint hint, M.Match enc a a (F hint a)) =>- MatchHint hint enc a where- type F hint a- match::hint (Pattern (enc a)) -> Body (enc a) -> F hint a- match h0 = M.match $ unhint h0---(=~)::MatchHint hint Utf8_ a =>- hint a -- ^ hint pattern- -> a -- ^ body- -> F hint a -- ^ type defined by the instance, determined by the hint-(=~) h0 = (M.=~) $ unhint h0---instance MatchHint Test Utf8_ String where- type F Test String = Bool---instance MatchHint PosLen' Utf8_ String where- type F PosLen' String = [PosLen]--{- ^ >>> PosLen' ("и"::String) =~ "бывает и хуже"-- \[(13,2)\] -}--instance MatchHint PosLen_ Utf8_ String where- type F PosLen_ String = [[PosLen]]--instance MatchHint Once Utf8_ String where- type F Once String = [String]--{- ^ >>> Once ("^all"::String) =~ "all the time"-- \["all"\] -}--instance MatchHint All Utf8_ String where- type F All String = [[String]]--instance MatchHint Test Utf8_ ByteString where- type F Test ByteString = Bool--{- ^ >>> Test (toByteString "в") =~ toByteString "тихо в лесу"-- True -}--instance MatchHint PosLen' Utf8_ ByteString where- type F PosLen' ByteString = [PosLen]--instance MatchHint PosLen_ Utf8_ ByteString where- type F PosLen_ ByteString = [[PosLen]]--instance MatchHint Once Utf8_ ByteString where- type F Once ByteString = [ByteString]--instance MatchHint All Utf8_ ByteString where- type F All ByteString = [[ByteString]]
− src/Text/Regex/Do/Pcre/Utf8/Replace.hs
@@ -1,180 +0,0 @@-{- | see also "Text.Regex.Do.Pcre.Ascii.Replace"-- 'Pattern' & 'Body' are wrapped in 'Utf8_' encoding tag.- This tag adds clarity, prevents calling Ascii functions by mistake.-- __'toByteString''__ converts String to 'Utf8_' 'ByteString' -}--module Text.Regex.Do.Pcre.Utf8.Replace- (Replace(..),- Replace'()) where--import Prelude as P-import Text.Regex.Do.Type.Do-import Text.Regex.Do.Pcre.Matchf-import qualified Text.Regex.Do.ReplaceOpen as O-import Text.Regex.Do.Type.Regex as T-import Text.Regex.Do.Type.MatchHint-import Text.Regex.Do.Convert-import Data.ByteString--{- | see "Text.Regex.Do.Pcre.Ascii.Replace" for implemented types-- to catch regex construction __errors__, precompile 'Regex' with 'makeRegexM' or 'makeRegexOptM'-- in full typed instance every b is wrapped in 'Utf8_' newtype-- 'GroupReplacer' is implemented only for 'ByteString' -}--class Replace pat repl body out where- replace::pat -> repl -> body -> out---instance (Replace' all enc b repl) =>- Replace (all (Pattern (enc b))) (repl (enc b)) (Body (enc b)) b where- replace = replace'-{- ^ full typed arg-- >>> replace (Once $ Pattern $ Utf8_ "праздник")- (Replacement $ Utf8_ "радость")- (Body $ Utf8_ "экзамен - всегда праздник")--}---instance (T.Regex b, Hint all,- Replace' all Utf8_ b repl,- Functor all,- Enc' repl Utf8_) =>- Replace (all b) (repl b) b b where- replace p0 r0 b0 = replace' p1 (enc' r0) $- Body $ Utf8_ b0- where p1 = Pattern . Utf8_ <$> p0-{- ^ hint 'Pattern'-- >>> replace (All "праздник")- (Replacement "радость")- "экзамен - всегда праздник"- -}---instance (T.Regex b, Hint all,- Replace' all Utf8_ b repl,- Functor all,- Enc' repl Utf8_) =>- Replace b (all (repl b)) b b where- replace p0 r0 b0 = replace' p1 (enc' $ unhint r0) $- Body $ Utf8_ b0- where p1 = swap r0 $ Pattern $ Utf8_ p0-{- ^ hint repl-- >>> replacer::GroupReplacer (ByteString)- replacer = defaultReplacer 1 tweak1- where tweak1 s1- | s1 == toByteString "[команды]" = toByteString "А - Я"- | s1 == toByteString "[счёт]" = toByteString "5:0"- | s1 == toByteString "[какая боль, ]" = empty- | otherwise = traceShow s1 $ toByteString "?"-- >>> let rx1 = toByteString "(\\[[^\\]]+\\])"- body1 = toByteString "[какая боль, ][команды] : [счёт]"- in replace rx1 (All replacer) body1-- "А - Я : 5:0" -}--instance (T.Regex b,- Replace' Once Utf8_ b repl,- Enc' repl Utf8_) =>- Replace b (repl b) (Once b) b where- replace p0 r0 b0 = replace' p1 (enc' r0) $- Body $ Utf8_ $ unhint b0- where p1 = swap b0 $ Pattern $ Utf8_ p0-{- ^ hint 'Body'-- >>> replace "праздник"- (Replacement "радость")- (Once "экзамен - всегда праздник")- -}---instance (T.Regex b,- Replace' All Utf8_ b repl,- Enc' repl Utf8_) =>- Replace b (repl b) (All b) b where- replace p0 r0 b0 = replace' p1 (enc' r0) $- Body $ Utf8_ $ unhint b0- where p1 = swap b0 $ Pattern $ Utf8_ p0-{- ^ hint 'Body'-- >>> replace "праздник"- (Replacement "радость")- (All "экзамен - всегда праздник")- -}----{- | internal class & instances-- use 'replace' instead -}-class Replace' all enc a repl where- replace'::all (Pattern (enc a)) -> repl (enc a) -> Body (enc a) -> a---instance Replace' Once Utf8_ String Replacement where- replace' = replace_str marray_--instance Replace' All Utf8_ String Replacement where- replace' = replace_str marray_--replace_str f0 p0 r0 b0 =- let ma1 = f0 p1 b1- b1 = toByteString . val <$> b0- r1 = toByteString <$> (val <$> r0)- p1 = T.makeRegex' . (toByteString' . val <$>) <$> p0- in toString $ O.replace ma1 r1 b1---instance Replace' Once Utf8_ ByteString Replacement where- replace' = replace_bs marray_--instance Replace' All Utf8_ ByteString Replacement where- replace' = replace_bs marray_--replace_bs f0 p0 r0 b0 =- let ma1 = f0 p1 b1- b1 = val <$> b0- p1 = T.makeRegex' . (Utf8_ . val <$>) <$> p0- in O.replace ma1 (val <$> r0) b1----instance Replace' Once Utf8_ ByteString GroupReplacer where- replace' = replace_bs' marray_--instance Replace' All Utf8_ ByteString GroupReplacer where- replace' = replace_bs' marray_--{- ^ >>> replacer::GroupReplacer (Utf8_ ByteString)- replacer = defaultReplacer 1 tweak1- where tweak1 bs1 = toByteString' $- if bs1 == toByteString' "左" then- "ー右ー"- else "?"--- >>> runFn1 `shouldBe` toByteString "100メートルー右ー折後、左"- where runFn1 =- let rx1 = Pattern $ toByteString' "(?<=ル)(左)"- body1 = Body $ toByteString' "100メートル左折後、左"- in replace (All rx1) replacer body1 -}---replace_bs' f0 p0 r0 b0 =- let ma1 = f0 p1 b1- b1 = val <$> b0- p1 = T.makeRegex' . (Utf8_ . val <$>) <$> p0- in O.replace ma1 (val' r0) b1---{- ^ to tweak regex with 'Comp' or 'Exec', see "Text.Regex.Do.Type.Regex"-- note 'Once_Utf8' and 'All_Utf8' hints -}
+ src/Text/Regex/Do/Replace/Fast.hs view
@@ -0,0 +1,25 @@+{- | simple (no regex) fast replace on 'B.ByteString's ++All occurrences are replaced. There is no Once option++see 'S.replace' for detail -}+module Text.Regex.Do.Replace.Fast where++import qualified Data.ByteString.Search as S+import Data.ByteString as B +import qualified Data.ByteString.Lazy as L+import Text.Regex.Do.Match.Matchf+++{- | >>> replace "\n" "," "a\nbc\nde"++ "a,bc,de" -}+replace::ByteString -- ^ Pattern + -> ByteString -- ^ Replacement+ -> ByteString -- ^ Body+ -> ByteString+replace pat0+ replacement0+ body0 = B.concat . L.toChunks $ l+ where l = S.replace pat1 replacement0 body0+ !pat1 = checkPattern pat0
+ src/Text/Regex/Do/Replace/Latin.hs view
@@ -0,0 +1,84 @@+{- | for reliable results with Utf8 pattern or body,+ use "Text.Regex.Do.Pcre.Replace.Utf8" -}++module Text.Regex.Do.Replace.Latin+ (Replace(..)) where++import Text.Regex.Base.RegexLike as R+import Prelude as P+import Text.Regex.Do.Type.Do+import Text.Regex.Do.Type.Reexport as R+import Text.Regex.Do.Match.Matchf+import qualified Text.Regex.Do.Replace.Open as O+import Text.Regex.Do.Match.Regex as T+import Text.Regex.Do.Type.Extract+import Text.Regex.Do.Type.MatchHint+++{- | hint: 'All' | 'Once'++ pattern: 'R.Regex', 'String', 'ByteString' + + String | ByteString pattern may contains regex+ + body: 'String', 'ByteString'++ result is 'Either' String body: 'Left' String returns regex construction errors. +-} +class Replace hint pattern repl body out where+ replace::(Extract' body, RegexLike R.Regex body) => + hint pattern -> repl -> body -> out+++instance (R.RegexLike R.Regex b, O.Replace Maybe repl b) =>+ Replace Once R.Regex repl b b where+ replace (Once p0) = replace_rx p0 tagOnce+{- ^ succeeds unless 'GroupReplacer' fails due to mismatched pattern etc ++ repl: 'String' | 'ByteString' | 'GroupReplacer' repl+-}+++instance (R.RegexLike R.Regex b, O.Replace [] repl b) =>+ Replace All R.Regex repl b b where+ replace (All p0) = replace_rx p0 tagAll+{- ^ succeeds unless 'GroupReplacer' fails due to mismatched pattern etc ++ repl: 'String' | 'ByteString' | 'GroupReplacer' repl+-}++++instance (R.RegexLike R.Regex b, T.Regex b) => + Replace Once b b b (E b) where+ replace (Once p0) = replace_ p0 tagOnce+{- ^ b: 'String' | 'ByteString'-}+++instance (R.RegexLike R.Regex b, T.Regex b) => + Replace Once b (GroupReplacer b) b (E b) where+ replace (Once p0) = replace_ p0 tagOnce+{- ^ b: 'String' | 'ByteString'-}+++instance (R.RegexLike R.Regex b, T.Regex b) => + Replace All b b b (E b) where+ replace (All p0) = replace_ p0 tagAll+{- ^ b: 'String' | 'ByteString'-}+++instance (R.RegexLike R.Regex b, T.Regex b) => + Replace All b (GroupReplacer b) b (E b) where+ replace (All p0) = replace_ p0 tagAll+{- ^ b: 'String' | 'ByteString'-}+++replace_rx rx0 tag0 r0 b0 =+ let Right ma1 = marray_ (Right rx0) (tag0 b0) + in O.replace ma1 r0 b0+++replace_ p0 tag0 r0 b0 = + marray_ (T.makeRegex p0) (tag0 b0) >>= \ma1 ->+ Right $ O.replace ma1 r0 b0+
+ src/Text/Regex/Do/Replace/Open.hs view
@@ -0,0 +1,150 @@+{- | extensible and reusable replacement functions++Run replacement with your preferred content types e.g. "Data.Text" (implemented),++from search results with non-PCRE regex or non-regex libs++=== how to use: ++value replacement:++>>> replace (Just [(4,3)::PosLen]) "4567" ("abc 123 def"::Text)++"abc 4567 def"+++'GroupReplacer' : replace with a function++@+replacer::GroupReplacer Text+replacer = defaultReplacer 1 tweak1 -- 1: group 1 match. + where tweak1 str1 = case str1 of+ "123" -> "[1-2-3]"+ otherwise -> traceShow str1 "?"+@++>>> replace (Just ([(4,3)]::[PosLen])) replacer ("abc 123 def"::Text)++ "abc [1-2-3] def" -} ++module Text.Regex.Do.Replace.Open+ (Replace(..),+ defaultReplacer,+ getGroup,+ replaceMatch+ )+ where++import Text.Regex.Base.RegexLike as R+import Data.Array as A+import Prelude as P+import Text.Regex.Do.Type.Do+import Text.Regex.Do.Match.Result as R+import Text.Regex.Do.Type.Convert+import Text.Regex.Do.Type.Extract+++++class Replace f repl body where+ replace::(Extract' body, ToArray arr) =>+ f arr -> repl -> body -> body+++instance Replace Maybe b b where+ replace Nothing repl0 body0 = body0+ replace (Just ma0) repl0 body0 = firstGroup lpl1 (repl0, body0)+ where lpl1 = A.elems $ toArray ma0+++instance Replace [] b b where+ replace [] _ body0 = body0+ replace ma0 repl0 body0 =+ let lpl1 = R.poslen $ toArray <$> ma0::[[PosLen]]+ foldFn1 lpl1 acc1 = firstGroup lpl1 (repl0,acc1)+ in P.foldr foldFn1 body0 lpl1+++instance Replace Maybe (GroupReplacer b) b where+ replace Nothing _ body0 = body0+ replace (Just ma0) (GroupReplacer repl0) body0 =+ let a1 = ReplaceAcc {+ acc = body0,+ pos_adj = 0+ }+ in acc $ repl0 (toArray ma0) a1+++instance Replace [] (GroupReplacer b) b where+ replace [] _ body0 = body0+ replace ma0 (GroupReplacer repl0) body0 =+ let acc1 = ReplaceAcc { acc = body0, pos_adj = 0 }+ in acc $ P.foldl (flip repl0) acc1 $ toArray <$> ma0+++firstGroup::Extract' a =>+ [PosLen] -> (a,a) -> a+firstGroup (pl0:_) r1@(new0,a0) = acc $ replaceMatch pl0 (new0, acc1)+ where acc1 = ReplaceAcc {+ acc = a0,+ pos_adj = 0+ }+++-- dynamic+{- | Replaces specified (by idx) group match with value provided by (a -> a) fn.+ Works for one common simple use case++ 'GroupReplacer' can also be used with multi-group regex++ another custom dynamic replacer could e.g.+ inspect all group matches before looking up a replacement. -}+defaultReplacer::Extract' a =>+ Int -- ^ group idx. 1-based+ -> (a -> a) -- ^ (group match -> replacement) lookup+ -> GroupReplacer a+defaultReplacer idx0 tweak0 = GroupReplacer fn1+ where fn1 (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:++ * non-existing group idx will not error but return 'Nothing'+ * adjust for previous replacements length++ see 'defaultReplacer' source for use example+ -}+getGroup::R.Extract a =>+ ReplaceAcc a -> MatchArray -> Int -> Maybe a+getGroup acc0 ma0 idx0 = if idx0 < 1 || 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+++{- | replace group match while adjusting for previous replacements length++ see 'defaultReplacer' source for use example -}++replaceMatch::Extract' 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+++adjustPoslen::PosLen -> ReplaceAcc a -> PosLen+adjustPoslen (p0,l0) acc0 = (p0 + pos_adj acc0, l0)
+ src/Text/Regex/Do/Replace/Template.hs view
@@ -0,0 +1,149 @@+{- | formerly /Format/++ substitutes placeholder values with values from args+ + in lieu of /format/ function there are 2 operators: '<' and '>': no need to remember arg order. ++ ==== placeholder syntax:++ * index based++ { Int }++ * key based++ { 'String' | 'ByteString' | 'Text' }++ other placeholders may be implemented with++ "Text.Regex.Do.Pcre.Ascii.Replace" or "Text.Regex.Do.Pcre.Utf8.Replace" + + to avoid clash with 'Prelude':+ + @import Prelude hiding((\<),(\>))@ ++ or qualify '<' with alias e.g. (assuming this module is imported with F alias):+ + @F.<@ -}++module Text.Regex.Do.Replace.Template+ (Template(..),+ ReplaceOne(),+ Formatable) where++import Prelude as P hiding ((<),(>))+import Text.Regex.Do.Replace.Fast as S (replace)+import Text.Regex.Do.Type.Convert+import Data.ByteString as B+import Data.Text as T+++type Formatable a = (Template a [a], Template a [(a,a)])++{- | ==== implemented a:++ * 'String'+ * 'ByteString'+ * 'Text' + + a: template e.g. "today is {0}"+ + repl: replacement: [a] or [(a,a)]+ -}+class Template a repl where+ (<)::a -> repl -> a+ (>)::repl -> a -> a+ (>) repl0 template0 = template0 < repl0+ ++instance ReplaceOne Int a =>+ Template a [a] where+ (<) t0 a0 = foldr_idx foldFn_idx t0 a0+{- ^ === index based+ >>> ["перловка"] > "на первое {0}, на второе {0}" ++ "на первое перловка, на второе перловка"++ >>> "Polly {0} a {1}" < ["got","cracker"]++ "Polly got a cracker"+-}++foldFn_idx::ReplaceOne k v =>+ v -> (k, v) -> v+foldFn_idx v0 (i0, body1) = replaceOne body1 i0 v0++++instance ReplaceOne a a =>+ Template a [(a, a)] where+ (<) = P.foldr foldFn_map+{- ^=== key based+ key may be {any a}++ >>> "овчинка {a} не {b}" < [("a","выделки"),("b","стоит")]++ "овчинка выделки не стоит"+-}++++foldFn_map::ReplaceOne k v =>+ (k, v) -> v -> v+foldFn_map (k0, v0) body1 = replaceOne body1 k0 v0++++-- fold with index+type CustomerFn a b = (a -> (Int,b) -> b)++foldr_idx::CustomerFn a b -> b -> [a] -> b+foldr_idx fn0 init1 list0 = b1+ where i0 = P.length list0 - 1+ (-1,b1) = P.foldr (foldFn fn0) (i0,init1) list0+++foldFn::CustomerFn a b -> a -> (Int, b) -> (Int, b)+foldFn fn0 val0 t0@(i0, _) = (i0 - 1, b1)+ where b1 = fn0 val0 t0+++class ReplaceOne idx a where+ replaceOne::a -> idx -> a -> a+++instance ReplaceOne Int String where+ replaceOne body0 k0 v0 = toString bs1+ where pat1 = toByteString $ "{" ++ (show k0) ++ "}"+ repl1 = toByteString v0+ bs1 = S.replace pat1 repl1 $ toByteString body0+++instance ReplaceOne String String where+ replaceOne body0 k0 v0 = toString bs1+ where pat1 = toByteString $ "{" ++ k0 ++ "}"+ repl1 = toByteString v0+ bs1 = S.replace pat1 repl1 $ toByteString body0+++instance ReplaceOne Int ByteString where+ replaceOne body0 k0 v0 = S.replace pat1 repl1 body0+ where pat1 = toByteString $ "{" ++ (show k0) ++ "}"+ repl1 = v0+++instance ReplaceOne ByteString ByteString where+ replaceOne body0 k0 v0 = S.replace pat1 repl1 body0+ where pat1 = B.concat [toByteString "{", k0, toByteString "}"]+ repl1 = v0++++instance ReplaceOne Int Text where+ replaceOne body0 k0 v0 = T.replace pat1 v0 body0+ where pat1 = T.pack $ "{" ++ (show k0) ++ "}"+++instance ReplaceOne Text Text where+ replaceOne body0 k0 v0 = T.replace pat1 v0 body0+ where pat1 = T.concat [T.pack "{", k0, T.pack "}"]
+ src/Text/Regex/Do/Replace/Utf8.hs view
@@ -0,0 +1,119 @@+{- | see also "Text.Regex.Do.Pcre.Replace.Latin"++ __'toByteString'__ converts String to 'ByteString' -}++module Text.Regex.Do.Replace.Utf8+ (Replace(..)) where++import Prelude as P+import Text.Regex.Do.Type.Do+import Text.Regex.Do.Match.Matchf+import qualified Text.Regex.Do.Replace.Open as O+import Text.Regex.Do.Match.Regex as T+import Text.Regex.Do.Type.MatchHint+import Text.Regex.Do.Type.Convert+import Data.ByteString+import Text.Regex.Do.Type.Extract+import Text.Regex.Do.Type.Reexport as R+import Text.Regex.Base.RegexLike as R+import Text.Regex.Do.Match.Option+++{- | see "Text.Regex.Do.Pcre.Replace.Latin" for implemented types++ 'GroupReplacer' is implemented only for 'ByteString' -}++class Replace hint pattern repl body out where+ replace::(Extract' body, RegexLike R.Regex body) =>+ hint pattern -> repl -> body -> out+++instance Replace Once R.Regex String String String where+ replace (Once p0) r0 b0 = + let b1 = toByteString b0+ r1 = toByteString r0 + Right ma1 = marray_ (Right p0) (tagOnce b1) + in toString $ O.replace ma1 r1 b1+-- ^ always succeeds++instance Replace All R.Regex String String String where+ replace (All p0) r0 b0 =+ let b1 = toByteString b0+ r1 = toByteString r0+ Right ma1 = marray_ (Right p0) (tagAll b1)+ in toString $ O.replace ma1 r1 b1+-- ^ always succeeds+++instance O.Replace Maybe repl ByteString => + Replace Once R.Regex repl ByteString ByteString where+ replace (Once p0) r0 b0 =+ let Right ma1 = marray_ (Right p0) (tagOnce b0)+ in O.replace ma1 r0 b0+{- ^ succeeds unless 'GroupReplacer' fails due to mismatched pattern etc ++repl: 'ByteString' | 'GroupReplacer' 'ByteString' +-}+++instance O.Replace [] repl ByteString => + Replace All R.Regex repl ByteString ByteString where+ replace (All p0) r0 b0 =+ let Right ma1 = marray_ (Right p0) (tagAll b0)+ in O.replace ma1 r0 b0+{- ^ succeeds unless 'GroupReplacer' fails due to mismatched pattern etc ++repl: 'ByteString' | 'GroupReplacer' 'ByteString' +-}++++instance Replace Once String String String (E String) where+ replace (Once p0) = replace_str p0 tagOnce+++instance Replace All String String String (E String) where+ replace (All p0) = replace_str p0 tagAll +++instance Replace Once ByteString ByteString ByteString (E ByteString) where+ replace (Once p0) = replace_bs p0 tagOnce+++instance Replace All ByteString ByteString ByteString (E ByteString)where+ replace (All p0) = replace_bs p0 tagAll+++instance Replace Once ByteString (GroupReplacer ByteString) ByteString (E ByteString) where+ replace (Once p0) = replace_bs p0 tagOnce++instance Replace All ByteString (GroupReplacer ByteString) ByteString (E ByteString) where+ replace (All p0) = replace_bs p0 tagAll+{- ^ +@+replacer::GroupReplacer ByteString+replacer = defaultReplacer 1 tweak1+ where tweak1 bs1 = toByteString' $+ if bs1 == toByteString "左" then+ "ー右ー"+ else "?"+++ runFn1 \`shouldBe\` toByteString "100メートルー右ー折後、左"+ where runFn1 = let rx1 = toByteString "(?<=ル)(左)"+ body1 = toByteString "100メートル左折後、左"+ in replace (All rx1) replacer body1 +@ -}++replace_str p0 tag0 r0 b0 =+ let b1 = toByteString b0+ r1 = toByteString r0+ p1 = T.makeRegexOpt p0 [Utf8] [] + in marray_ p1 (tag0 b0) >>= \ma1 ->+ Right $ toString $ O.replace ma1 r1 b1+++replace_bs p0 tag0 r0 b0 =+ marray_ (T.makeRegexOpt p0 [Utf8] []) (tag0 b0) >>= \ma1 ->+ Right $ O.replace ma1 r0 b0+
− src/Text/Regex/Do/ReplaceOpen.hs
@@ -1,147 +0,0 @@-{- | extensible and reusable replacement functions-- Run replacement with your preferred content types e.g. "Data.Text",- from search results with non-PCRE regex or non-regex libs-- open an issue or a PR on <https://github.com/ciez/regex-do git> to request a new 'Extract'' instance-- "Data.Text" instance already works -}--module Text.Regex.Do.ReplaceOpen- (ReplaceOpen(..),- defaultReplacer,- getGroup,- replaceMatch- )- where--import Text.Regex.Base.RegexLike as R-import Data.Array as A-import Prelude as P-import Text.Regex.Do.Type.Do-import Text.Regex.Do.Result as R-import Text.Regex.Do.Convert-import Text.Regex.Do.Type.Extract---{- | 'Replacement':-- >>> replace (Just [(4,3)::PosLen]) (Replacement "4567") (Body "abc 123 def"::Body Text)-- "abc 4567 def"--- 'GroupReplacer' :-- >>> replacer::GroupReplacer Text- replacer = defaultReplacer 1 tweak1 -- 1: first match in group- where tweak1 str1 = case str1 of- "123" -> "[1-2-3]"- otherwise -> traceShow str1 "?"-- >>> replace (Just ([(4,3),(8,2)]::[PosLen])) replacer (Body "abc 123 def"::Body Text)-- "abc [1-2-3] def" -}--class ReplaceOpen f r where- replace::(Extract' a, ToArray arr) =>- f arr -> r a -> Body a -> a---instance ReplaceOpen Maybe Replacement where- replace Nothing (Replacement repl0) (Body b0) = b0- replace (Just ma0) (Replacement repl0) (Body b0) = firstGroup lpl1 (repl0, b0)- where lpl1 = A.elems $ toArray ma0---instance ReplaceOpen [] Replacement where- replace [] _ (Body b0) = b0- replace ma0 (Replacement repl0) (Body b0) =- let lpl1 = R.poslen $ toArray <$> ma0::[[PosLen]]- foldFn1 lpl1 acc1 = firstGroup lpl1 (repl0,acc1)- in P.foldr foldFn1 b0 lpl1---instance ReplaceOpen Maybe GroupReplacer where- replace Nothing _ (Body b0) = b0- replace (Just ma0) (GroupReplacer repl0) (Body b0) =- let a1 = ReplaceAcc {- acc = b0,- pos_adj = 0- }- in acc $ repl0 (toArray ma0) a1---instance ReplaceOpen [] GroupReplacer where- replace [] _ (Body b0) = b0- replace ma0 (GroupReplacer repl0) (Body b0) =- let acc1 = ReplaceAcc { acc = b0, pos_adj = 0 }- in acc $ P.foldl (flip repl0) acc1 $ toArray <$> ma0---firstGroup::Extract' a =>- [PosLen] -> (a,a) -> a-firstGroup (pl0:_) r1@(new0,a0) = acc $ replaceMatch pl0 (new0, acc1)- where acc1 = ReplaceAcc {- acc = a0,- pos_adj = 0- }----- dynamic-{- | Replaces specified (by idx) group match with tweaked value.- Works for one common simple use case-- 'GroupReplacer' can be used with complicated regex-- another custom dynamic replacer could e.g.- inspect all group matches before looking up a replacement. -}-defaultReplacer::Extract' a =>- Int -- ^ group idx- -> (a -> a) -- ^ (group match -> replacement) tweak- -> GroupReplacer a-defaultReplacer idx0 tweak0 = GroupReplacer fn1- where fn1 (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:-- * non-existing group idx will not error but return 'Nothing'- * adjust for previous replacements length-- see 'defaultReplacer' source for use example- -}-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---{- | replace group match while adjusting for previous replacements length-- see 'defaultReplacer' source for use example -}--replaceMatch::Extract' 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---adjustPoslen::PosLen -> ReplaceAcc a -> PosLen-adjustPoslen (p0,l0) acc0 = (p0 + pos_adj acc0, l0)
− src/Text/Regex/Do/Result.hs
@@ -1,22 +0,0 @@-module Text.Regex.Do.Result where--import qualified Data.Array as A(elems)-import Text.Regex.Base.RegexLike as R-import Text.Regex.Do.Type.Do---- | match offset, length-poslen::Functor f =>- f MatchArray -> f [PosLen]-poslen = (A.elems <$>)----- | all groups-allMatches::(Functor f, R.Extract b) =>- Body b -> f MatchArray -> f [b]-allMatches hay0 results0 = groupMatch hay0 <$> results0----- | matches for one group-groupMatch::R.Extract b =>- Body b -> MatchArray -> [b]-groupMatch (Body b0) a0 = [R.extract tuple1 b0 | tuple1 <- A.elems a0]
src/Text/Regex/Do/Split.hs view
@@ -1,125 +1,111 @@ {- | see "Data.ByteString.Search" package + break, split ops on 'ByteString'+ regex is treated as ordinary String+ + break & split are now '/', '-/', '/-' + + replace moved to "Text.Regex.Do.Replace.Fast" -} module Text.Regex.Do.Split- (break,- replace,- split,- KeepNeedle(..)) where+ (Split(..),+ SplitFront(..),+ SplitEnd(..),+ T,L+ ) where import qualified Data.ByteString.Search as S-import Text.Regex.Do.Type.Do hiding (replace) import Data.ByteString as B hiding (break, breakEnd, split)-import qualified Data.ByteString.Lazy as L-import Prelude hiding (break)+import Prelude hiding (break,(/))+import Text.Regex.Do.Match.Matchf -data KeepNeedle = Drop -- ^ needle between parts disappears- | Front -- ^ needle sticks to front of next part- | End -- ^ needle sticks to end of previous part+-- | Break result: tuple+type T = (B.ByteString,B.ByteString) -{- | >>> replace (Pattern "\n") (Replacement ",") (Body "a\nbc\nde")+-- | Split result: list+type L = [B.ByteString] - "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 +{- | slices 'ByteString'. drops needle+ + to avoid clash with 'Prelude':+ + @import Prelude hiding((/))@ --- ordinary: a b--- front: a \nb--- end: a\n b+ or qualify '/' with alias e.g. (assuming this module is imported with S alias):+ + @S./@ + + body -> pattern -> result+ -}+class Split out where+ (/)::ByteString -> ByteString -> out -{- | >>> break Drop (Pattern "\n") (Body "a\nbc\nde") - ("a", "bc\\nde")+instance Split (ByteString,ByteString) where+ (/) body0 pat0 = (h1,t2)+ where (h1,t1) = S.breakOn pat1 body0+ len1 = B.length pat1+ t2 = B.drop len1 t1+ !pat1 = checkPattern pat0+{- ^ >>> "a\nbc\nde" / "\n" + ("a", "bc\\nde") -} - >>> break Front (Pattern "\n") (Body "a\nbc\nde") - ("a", "\\nbc\\nde")+-- | keep needle \@ front+class SplitFront out where+ (-/)::ByteString + -> ByteString + -> out - >>> break End (Pattern "\n") (Body "a\nbc\nde")-- ("a\\n", "bc\\nde") -}--break::KeepNeedle ->- Pattern ByteString -> Body ByteString ->- (ByteString, ByteString)-break case0 = case case0 of- Drop -> break'- Front -> breakFront- End -> breakEnd-+instance SplitFront (ByteString,ByteString) where+ (-/) body0 pat0 = S.breakOn pat1 body0+ where !pat1 = checkPattern pat0+{- ^ >>> "a\nbc\nde" -/ "\n" -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+ ("a", "\\nbc\\nde") -} -breakFront::Pattern ByteString -> Body ByteString -> (ByteString, ByteString)-breakFront (Pattern pat0)- (Body b0) = S.breakOn pat1 b0- where !pat1 = checkPattern pat0+-- | keep needle \@ end+class SplitEnd out where+ (/-)::ByteString + -> ByteString + -> out -breakEnd::Pattern ByteString -> Body ByteString -> (ByteString, ByteString)-breakEnd (Pattern pat0)- (Body b0) = S.breakAfter pat1 b0- where !pat1 = checkPattern pat0-+instance SplitEnd (ByteString,ByteString) where+ (/-) body0 pat0 = S.breakAfter pat1 body0+ where !pat1 = checkPattern pat0+{- ^ >>> "a\nbc\nde" /- "\n" + ("a\\n", "bc\\nde") -} -{- | >>> split Drop (Pattern " ") (Body "a bc de")-- \["a", "bc", "de"]-- /space may be used/-- >>> split Front (Pattern "\n") (Body "a\nbc\nde")+instance Split [ByteString] where+ (/) body0 pat0 = S.split pat1 body0+ where !pat1 = checkPattern pat0+{- ^ >>> "a bc de" / " " -- space may be used - \["a", "\\nbc", "\\nde"]+ \["a", "bc", "de"] -} - >>> split End (Pattern "\n") (Body "a\nbc\nde")-- \["a\\n", "bc\\n", "de"] -}+instance SplitFront [ByteString] where+ (-/) body0 pat0 = S.splitKeepFront pat1 body0+ where !pat1 = checkPattern pat0+{- ^ >>> "a\nbc\nde" -/ "\n" -split::KeepNeedle ->- Pattern ByteString -> Body ByteString ->- [ByteString]-split case0 = case case0 of- Drop -> split'- Front -> splitFront- End -> splitEnd+ \["a", "\\nbc", "\\nde"] -} -split'::Pattern ByteString -> Body ByteString -> [ByteString]-split' (Pattern pat0)- (Body b0) = S.split pat1 b0- where !pat1 = checkPattern pat0--splitEnd::Pattern ByteString -> Body ByteString -> [ByteString]-splitEnd (Pattern pat0)- (Body b0) = S.splitKeepEnd pat1 b0- where !pat1 = checkPattern pat0--splitFront::Pattern ByteString -> Body ByteString -> [ByteString]-splitFront (Pattern pat0)- (Body b0) = S.splitKeepFront pat1 b0- where !pat1 = checkPattern pat0+instance SplitEnd [ByteString] where+ (/-) body0 pat0 = S.splitKeepEnd pat1 body0+ where !pat1 = checkPattern pat0+{- ^ >>> "a\nbc\nde" /- "\n" + \["a\\n", "bc\\n", "de"] -} -checkPattern::ByteString -> ByteString-checkPattern bs0 = if bs0 == B.empty then error "empty pattern"- else bs0
src/Text/Regex/Do/Trim.hs view
@@ -1,14 +1,13 @@ module Text.Regex.Do.Trim where -import Text.Regex.Do.Type.Do import Data.Char(isSpace) import qualified Data.ByteString as B import qualified Data.Text as T-import Text.Regex.Do.Convert-import Text.Regex.Do.Pcre.Ascii.Replace+import Text.Regex.Do.Type.Convert+import Text.Regex.Do.Replace.Latin import Text.Regex.Do.Type.MatchHint-import Text.Regex.Do.Type.Regex-import Text.Regex.Do.Pcre.Option+import Text.Regex.Do.Match.Regex+import Text.Regex.Do.Match.Option {- | removes leading and trailing spaces and tabs -}@@ -18,11 +17,11 @@ instance Trim B.ByteString where- trim bs1 = replace rx2 repl1 (All bs1)- where repl1 = Replacement B.empty+ trim bs1 = replace (All rx3) repl1 bs1+ where repl1 = B.empty rx1 = "(^[\\s\\t]+)|([\\s\\t]+$)"- rx2 = let p1 = Pattern $ toByteString rx1- in makeRegexOpt p1 [Blank] []+ rx2 = toByteString rx1+ Right rx3 = makeRegexOpt rx2 [Blank] [] instance Trim String where
+ src/Text/Regex/Do/Type/Convert.hs view
@@ -0,0 +1,31 @@+module Text.Regex.Do.Type.Convert where++import qualified Data.Text.Encoding as E+import qualified Data.Text as T+import Data.ByteString as B+import Text.Regex.Do.Type.Do+import Text.Regex.Base.RegexLike as R+import Data.Array as A+import Prelude as P+++-- | both Ascii and Utf8+toByteString::String -> ByteString+toByteString = E.encodeUtf8 . T.pack+++-- | both Ascii and Utf8+toString::ByteString -> String+toString = T.unpack . E.decodeUtf8++++class ToArray a where+ toArray::a -> MatchArray++instance ToArray MatchArray where+ toArray = id++instance ToArray [PosLen] where+ toArray [] = listArray (0,0) []+ toArray lpl0 = listArray (1, P.length lpl0) lpl0
src/Text/Regex/Do/Type/Do.hs view
@@ -3,7 +3,7 @@ import Text.Regex.Base.RegexLike as R --- | see "Text.Regex.Do.Pcre.ReplaceOpen" 'defaultReplacer' for example implementation+-- | see "Text.Regex.Do.Replace.Open" 'defaultReplacer' for example implementation newtype GroupReplacer b = GroupReplacer (MatchArray -> ReplaceAcc b -> ReplaceAcc b) -- MatchArray -> acc -> acc data ReplaceAcc b = ReplaceAcc {@@ -16,13 +16,6 @@ --- | Needle-data Pattern a = Pattern a deriving (Functor) -- Bs, String, RegexPcre-instance Applicative Pattern where- pure p0 = Pattern p0- (<*>) (Pattern f0) (Pattern a0) = Pattern $ f0 a0-- -- | Haystack data Body b = Body b deriving (Functor) -- Bs, String instance Applicative Body where@@ -30,46 +23,9 @@ (<*>) (Body f0) (Body a0) = Body $ f0 a0 -data Replacement r = Replacement r deriving (Functor) -- Bs, String-instance Applicative Replacement where- pure p0 = Replacement p0- (<*>) (Replacement f0) (Replacement a0) = Replacement $ f0 a0- -- | Offset, Length type PosLen = (MatchOffset, MatchLength) --newtype Utf8_ a = Utf8_ a -- ^ values- deriving (Functor,Eq,Ord)--instance Applicative Utf8_ where- pure p0 = Utf8_ p0- (<*>) (Utf8_ f0) (Utf8_ a0) = Utf8_ $ f0 a0----- ^ does not do any codec. Plain wrap / unwrap newtype-class Enc enc where- val::enc a -> a- enc::a -> enc a---- ^ does not do any codec. Plain wrap / unwrap newtype-class Enc' f enc where- val'::f (enc a) -> f a- enc'::f a -> f (enc a)---instance Enc Utf8_ where- val (Utf8_ v0) = v0- enc = Utf8_---instance Enc enc => Enc' GroupReplacer enc where- val' (GroupReplacer fn0) = GroupReplacer $- \ma1 acc1 -> val <$> (fn0 ma1 $ enc <$> acc1)- enc' (GroupReplacer fn0) = GroupReplacer $- \ma1 acc1 -> enc <$> (fn0 ma1 $ val <$> acc1)--instance Enc enc => Enc' Replacement enc where- val' = (val <$>)- enc' = (enc <$>)+{-| 'Left' String returns regex construction error -}+type E a = Either String a
src/Text/Regex/Do/Type/Extract.hs view
@@ -27,17 +27,6 @@ len' = B.length -instance Extract (Utf8_ B.ByteString) where- before i0 = (before i0 <$>)- after i0 = (after i0 <$>)- empty = Utf8_ R.empty---instance Extract' (Utf8_ B.ByteString) where- concat' = Utf8_ . B.concat . (val <$>)- len' = B.length . val-- instance Extract Text where before = T.take after = T.drop
src/Text/Regex/Do/Type/MatchHint.hs view
@@ -1,10 +1,10 @@ module Text.Regex.Do.Type.MatchHint where newtype Test a = Test a -- ^ test: does body match pattern?-newtype Once a = Once a -- ^ match / replace once+newtype Once a = Once a -- ^ replace once deriving (Functor) -newtype All a = All a -- ^ match / replace all+newtype All a = All a -- ^ replace all deriving (Functor) newtype PosLen' a = PosLen' a -- ^ once@@ -45,7 +45,3 @@ instance Applicative All where pure p0 = All p0 (<*>) (All f0) (All a0) = All $ f0 a0---swap::Hint hint => hint a -> b -> hint b-swap _ = hint
− src/Text/Regex/Do/Type/Regex.hs
@@ -1,121 +0,0 @@-module Text.Regex.Do.Type.Regex- (Regex(..),- makeRegex',- makeRegexOpt',- RegexResult(..),- Rx_, Opt_, Ro_) where--import qualified Text.Regex.Base.RegexLike as R-import qualified Text.Regex.Do.Type.Reexport as R-import Data.ByteString-import Text.Regex.Do.Type.Do-import Text.Regex.Do.Pcre.Option---class Regex a where- makeRegex::Pattern a -> R.Regex- makeRegexM::Monad m => Pattern a -> m R.Regex- makeRegexOpt::Pattern a -> [Comp] -> [Exec] -> R.Regex- makeRegexOptM::Monad m => Pattern a -> [Comp] -> [Exec] -> m R.Regex--{- ^ monadic-- * 'makeRegexM'- * 'makeRegexOptM'-- let catch regex construction errors-- for 'm' to catch errors, implement 'fail' in 'm'-- default 'm' implementation: 'RegexResult'-- ==== makeRegexM test case:-- >>> it "RegexResult test case" $ do- rx1 `shouldNotSatisfy` isok1- rx2 `shouldSatisfy` isok1- where rx1 = T.makeRegexM $ Pattern "[["::RegexResult R.Regex- rx2 = T.makeRegexM $ Pattern "."::RegexResult R.Regex- isok1 (RegexResult (Left e1)) = traceShow e1 False- isok1 _ = True-- >>> instance Show (RegexResult R.Regex) where- show _ = "bon" -}--makeRegex'::Regex a => Pattern a -> Pattern R.Regex-makeRegex' = Pattern . makeRegex--makeRegexOpt'::Regex a => Pattern a -> [Comp] -> [Exec] -> Pattern R.Regex-makeRegexOpt' p0 c0 e0 = Pattern $ makeRegexOpt p0 c0 e0----instance Regex a => Regex (Utf8_ a) where- makeRegex p0 = makeRegexOpt (Pattern val <*> p0) [Utf8] []- makeRegexM p0 = makeRegexOptM (Pattern val <*> p0) [Utf8] []- makeRegexOpt p0 c0 e0 = makeRegexOpt (Pattern val <*> p0) (Utf8:c0) e0- makeRegexOptM p0 c0 e0 = makeRegexOptM (Pattern val <*> p0) (Utf8:c0) e0---instance Regex ByteString where- makeRegex (Pattern p0) = R.makeRegex p0- makeRegexM (Pattern p0) = R.makeRegexM p0- makeRegexOpt = makeRegexOpts- makeRegexOptM = makeRegexOptsM---instance Regex String where- makeRegex (Pattern p0) = R.makeRegex p0- makeRegexM (Pattern p0) = R.makeRegexM p0- makeRegexOpt = makeRegexOpts- makeRegexOptM = makeRegexOptsM---instance Regex R.Regex where- makeRegex (Pattern p0) = p0- makeRegexM (Pattern p0) = pure p0- makeRegexOpt (Pattern p0) _ _ = p0- makeRegexOptM (Pattern p0) _ _ = pure p0----- | tweak Regex with options-makeRegexOpts::Opt_ a =>- Pattern a ->- [Comp] -> [Exec] ->- R.Regex-makeRegexOpts (Pattern pat0) comp0 exec0 = rx1- where c1 = comp comp0- e1 = exec exec0- rx1 = R.makeRegexOpts c1 e1 pat0---makeRegexOptsM::(Monad m, Opt_ a) =>- Pattern a ->- [Comp] -> [Exec] ->- m R.Regex-makeRegexOptsM (Pattern pat0) comp0 exec0 = rx1- where c1 = comp comp0- e1 = exec exec0- rx1 = R.makeRegexOptsM c1 e1 pat0----type Rx_ a b = (Regex a, R.Extract b, R.RegexLike R.Regex b)-type Opt_ a = R.RegexMaker R.Regex R.CompOption R.ExecOption a-type Ro_ rx = (Regex rx, Opt_ rx)---{- | catches regex construction __errors__ -}-newtype RegexResult a = RegexResult (Either [String] a) deriving (Functor)--instance Applicative RegexResult where- pure = RegexResult . Right- (<*>) (RegexResult (Left e1)) (RegexResult (Left e2)) = RegexResult $ Left $ e1 ++ e2- (<*>) (RegexResult (Right fn0)) (RegexResult (Left e1)) = RegexResult $ Left e1- (<*>) (RegexResult (Left e1)) (RegexResult (Right r1)) = RegexResult $ Left e1- (<*>) (RegexResult (Right fn0)) (RegexResult (Right a0)) = pure $ fn0 a0--instance Monad RegexResult where- (>>=) (RegexResult (Left e1)) fn0 = RegexResult $ Left e1- (>>=) (RegexResult (Right a0)) fn0 = fn0 a0- fail s0 = RegexResult $ Left [s0]
test/Main.hs view
@@ -9,6 +9,7 @@ import qualified TestRegex.TestTrim as T import qualified TestRegex.TestMakeRegexM as E + main::IO() main = do F.main@@ -16,6 +17,6 @@ S.main T.main O.main- R.main U.main+ R.main E.main
test/TestRegex/TestFormat.hs view
@@ -1,12 +1,13 @@ module TestRegex.TestFormat where import Test.Hspec-import Text.Regex.Do.Format+import Text.Regex.Do.Replace.Template import Text.Regex.Do.Pad import Data.String-import Text.Regex.Do.Convert+import Text.Regex.Do.Type.Convert import Data.ByteString import Data.Text as T+import Prelude hiding ((<),(>)) main::IO()@@ -23,15 +24,17 @@ oneFormat fn0 idx0 = hspec $ do describe "Habase.Bin.Format" $ do it "list arg 0,0 repl []" $- format (fn0 "на первое {0}, на второе {0}") (fn0 <$> []) `shouldBe` (fn0 "на первое {0}, на второе {0}")+ (fn0 "на первое {0}, на второе {0}") < (fn0 <$> []) `shouldBe` (fn0 "на первое {0}, на второе {0}") it "list arg 0,0" $- format (fn0 "на первое {0}, на второе {0}") [fn0 "перловка"] `shouldBe` (fn0 "на первое перловка, на второе перловка")+ (fn0 "на первое {0}, на второе {0}") < [fn0 "перловка"] `shouldBe` (fn0 "на первое перловка, на второе перловка")+ it "list arg 0,0 >" $+ [fn0 "перловка"] > (fn0 "на первое {0}, на второе {0}") `shouldBe` (fn0 "на первое перловка, на второе перловка") it "list arg 0,1" $ do- format (fn0 "Polly {0} a {1}") [fn0 "gets",fn0 "cracker"] `shouldBe` (fn0 "Polly gets a cracker")- format (fn0 "{10} {15} {21}") (idx0 <$> [0..22]) `shouldBe` (fn0 "10 15 21")- format (fn0 "{ten} {пятнадцать} {vingt}") [(fn0 "ten", fn0 "10"), (fn0 "пятнадцать", fn0 "15"), (fn0 "vingt", fn0 "20")] `shouldBe` (fn0 "10 15 20")+ (fn0 "Polly {0} a {1}") < [fn0 "gets",fn0 "cracker"] `shouldBe` (fn0 "Polly gets a cracker")+ (fn0 "{10} {15} {21}") < (idx0 <$> [0..22]) `shouldBe` (fn0 "10 15 21")+ (fn0 "{ten} {пятнадцать} {vingt}") < [(fn0 "ten", fn0 "10"), (fn0 "пятнадцать", fn0 "15"), (fn0 "vingt", fn0 "20")] `shouldBe` (fn0 "10 15 20") it "map arg" $- format (fn0 "овчинка {a} не {b}") [(fn0 "a", fn0 "выделки"),(fn0 "b", fn0 "стоит")] `shouldBe` (fn0 "овчинка выделки не стоит")+ (fn0 "овчинка {a} не {b}") < [(fn0 "a", fn0 "выделки"),(fn0 "b", fn0 "стоит")] `shouldBe` (fn0 "овчинка выделки не стоит") it "pad" $ pad '-' 5 "abc" `shouldBe` "--abc" it "pad'" $ pad' '-' 5 "abc" `shouldBe` "abc--"
test/TestRegex/TestMakeRegexM.hs view
@@ -3,8 +3,7 @@ import Test.Hspec import Text.Regex.Do.Type.Reexport as R-import Text.Regex.Do.Type.Regex as T-import Text.Regex.Do.Type.Do as T+import Text.Regex.Do.Match.Regex as T import Debug.Trace @@ -14,12 +13,12 @@ it "RegexResult test case" $ do rx1 `shouldNotSatisfy` isok1 rx2 `shouldSatisfy` isok1- where rx1 = T.makeRegexM $ Pattern "[["::RegexResult R.Regex- rx2 = T.makeRegexM $ Pattern "."::RegexResult R.Regex+ where rx1 = T.makeRegex "[["::E R.Regex+ rx2 = T.makeRegex "."::E R.Regex - isok1 (RegexResult (Left e1)) = traceShow e1 False+ isok1 (Left e1) = traceShow e1 False isok1 _ = True -instance Show (RegexResult R.Regex) where+instance Show (R.Regex) where show _ = "rx"
test/TestRegex/TestPcre.hs view
@@ -2,46 +2,46 @@ import Test.Hspec import Text.Regex.Do.Type.Do as M-import Text.Regex.Do.Pcre.Ascii.Match as M-import Text.Regex.Do.Pcre.Utf8.Match as U-import Text.Regex.Do.Pcre.Ascii.MatchHint as S-import Text.Regex.Do.Pcre.Utf8.MatchHint as Su-import Text.Regex.Do.Convert+import Text.Regex.Do.Match.Latin as M+import Text.Regex.Do.Match.Utf8 as U+import Text.Regex.Do.Type.Convert import Data.ByteString-import Text.Regex.Do.Type.MatchHint as S-import Text.Regex.Do.Type.Regex+import Text.Regex.Do.Match.Regex+import Text.Regex.Do.Match.Option main::IO() main = hspec $ describe " matchTest " $ do- it " ?String " $ (M.match (Pattern n) h::[String]) `shouldBe` ["d1"]- it " [String] " $ (M.match (Pattern n) h::[[String]]) `shouldBe` [["d1"],["d1"]]- it " ?ByteString " $ (M.match (Pattern $ b n) (b <$> h)::[ByteString]) `shouldBe` [b "d1"]- it " [ByteString] " $ (M.match (Pattern $ b n) (b <$> h)::[[ByteString]]) `shouldBe` [[b "d1"],[b "d1"]]- it " ша " $ S.match (Test $ Pattern ("^ша"::String)) (Body "шапка") `shouldBe` True- it " cd " $ S.match (Test $ Pattern ("^cd"::String)) (Body "abcde") `shouldBe` False- it " cd " $ S.match (PosLen' $ Pattern ("^cd"::String)) (Body "abcde") `shouldBe` []- it " ab " $ S.match (Test $ Pattern ("^ab"::String)) (Body "abc") `shouldBe` True- it "doc 1" $ Test ("в"::ByteString) S.=~ "тихо в лесу" `shouldBe` True- it "doc 1.2" $ Test ("chilly"::ByteString) S.=~ "it's chilly inside, chilly outside" `shouldBe` True- it "doc 1.3" $ Test (toByteString "в") Su.=~ toByteString "тихо в лесу" `shouldBe` True- it "doc 2" $ S.Once ("^all"::String) S.=~ "all the time" `shouldBe` ["all"]- it "doc 3" $ S.Once ("^all"::ByteString) S.=~ "all the time" `shouldBe` ["all"]- it "doc 4" $ S.All ("chilly"::ByteString) S.=~ "it's chilly inside, chilly outside" `shouldBe` ([["chilly"],["chilly"]])- it "doc 5" $ PosLen' ("и"::String) S.=~ "бывает и хуже" `shouldBe` [(13,2)]- it "doc 6" $ PosLen' ("à"::String) S.=~ "tourner à gauche" `shouldBe` [(8,2)]+ it " ?String " $ (n M.~? h::E [String]) `shouldBe` (Right ["d1"])+ it " [String] " $ (n M.~* h::E [[String]]) `shouldBe` (Right [["d1"],["d1"]])+ it " ?ByteString " $ (b n M.~? (b h)::E [ByteString]) `shouldBe` (Right [b "d1"])+ it " [ByteString] " $ (b n M.~* (b h)::E [[ByteString]]) `shouldBe` (Right [[b "d1"],[b "d1"]])+ it " ша " $ ("^ша"::String) M.~? ("шапка"::String) `shouldBe` (Right True::E Bool)+ it " cd " $ ("^cd"::String) M.~? ("abcde"::String) `shouldBe` (Right False::E Bool)+ it " cd " $ ("^cd"::String) M.~? ("abcde"::String) `shouldBe` (Right []::E [PosLen])+ it " ab " $ ("^ab"::String) M.~? ("abc"::String) `shouldBe` (Right True::E Bool)+ it "doc 1" $ ("в"::String) U.~? ("тихо в лесу"::String) `shouldBe` (Right True::E Bool)+ it "doc 1.2" $ ("chilly"::ByteString) U.~? ("it's chilly inside, chilly outside"::ByteString) `shouldBe` (Right True::E Bool)+ it "doc 1.3" $ (toByteString "в") U.~? toByteString "тихо в лесу" `shouldBe` (Right True::E Bool)+ it "doc 2" $ ("^all"::String) M.~? ("all the time"::String) `shouldBe` (Right ["all"]::E [String])+ it "doc 3" $ ("^all"::ByteString) M.~? ("all the time"::ByteString) `shouldBe` (Right ["all"]::E [ByteString])+ it "doc 4" $ ("chilly"::ByteString) M.~* ("it's chilly inside, chilly outside"::ByteString) `shouldBe` (Right [["chilly"],["chilly"]]::E [[ByteString]])+ it "doc 5" $ ("и"::String) U.~? ("бывает и хуже"::String) `shouldBe` (Right [(13,2)]::E [PosLen])+ it "doc 6" $ ("à"::String) U.~? ("tourner à gauche"::String) `shouldBe` (Right [(8,2)]::E [PosLen]) it "doc 7" $ do- let rx1 = makeRegexOpt' (Pattern $ toByteString'"左") [] []- rx2 = Utf8_ <$> rx1- m1 = U.match rx2 (Body $ toByteString' "100メートル左折後、左")::[ByteString]+ let Right rx1 = makeRegexOpt (toByteString "左") [Utf8] []+ m1 = rx1 U.~? (toByteString "100メートル左折後、左")::[ByteString] m1 `shouldBe` [toByteString "左"] it "doc 8" $ do- let t1 = toByteString "в" U.=~ ("тихо в лесу"::String)::Bool+ let Right t1 = ("в"::String) U.~? ("тихо в лесу"::String)::E Bool t1 `shouldBe` True it "doc 9" $ do- let m1 = ("well"::String) U.=~ ("all is well that ends well"::String)::[[String]]- m1 `shouldBe` ([["well"],["well"]]::[[String]])+ let Right m1 = ("лес"::String) U.~* ("Залесью, залесью…"::String)::E [[String]]+ m1 `shouldBe` ([["лес"],["лес"]]::[[String]])+ it "doc 10" $ do+ let Right m1 = ("^熱"::String) U.~? ("熱い午後"::String)::E [String]+ m1 `shouldBe` ["熱"] n = "d1"-h = Body "abcd1efg d1hij"+h = "abcd1efg d1hij" b = toByteString
test/TestRegex/TestReplace.hs view
@@ -4,15 +4,15 @@ import Test.Hspec import Text.Regex.Do.Type.Do -import Text.Regex.Do.Pcre.Ascii.Replace as R-import qualified Text.Regex.Do.Pcre.Utf8.Replace as U-import Text.Regex.Do.ReplaceOpen hiding (replace)-import Text.Regex.Do.Convert-import Data.ByteString as B+import Text.Regex.Do.Replace.Latin as R+import qualified Text.Regex.Do.Replace.Utf8 as U+import Text.Regex.Do.Replace.Open hiding (replace)+import Text.Regex.Do.Type.Convert import Debug.Trace import Text.Regex.Do.Type.MatchHint---import Text.Regex.Do.Pcre.Option+import Data.ByteString + main::IO() main = do onceUtf8@@ -26,63 +26,56 @@ describe "Pcre.Replace doc" $ do it "replaceGroup 1" $ do replace (Once "\\w=(\\d{1,3})") replacer "a=101 b=3 12"- `shouldBe` "a=[сто один] b=3 12"+ `shouldBe` (Right "a=[сто один] b=3 12"::E String) it "replaceGroup 2" $ do replace (All "\\w=(\\d{1,3})") replacer "a=101 b=3 12"- `shouldBe` "a=[сто один] b=[three] 12"+ `shouldBe` (Right "a=[сто один] b=[three] 12"::E String) it "replace 3" $ do- U.replace (Once (Pattern $ Utf8_ "менее")) (Replacement $ Utf8_ $ "более") (Body $ Utf8_ "менее менее")- `shouldBe` "более менее"+ U.replace (Once "менее") ("более") ("менее менее")+ `shouldBe` (Right "более менее"::E String) it "replace 4" $ do- U.replace (All (Pattern $ Utf8_ "менее")) (Replacement $ Utf8_ $ "боле") (Body $ Utf8_ "менее менее")- `shouldBe` "боле боле"+ U.replace (All "менее") ("боле") ("менее менее")+ `shouldBe` (Right "боле боле"::E String) it "replace 5" $ do- replace (Once "^a\\s") (Replacement "A") "a bc хол.гор."- `shouldBe` "Abc хол.гор."+ U.replace (Once "^a\\s") ("A") "a bc хол.гор."+ `shouldBe` (Right "Abc хол.гор."::E String) onceUtf8::IO() onceUtf8 = hspec $ do describe "Pcre.Replace Once Utf8" $ do it "^a\\s" $ do- replace (Once (Pattern "^a\\s")) (Replacement "A") (Body "a bc хол.гор.") `shouldBe` "Abc хол.гор."+ replace (Once ("^a\\s")) ("A") ("a bc хол.гор.") `shouldBe` (Right "Abc хол.гор."::E String) it "^b\\s" $ do- replace (Once (Pattern "^b\\s")) (Replacement "A") (Body "a bc хол.гор.") `shouldBe` "a bc хол.гор."+ replace (Once ("^b\\s")) ("A") ("a bc хол.гор.") `shouldBe` (Right "a bc хол.гор."::E String) latinOnceAll::IO() latinOnceAll = hspec $ do describe "Pcre.Replace" $ do it "Once" $ do- runFn1 Once `shouldBe` toByteString "a=text1 b=11 12"+ runFn1 Once `shouldBe` (Right $ toByteString "a=text1 b=11 12"::E ByteString) it "All" $ do- runFn1 All `shouldBe` toByteString "a=text1 b=text1 12"+ runFn1 All `shouldBe` (Right $ toByteString "a=text1 b=text1 12"::E ByteString) where runFn1 hint1 =- let rx1 = pattern "(?<==)(\\d{2})"- body1 = Body $ toByteString haystack1+ let rx1 = toByteString "(?<==)(\\d{2})"+ body1 = toByteString haystack1 haystack1 = "a=10 b=11 12"- repl1 = replacement "text1"+ repl1 = toByteString "text1" in replace (hint1 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 `shouldBe` "a=[сто один] b=3 12"+ runFn1 Once `shouldBe` (Right "a=[сто один] b=3 12"::E String) it "All" $ do- runFn1 All `shouldBe` "a=[сто один] b=[three] 12"+ runFn1 All `shouldBe` (Right "a=[сто один] b=[three] 12"::E String) where runFn1 opts1 =- let rx1 = Pattern "\\w=(\\d{1,3})"- body1 = Body "a=101 b=3 12"+ let rx1 = "\\w=(\\d{1,3})"+ body1 = "a=101 b=3 12" in replace (opts1 rx1) replacer body1
test/TestRegex/TestReplaceOpen.hs view
@@ -2,10 +2,10 @@ module TestRegex.TestReplaceOpen where import Test.Hspec-import Text.Regex.Do.ReplaceOpen as O+import Text.Regex.Do.Replace.Open as O import Text.Regex.Do.Type.Do import Data.Text-import Text.Regex.Do.Convert()+import Text.Regex.Do.Type.Convert() import Debug.Trace @@ -13,9 +13,11 @@ main = hspec $ do describe "TestRegex.TestReplaceOpen" $ do it "case 1" $- O.replace (Just [(4,3)::PosLen]) (Replacement "4567") (Body "abc 123 def"::Body Text) `shouldBe` ("abc 4567 def"::Text)+ O.replace (Just [(4,3)::PosLen]) ("4567"::Text) ("abc 123 def"::Text) `shouldBe` ("abc 4567 def"::Text) it "case 2" $- O.replace (Just ([(4,3),(8,2)]::[PosLen])) replacer (Body "abc 123 def"::Body Text) `shouldBe` ("abc [1-2-3] def"::Text)+ O.replace (Just [(4,3)::PosLen]) replacer ("abc 123 def"::Text) `shouldBe` ("abc [1-2-3] def"::Text)+ it "case 3" $+ O.replace ([[(4,3)::PosLen]]) replacer ("abc 123 def"::Text) `shouldBe` ("abc [1-2-3] def"::Text) replacer::GroupReplacer Text
test/TestRegex/TestReplaceUtf.hs view
@@ -4,10 +4,10 @@ import Test.Hspec import Text.Regex.Do.Type.Do import Data.ByteString-import Text.Regex.Do.Convert-import Text.Regex.Do.Pcre.Utf8.Replace as U+import Text.Regex.Do.Type.Convert+import Text.Regex.Do.Replace.Utf8 as U import Text.Regex.Do.Type.MatchHint-import Text.Regex.Do.ReplaceOpen+import Text.Regex.Do.Replace.Open import Debug.Trace @@ -22,24 +22,24 @@ doc = hspec $ do describe "TestRegex.TestReplaceUtf doc" $ do it "doc 1" $- U.replace (All "праздник") (Replacement "радость") "экзамен - всегда праздник"+ U.replace (All "всегда") "часто" "экзамен - всегда праздник" `shouldBe` out1 it "doc 2" $- U.replace "праздник" (All (Replacement "радость")) "экзамен - всегда праздник"+ U.replace (All "всегда") "часто" "экзамен - всегда праздник" `shouldBe` out1 it "doc 3" $- U.replace "праздник" (Replacement "радость") (All "экзамен - всегда праздник")+ U.replace (All "всегда") "часто" "экзамен - всегда праздник" `shouldBe` out1 it "doc 4" $- U.replace "праздник" (Replacement "радость") (Once "экзамен - всегда праздник")+ U.replace (Once "всегда") "часто" "экзамен - всегда праздник" `shouldBe` out1 it "doc 2-bs" $- U.replace (toByteString "праздник") (All (Replacement $ toByteString "радость")) (toByteString "экзамен - всегда праздник")- `shouldBe` (toByteString out1)+ U.replace (All $ toByteString "всегда") (toByteString "часто") (toByteString "экзамен - всегда праздник")+ `shouldBe` (toByteString <$> out1) it "doc 4-2" $- U.replace (Once $ Pattern $ Utf8_ "праздник") (Replacement $ Utf8_ "радость") (Body $ Utf8_ "экзамен - всегда праздник")+ U.replace (Once "всегда") "часто" "экзамен - всегда праздник" `shouldBe` out1- where out1 = "экзамен - всегда радость"+ where out1 = Right "экзамен - часто праздник"::E String @@ -47,17 +47,17 @@ groupReplace = hspec $ do describe "TestRegex.TestReplaceUtf" $ do it "All" $ do- runFn1 `shouldBe` toByteString "100メートルー右ー折後、左"+ runFn1 `shouldBe` (Right $ toByteString "100メートルー右ー折後、左"::E ByteString) where runFn1 =- let rx1 = Pattern $ toByteString' "(?<=ル)(左)"- body1 = Body $ toByteString' "100メートル左折後、左"+ let rx1 = toByteString "(?<=ル)(左)"+ body1 = toByteString "100メートル左折後、左" in U.replace (All rx1) replacer body1 -replacer::GroupReplacer (Utf8_ ByteString)+replacer::GroupReplacer ByteString replacer = defaultReplacer 1 tweak1- where tweak1 bs1 = toByteString' $- if bs1 == toByteString' "左" then+ where tweak1 bs1 = toByteString $+ if bs1 == toByteString "左" then "ー右ー" else "?" @@ -66,11 +66,11 @@ groupReplace2_ = hspec $ do describe "TestRegex.TestReplaceUtf" $ do it "боль" $ do- runFn1 `shouldBe` (toByteString "А - Я : 5:0")+ runFn1 `shouldBe` (Right $ toByteString "А - Я : 5:0"::E ByteString) where runFn1 = let rx1 = toByteString "(\\[[^\\]]+\\])" body1 = toByteString "[какая боль, ][команды] : [счёт]"- in U.replace rx1 (All replacer2_) body1+ in U.replace (All rx1) replacer2_ body1 replacer2_::GroupReplacer (ByteString)
test/TestRegex/TestSplit.hs view
@@ -1,75 +1,74 @@ module TestRegex.TestSplit where -import Prelude hiding(break)+import Prelude hiding((/)) import Test.Hspec import Control.Exception (evaluate)-import Text.Regex.Do.Type.Do import Text.Regex.Do.Split as S+import Text.Regex.Do.Replace.Fast as S import qualified Data.ByteString as B-import Text.Regex.Do.Convert+import Text.Regex.Do.Type.Convert + main::IO() main = hspec $ do describe "Habase.Regex.StringSearch.Search" $ do it "break :" $ do- break Drop (Pattern ":") (Body "0123:oid:90") `shouldBe` ("0123", "oid:90")+ "0123:oid:90" S./ ":" `shouldBe` (("0123", "oid:90")::S.T) it "break" $ do- break Drop (Pattern "\n") (Body "a\nbc\nde") `shouldBe` ("a", "bc\nde")+ "a\nbc\nde" / "\n" `shouldBe` (("a", "bc\nde")::S.T) it "break front" $ do- break Front (Pattern "\n") (Body "a\nbc\nde") `shouldBe` ("a", "\nbc\nde")+ "a\nbc\nde" -/ "\n" `shouldBe` (("a", "\nbc\nde")::S.T) it "break end" $ do- break End (Pattern "\n") (Body "a\nbc\nde") `shouldBe` ("a\n", "bc\nde")+ "a\nbc\nde" /- "\n" `shouldBe` (("a\n", "bc\nde")::S.T) it "replace" $ do- S.replace (Pattern "\n") (Replacement ",") (Body "a\nbc\nde") `shouldBe` "a,bc,de"+ S.replace "\n" "," "a\nbc\nde" `shouldBe` "a,bc,de" it "split" $ do- split Drop (Pattern "\n") (Body "a\nbc\nde") `shouldBe` ["a", "bc", "de"]+ "a\nbc\nde" / "\n" `shouldBe` (["a", "bc", "de"]::S.L) it "split_sp" $ do- split Drop (Pattern " ") (Body "a bc de") `shouldBe` ["a", "bc", "de"]+ "a bc de" / " " `shouldBe` (["a", "bc", "de"]::S.L) it "split end" $ do- split End (Pattern "\n") (Body "a\nbc\nde") `shouldBe` ["a\n", "bc\n", "de"]+ "a\nbc\nde" /- "\n" `shouldBe` (["a\n", "bc\n", "de"]::S.L) it "split front" $ do- split Front (Pattern "\n") (Body "a\nbc\nde") `shouldBe` ["a", "\nbc", "\nde"]+ "a\nbc\nde" -/ "\n" `shouldBe` (["a", "\nbc", "\nde"]::S.L) it "split regex" $ do- split Drop (Pattern "\\s") (Body "abc de fghi ") `shouldBe` ["abc de fghi "]+ "abc de fghi " / "\\s" `shouldBe` (["abc de fghi "]::S.L) describe "StringSearch.Search zerolength" $ do it "break" $ do- evaluate (errFn1 $ break Drop) `shouldThrow` anyException+ evaluate (body / z1::S.T) `shouldThrow` anyException it "break front" $ do- evaluate (errFn1 $ break Front) `shouldThrow` anyException+ evaluate (body -/ z1::S.T) `shouldThrow` anyException it "break end" $ do- evaluate (errFn1 $ break End) `shouldThrow` anyException+ evaluate (body /- z1::S.T) `shouldThrow` anyException it "replace" $ do- evaluate (S.replace (Pattern B.empty) with body) `shouldThrow` anyException+ evaluate (S.replace B.empty with body) `shouldThrow` anyException it "split" $ do- evaluate (errFn2 $ split Drop) `shouldThrow` anyException+ evaluate (body / z1::S.T) `shouldThrow` anyException it "split end" $ do- evaluate (errFn2 $ split End) `shouldThrow` anyException+ evaluate (body -/ z1::S.T) `shouldThrow` anyException it "split front" $ do- evaluate (errFn2 $ split Front) `shouldThrow` anyException+ evaluate (body -/ z1::S.T) `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 Drop pat body- breakFront1 = break Front pat body- breakEnd1 = break End pat body- replace1 = S.replace pat with body- split1 = split Drop pat body- split_sp1 = split Drop pat_sp body_sp- splitFront1 = split Front pat body- splitEnd1 = split End pat body- errFn1 fn1 = fn1 (Pattern B.empty) body- errFn2 fn1 = fn1 (Pattern B.empty) body+ where pat = "\n"+ pat_sp = " "+ body = "a\nbc\nde"+ body_sp = "a bc de"+ with = ","+ break1 = body / pat::S.T + breakFront1 = body -/ pat::S.T+ breakEnd1 = body /- pat::S.T+ replace1 = S.replace pat with $ body+ split1 = body / pat::S.L + split_sp1 = body_sp / pat_sp::S.L + splitFront1 = body -/ pat::S.L + splitEnd1 = body /- pat::S.L + z1 = B.empty b = toByteString -- break delim not found- pat_nf = Pattern ":"- break_nf = break Drop pat_nf body+ break_nf = body / ":"
test/TestRegex/TestTrim.hs view
@@ -4,7 +4,7 @@ import Debug.Trace import qualified Data.Text as T (strip, pack, unpack) import Text.Regex.Do.Trim-import Text.Regex.Do.Convert+import Text.Regex.Do.Type.Convert main::IO()