packages feed

regex-do 2.6 → 2.6.1

raw patch · 16 files changed

+212/−67 lines, 16 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Text.Regex.Do.Format: instance Text.Regex.Do.Format.Format [(GHC.Base.String, GHC.Base.String)]
- Text.Regex.Do.Format: instance Text.Regex.Do.Format.Format [GHC.Base.String]
+ Text.Regex.Do.Format: class ReplaceOne idx a
+ Text.Regex.Do.Format: instance Text.Regex.Do.Format.ReplaceOne Data.ByteString.Internal.ByteString Data.ByteString.Internal.ByteString
+ Text.Regex.Do.Format: instance Text.Regex.Do.Format.ReplaceOne Data.Text.Internal.Text Data.Text.Internal.Text
+ Text.Regex.Do.Format: instance Text.Regex.Do.Format.ReplaceOne GHC.Base.String GHC.Base.String
+ Text.Regex.Do.Format: instance Text.Regex.Do.Format.ReplaceOne GHC.Types.Int Data.ByteString.Internal.ByteString
+ Text.Regex.Do.Format: instance Text.Regex.Do.Format.ReplaceOne GHC.Types.Int Data.Text.Internal.Text
+ Text.Regex.Do.Format: instance Text.Regex.Do.Format.ReplaceOne GHC.Types.Int GHC.Base.String
+ Text.Regex.Do.Format: instance Text.Regex.Do.Format.ReplaceOne GHC.Types.Int a => Text.Regex.Do.Format.Format a [a]
+ Text.Regex.Do.Format: instance Text.Regex.Do.Format.ReplaceOne a a => Text.Regex.Do.Format.Format a [(a, a)]
+ Text.Regex.Do.Format: replaceOne :: ReplaceOne idx a => a -> idx -> a -> a
+ Text.Regex.Do.Format: type Formatable a = (Format a [a], Format a [(a, a)])
+ Text.Regex.Do.Trim: instance Text.Regex.Do.Trim.Trim Data.Text.Internal.Text
- Text.Regex.Do.Format: class Format a
+ Text.Regex.Do.Format: class Format a arg
- Text.Regex.Do.Format: format :: Format a => String -> a -> String
+ Text.Regex.Do.Format: format :: Format a arg => a -> arg -> a

Files

