regex-do 2.5 → 2.6
raw patch · 12 files changed
+261/−44 lines, 12 files
Files
- changelog.md +8/−0
- regex-do.cabal +1/−1
- src/Text/Regex/Do/Pcre/Ascii/Match.hs +10/−4
- src/Text/Regex/Do/Pcre/Ascii/MatchHint.hs +5/−4
- src/Text/Regex/Do/Pcre/Ascii/Replace.hs +57/−10
- src/Text/Regex/Do/Pcre/Utf8/Match.hs +8/−4
- src/Text/Regex/Do/Pcre/Utf8/Replace.hs +105/−15
- src/Text/Regex/Do/Trim.hs +2/−2
- src/Text/Regex/Do/Type/Do.hs +4/−0
- src/Text/Regex/Do/Type/MatchHint.hs +4/−0
- test/TestRegex/TestReplace.hs +3/−3
- test/TestRegex/TestReplaceUtf.hs +54/−1
changelog.md view
@@ -1,7 +1,15 @@+##### 2.6+ compatible with 2.5 + + overload replace (both Ascii & Utf8): add shorter arg versions + ##### 2.5 *API changes*+ split PCRE to Ascii and Utf8+ remove \[Comp\] opt from replace signature + tweak trim ##### 2.4
regex-do.cabal view
@@ -1,5 +1,5 @@ name: regex-do-version: 2.5+version: 2.6 synopsis: PCRE wrapper description: format, search, replace (String | ByteString) with PCRE regex. Utf8-safe author: Imants Cekusins
src/Text/Regex/Do/Pcre/Ascii/Match.hs view
@@ -7,6 +7,7 @@ module Text.Regex.Do.Pcre.Ascii.Match (Match(..),+ (=~), R.extract -- | 'extract' is reexport from "Text.Regex.Base.RegexLike" ) where @@ -25,14 +26,19 @@ '=~' is borrowed from "Text.Regex.PCRE.Wrap", is a short version of 'match' + precompiled Regex may be used as pattern too. see "Text.Regex.Do.Pcre.Utf8.Match"+ See also "Text.Regex.Do.Pcre.Ascii.MatchHint" -} class Match a b out where match::Pattern a -> Body b -> out- (=~)::a -- ^ pattern- -> b -- ^ body- -> out- (=~) p0 b0 = match (Pattern p0) (Body b0)+++(=~)::Match a b out =>+ a -- ^ pattern+ -> b -- ^ body+ -> out+(=~) p0 b0 = match (Pattern p0) (Body b0) -- | match once
src/Text/Regex/Do/Pcre/Ascii/MatchHint.hs view
@@ -35,10 +35,11 @@ match::hint (Pattern a) -> Body a -> F hint a match h0 = M.match $ unhint h0 - (=~)::hint a -- ^ hint & pattern- -> a -- ^ body- -> F hint a -- ^ type defined by the instance, determined by the hint- (=~) h0 = (M.=~) $ 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
src/Text/Regex/Do/Pcre/Ascii/Replace.hs view
@@ -1,10 +1,9 @@-{- | === Ascii vs Utf8 modules-- for reliable results with Utf8 pattern or body,+{- | 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@@ -18,11 +17,59 @@ import Text.Regex.Do.Type.MatchHint import Text.Regex.Do.Pcre.Option as O +{- | arg overloading -}+class Replace pat repl body out where+ replace::pat -> repl -> body -> out -class Replace all a repl b where- replace::(R_ b, Matchf all b) =>- all (Pattern a) -> repl b -> Body b -> b +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,@@ -35,8 +82,8 @@ -instance Repl_ Maybe a repl b => Replace Once a repl b where- replace = replace_ marray_+instance Repl_ Maybe a repl b => Replace' Once a repl b where+ replace' = replace_ marray_ {- ^ === static replace for simple (no group) needle @@ -53,8 +100,8 @@ "a=[1 0 1] b=3 12" -} -instance Repl_ [] a repl b => Replace All a repl b where- replace = replace_ marray_+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"
src/Text/Regex/Do/Pcre/Utf8/Match.hs view
@@ -35,14 +35,18 @@ (=~) p0 b0 = match (Pattern $ Utf8_ p0) (Body $ Utf8_ b0) --- | match once-instance Rx_ a b => Match Utf8_ a b [b] where- match p0 b0 = once (mr_ p0) $ val <$> b0+{- | match once -{- ^ >>> let rx1 = makeRegexOpt' (Pattern $ toByteString' "左") [] [] -- add options as needed+ ==== 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
src/Text/Regex/Do/Pcre/Utf8/Replace.hs view
@@ -6,7 +6,8 @@ __'toByteString''__ converts String to 'Utf8_' 'ByteString' -} module Text.Regex.Do.Pcre.Utf8.Replace- (Replace(..)) where+ (Replace(..),+ Replace'()) where import Prelude as P import Text.Regex.Do.Type.Do@@ -17,17 +18,106 @@ import Text.Regex.Do.Convert import Data.ByteString +{- | arg overloading -}+class Replace pat repl body out where+ replace::pat -> repl -> body -> out -class Replace all enc a repl where- replace::all (Pattern (enc a)) -> repl (enc a) -> Body (enc a) -> a +instance (Replace' all enc b repl) =>+ Replace (all (Pattern (enc b))) (repl (enc b)) (Body (enc b)) b where+ replace = replace'+{- ^ full typed arg -instance Replace Once Utf8_ String Replacement where- replace = replace_str marray_+ >>> replace (Once $ Pattern $ Utf8_ "праздник")+ (Replacement $ Utf8_ "радость")+ (Body $ Utf8_ "экзамен - всегда праздник")+-} -instance Replace All Utf8_ String Replacement where- replace = replace_str marray_ +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 "A - B"+ | s1 == toByteString "[счёт]" = toByteString "5:0"+ | s1 == toByteString "[какая боль, ]" = empty+ | otherwise = traceShow s1 $ toByteString "?"++ >>> let rx1 = toByteString "(\\[[^\\]]+\\])"+ body1 = toByteString "[какая боль, ][команды] : [счёт]"+ in replace rx1 (All replacer) body1++ "A - B : 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@@ -36,11 +126,11 @@ in toString $ O.replace ma1 r1 b1 -instance Replace Once Utf8_ ByteString Replacement where- replace = replace_bs marray_+instance Replace' Once Utf8_ ByteString Replacement where+ replace' = replace_bs marray_ -instance Replace All 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@@ -50,11 +140,11 @@ -instance Replace Once Utf8_ ByteString GroupReplacer where- replace = replace_bs' marray_+instance Replace' Once Utf8_ ByteString GroupReplacer where+ replace' = replace_bs' marray_ -instance Replace All 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
src/Text/Regex/Do/Trim.hs view
@@ -17,11 +17,11 @@ instance Trim B.ByteString where- trim bs1 = replace (All rx2) repl1 $ Body bs1+ trim bs1 = replace rx2 repl1 (All bs1) where repl1 = Replacement B.empty rx1 = "(^[\\s\\t]+)|([\\s\\t]+$)" rx2 = let p1 = Pattern $ toByteString rx1- in makeRegexOpt' p1 [Blank] []+ in makeRegexOpt p1 [Blank] [] instance Trim String where
src/Text/Regex/Do/Type/Do.hs view
@@ -69,3 +69,7 @@ \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 <$>)
src/Text/Regex/Do/Type/MatchHint.hs view
@@ -45,3 +45,7 @@ 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
test/TestRegex/TestReplace.hs view
@@ -25,10 +25,10 @@ doc = hspec $ do describe "Pcre.Replace doc" $ do it "replaceGroup 1" $ do- replace (Once (Pattern "\\w=(\\d{1,3})")) replacer (Body "a=101 b=3 12")+ replace (Once "\\w=(\\d{1,3})") replacer "a=101 b=3 12" `shouldBe` "a=[сто один] b=3 12" it "replaceGroup 2" $ do- replace (All (Pattern "\\w=(\\d{1,3})")) replacer (Body "a=101 b=3 12")+ replace (All "\\w=(\\d{1,3})") replacer "a=101 b=3 12" `shouldBe` "a=[сто один] b=[three] 12" it "replace 3" $ do U.replace (Once (Pattern $ Utf8_ "менее")) (Replacement $ Utf8_ $ "более") (Body $ Utf8_ "менее менее")@@ -37,7 +37,7 @@ U.replace (All (Pattern $ Utf8_ "менее")) (Replacement $ Utf8_ $ "боле") (Body $ Utf8_ "менее менее") `shouldBe` "боле боле" it "replace 5" $ do- replace (Once (Pattern "^a\\s")) (Replacement "A") (Body "a bc хол.гор.")+ replace (Once "^a\\s") (Replacement "A") "a bc хол.гор." `shouldBe` "Abc хол.гор."
test/TestRegex/TestReplaceUtf.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE NoOverloadedStrings #-} module TestRegex.TestReplaceUtf where import Test.Hspec@@ -7,11 +8,41 @@ import Text.Regex.Do.Pcre.Utf8.Replace as U import Text.Regex.Do.Type.MatchHint import Text.Regex.Do.ReplaceOpen+import Debug.Trace main::IO()-main = groupReplace+main = do+ groupReplace+ groupReplace2_+ doc ++doc::IO()+doc = hspec $ do+ describe "TestRegex.TestReplaceUtf doc" $ do+ it "doc 1" $+ U.replace (All "праздник") (Replacement "радость") "экзамен - всегда праздник"+ `shouldBe` out1+ it "doc 2" $+ U.replace "праздник" (All (Replacement "радость")) "экзамен - всегда праздник"+ `shouldBe` out1+ it "doc 3" $+ U.replace "праздник" (Replacement "радость") (All "экзамен - всегда праздник")+ `shouldBe` out1+ it "doc 4" $+ U.replace "праздник" (Replacement "радость") (Once "экзамен - всегда праздник")+ `shouldBe` out1+ it "doc 2-bs" $+ U.replace (toByteString "праздник") (All (Replacement $ toByteString "радость")) (toByteString "экзамен - всегда праздник")+ `shouldBe` (toByteString out1)+ it "doc 4-2" $+ U.replace (Once $ Pattern $ Utf8_ "праздник") (Replacement $ Utf8_ "радость") (Body $ Utf8_ "экзамен - всегда праздник")+ `shouldBe` out1+ where out1 = "экзамен - всегда радость"+++ groupReplace::IO() groupReplace = hspec $ do describe "TestRegex.TestReplaceUtf" $ do@@ -29,3 +60,25 @@ if bs1 == toByteString' "左" then "ー右ー" else "?"+++groupReplace2_::IO()+groupReplace2_ = hspec $ do+ describe "TestRegex.TestReplaceUtf" $ do+ it "боль" $ do+ runFn1 `shouldBe` (toByteString "A - B : 5:0")+ where runFn1 =+ let rx1 = toByteString "(\\[[^\\]]+\\])"+ body1 = toByteString "[какая боль, ][команды] : [счёт]"+ in U.replace rx1 (All replacer2_) body1+++replacer2_::GroupReplacer (ByteString)+replacer2_ = defaultReplacer 1 tweak1+ where tweak1 s1+ | s1 == toByteString "[команды]" = toByteString "A - B"+ | s1 == toByteString "[счёт]" = toByteString "5:0"+ | s1 == toByteString "[какая боль, ]" = empty+ | otherwise = traceShow s1 $ toByteString "?"++