{- | 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