changelog.md view
@@ -1,3 +1,10 @@+#####   2.6.1+  compatible with 2.6+  +  add Format instances: ByteString, Text   +  add Trim instance: Text   +    + #####   2.6   compatible with 2.5      
regex-do.cabal view
@@ -1,5 +1,5 @@ name:                regex-do-version:             2.6+version:             2.6.1 synopsis:            PCRE wrapper description:         format, search, replace (String | ByteString) with PCRE regex. Utf8-safe author:              Imants Cekusins
src/Text/Regex/Do/Format.hs view
@@ -1,63 +1,116 @@ module Text.Regex.Do.Format-    (Format(..)) where+    (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  -class Format a where-   format::String -> a -> String+type Formatable a = (Format a [a], Format a [(a,a)]) +{- | ==== implemented a: -instance Format [String] where+    * 'String'+    * 'ByteString'+    * 'Text'      -}++class Format a arg where+   format::a -> arg -> a+++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"---+{- ^ === index based+     >>> format "на первое {0}, на второе {0}" ["перловка"] -foldFn_idx::String -> (Int, String) -> String-foldFn_idx v (i,body1) = replaceOne body1 (show i) v+     "на первое перловка, на второе перловка" +     >>> format "Polly {0} a {1}" ["got","cracker"] -instance Format [(String,String)] where+     "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 string}------ >>> format "овчинка {a} не {b}" [("a","выделки"),("b","стоит")]------ "овчинка выделки не стоит"---+{- ^=== key based+     key may be {any a} -foldFn_map:: (String, String) -> String -> String-foldFn_map (k,v) body1 = replaceOne body1 k v+     >>> format "овчинка {a} не {b}" [("a","выделки"),("b","стоит")] -replaceOne::String -> String -> String -> String-replaceOne body k v = toString bs1-   where pat1 = Pattern $ toByteString $ "{" ++ k ++ "}"-         repl1 = Replacement $ toByteString v-         bs1 = S.replace pat1 repl1 $ Body $ toByteString body+     "овчинка выделки не стоит"+-}   +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 fn init1 list = b1-   where i0 = P.length list - 1-         (-1,b1) = P.foldr (foldFn fn) (i0,init1) list+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 fn val t@(i,_)= (i-1,b1)-   where b1 = fn val t++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/Pcre/Ascii/Match.hs view
@@ -19,8 +19,12 @@ import Text.Regex.Do.Type.MatchHint  -{- | 'match' covers all result types+{- | * a:  'String', 'ByteString', 'Regex'+    * b:  'String', 'ByteString'+    * out: ['String'], [['String']], ['ByteString'], [['ByteString']], 'Bool', ['PosLen'], [['PosLen']] +    'match' covers all result types+     compiler looks up the appropriate function depending on the result type      '=~' is borrowed from "Text.Regex.PCRE.Wrap",@@ -34,6 +38,7 @@     match::Pattern a -> Body b -> out  +-- | synonym for 'match'. arg without newtypes (=~)::Match a b out =>     a     -- ^ pattern     -> b    -- ^ body
src/Text/Regex/Do/Pcre/Ascii/MatchHint.hs view
@@ -21,7 +21,10 @@ import Data.ByteString  -{- | picks 'M.Match' instance where 'Pattern' and 'Body' are of the same type+{- | * hint: 'Once', 'All', 'Test', 'PosLen'', 'PosLen_'+    * a: 'String', 'ByteString'++    picks 'M.Match' instance where 'Pattern' and 'Body' are of the same type      'Hint' and inferrable 'Pattern' or 'Body' type determine the instance 
src/Text/Regex/Do/Pcre/Ascii/Replace.hs view
@@ -17,7 +17,31 @@ import Text.Regex.Do.Type.MatchHint import Text.Regex.Do.Pcre.Option as O -{- | arg overloading    -}+{- | '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))++    * 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 
src/Text/Regex/Do/Pcre/Option.hs view
@@ -11,7 +11,11 @@  -- | <http://www.pcre.org/pcre.txt pcre man pages> -data Comp = Blank       -- ^ 'B.compBlank'+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@@ -85,7 +89,9 @@    deriving (Eq,Ord,Enum)  -data Exec = BlankE  -- ^ 'B.execBlank'+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
src/Text/Regex/Do/Pcre/Utf8/Match.hs view
@@ -24,10 +24,15 @@ import Data.ByteString  -+{- | * enc: 'Utf8_'+    * a:  'String', 'ByteString', 'Regex'+    * 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 +-- | synonym for 'match'. arg without newtypes (=~)::Match Utf8_ a b out =>     a     -- ^ pattern     -> b    -- ^ body
src/Text/Regex/Do/Pcre/Utf8/MatchHint.hs view
@@ -12,7 +12,11 @@ import Data.ByteString  -{- | picks 'M.Match' instance where 'Pattern' and 'Body' are of the same type+{- | * hint: 'Once', 'All', 'Test', 'PosLen'', 'PosLen_'+    * a: 'String', 'ByteString'+    * enc: 'Utf8_'++    picks 'M.Match' instance where 'Pattern' and 'Body' are of the same type      'Hint' and inferrable 'Pattern' or 'Body' type determine the instance 
src/Text/Regex/Do/Pcre/Utf8/Replace.hs view
@@ -18,7 +18,12 @@ import Text.Regex.Do.Convert import Data.ByteString -{- | arg overloading    -}+{- | see "Text.Regex.Do.Pcre.Ascii.Replace" for implemented types++    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 @@ -63,7 +68,7 @@     >>> replacer::GroupReplacer (ByteString)     replacer = defaultReplacer 1 tweak1           where tweak1 s1-                    | s1 == toByteString "[команды]" = toByteString "A - B"+                    | s1 == toByteString "[команды]" = toByteString "А - Я"                     | s1 == toByteString "[счёт]" = toByteString "5:0"                     | s1 == toByteString "[какая боль, ]" = empty                     | otherwise = traceShow s1 $ toByteString "?"@@ -72,7 +77,7 @@             body1 = toByteString "[какая боль, ][команды] : [счёт]"         in replace rx1 (All replacer) body1 -    "A - B : 5:0"       -}+    "А - Я : 5:0"       -}  instance (T.Regex b,         Replace' Once Utf8_ b repl,
src/Text/Regex/Do/ReplaceOpen.hs view
@@ -108,8 +108,11 @@                                  where str2 = tweak0 str1  -{- | get group content safely+{- | 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 =>@@ -121,9 +124,10 @@           val1 = extract pl2 $ acc acc0  -{- | call from your custom 'GroupReplacer' passed to 'replaceGroup'+{- | replace group match while adjusting for previous replacements length -     see 'defaultReplacer' source for use example     -}+    see 'defaultReplacer' source for use example     -}+ replaceMatch::Extract' a =>         PosLen      -- ^ replaceable, unadjusted         -> (a, ReplaceAcc a)  -- ^ (new val, acc passed to 'GroupReplacer')
src/Text/Regex/Do/Trim.hs view
@@ -3,6 +3,7 @@ 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.MatchHint@@ -24,6 +25,11 @@                         in makeRegexOpt p1 [Blank] []  -instance  Trim String where+instance Trim String where     trim = f . f        where f = reverse . dropWhile isSpace+++instance Trim T.Text where+    trim = T.strip+-- ^ see 'T.strip'
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     -- ^ values+newtype Once a = Once a     -- ^ match / replace once         deriving (Functor) -newtype All a = All a        -- ^ values+newtype All a = All a        -- ^ match / replace all         deriving (Functor)  newtype PosLen' a = PosLen' a   -- ^ once
test/TestRegex/TestFormat.hs view
@@ -1,24 +1,48 @@-{-# LANGUAGE NoOverloadedStrings #-} module TestRegex.TestFormat where  import Test.Hspec import Text.Regex.Do.Format import Text.Regex.Do.Pad+import Data.String+import Text.Regex.Do.Convert+import Data.ByteString+import Data.Text as T   main::IO()-main = hspec $ do+main = do+    oneFormat s show                        --  String+    oneFormat b $ toByteString . show       --  ByteString+    oneFormat t $ T.pack . show       --  Text+++oneFormat::(Formatable a, IsString a, Eq a, Show a) =>+        (String -> a) ->+        (Int -> a) ->+            IO()+oneFormat fn0 idx0 = hspec $ do        describe "Habase.Bin.Format" $ do           it "list arg 0,0 repl []" $-            format "на первое {0}, на второе {0}" ([]::[String]) `shouldBe` "на первое {0}, на второе {0}"+            format (fn0 "на первое {0}, на второе {0}") (fn0 <$> []) `shouldBe` (fn0 "на первое {0}, на второе {0}")           it "list arg 0,0" $-            format "на первое {0}, на второе {0}" ["перловка"] `shouldBe` "на первое перловка, на второе перловка"+            format (fn0 "на первое {0}, на второе {0}") [fn0 "перловка"] `shouldBe` (fn0 "на первое перловка, на второе перловка")           it "list arg 0,1" $ do-            format "Polly {0} a {1}" ["gets","cracker"] `shouldBe` "Polly gets a cracker"-            format "{10} {15} {21}" (show <$> [0..22]) `shouldBe` "10 15 21"-            format "{ten} {пятнадцать} {vingt}" [("ten","10"), ("пятнадцать", "15"), ("vingt", "20")] `shouldBe` "10 15 20"+            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")           it "map arg" $-            format "овчинка {a} не {b}" [("a","выделки"),("b","стоит")] `shouldBe` "овчинка выделки не стоит"+            format (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--"           it "pad" $ pad '-' 3 "abcde" `shouldBe` "abcde"+++s::String -> String+s = id++b::String -> ByteString+b = toByteString++t::String -> Text+t = T.pack
test/TestRegex/TestReplaceUtf.hs view
@@ -66,7 +66,7 @@ groupReplace2_ =  hspec $ do        describe "TestRegex.TestReplaceUtf" $ do             it "боль" $ do-               runFn1 `shouldBe` (toByteString "A - B : 5:0")+               runFn1 `shouldBe` (toByteString "А - Я : 5:0")             where runFn1 =                      let rx1 = toByteString "(\\[[^\\]]+\\])"                          body1 = toByteString "[какая боль, ][команды] : [счёт]"@@ -76,7 +76,7 @@ replacer2_::GroupReplacer (ByteString) replacer2_ = defaultReplacer 1 tweak1       where tweak1 s1-                | s1 == toByteString "[команды]" = toByteString "A - B"+                | s1 == toByteString "[команды]" = toByteString "А - Я"                 | s1 == toByteString "[счёт]" = toByteString "5:0"                 | s1 == toByteString "[какая боль, ]" = empty                 | otherwise = traceShow s1 $ toByteString "?"
test/TestRegex/TestTrim.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE OverloadedStrings #-} module TestRegex.TestTrim where  import Test.Hspec