\begin{code}
{-# LANGUAGE NoImplicitPrelude          #-}
{-# LANGUAGE QuasiQuotes                #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE RecordWildCards            #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE MonoLocalBinds             #-}

module Text.RE.ZeInternals.Replace
  (
  -- * REContext and RELocation
    REContext(..)
  , RELocation(..)
  , isTopLocation
  -- * replaceAll
  , replaceAll
  , replaceAllCaptures
  , replaceAllCaptures_
  , replaceAllCapturesM
  -- * replace
  , replace
  , replaceCaptures
  , replaceCaptures_
  , replaceCapturesM
  -- * expandMacros
  , expandMacros
  , expandMacros'
  -- * templateCaptures
  , templateCaptures
  -- * Replace and ReplaceMethods
  , Replace(..)
  , ReplaceMethods(..)
  , replaceMethods
  ) where

import           Control.Applicative
import           Data.Array
import qualified Data.ByteString.Char8          as B
import qualified Data.ByteString.Lazy.Char8     as LBS
import           Data.Char
import qualified Data.Foldable                  as F
import           Data.Functor.Identity
import qualified Data.HashMap.Strict            as HM
import           Data.Maybe
import qualified Data.Monoid                    as M
import qualified Data.Sequence                  as S
import qualified Data.Text                      as T
import qualified Data.Text.Encoding             as TE
import qualified Data.Text.Lazy                 as LT
import           Prelude.Compat
import           Text.RE.REOptions
import           Text.RE.ZeInternals.Types.Capture
import           Text.RE.ZeInternals.Types.CaptureID
import           Text.RE.ZeInternals.Types.Match
import           Text.RE.ZeInternals.Types.Matches
import           Text.Read
import           Text.Regex.TDFA
import           Text.Regex.TDFA.Text()
import           Text.Regex.TDFA.Text.Lazy()
\end{code}


ReContext and RELocation
------------------------

\begin{code}
-- | @REContext@ specifies which contexts the substitutions should be applied
data REContext
  = TOP   -- ^ substitutions should be applied to the top-level only,
          -- the text that matched the whole RE
  | SUB   -- ^ substitutions should only be applied to the text
          -- captured by bracketed sub-REs
  | ALL   -- ^ the substitution function should be applied to all
          -- captures, the top level and the sub-expression captures
  deriving (Int -> REContext -> ShowS
[REContext] -> ShowS
REContext -> String
(Int -> REContext -> ShowS)
-> (REContext -> String)
-> ([REContext] -> ShowS)
-> Show REContext
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [REContext] -> ShowS
$cshowList :: [REContext] -> ShowS
show :: REContext -> String
$cshow :: REContext -> String
showsPrec :: Int -> REContext -> ShowS
$cshowsPrec :: Int -> REContext -> ShowS
Show)

-- | the @RELocation@ information passed into the substitution function
-- specifies which sub-expression is being substituted
data RELocation =
  RELocation
    { RELocation -> Int
locationMatch   :: Int
          -- ^ the zero-based, i-th string to be matched,
          -- when matching all strings, zero when only the
          -- first string is being matched
    , RELocation -> CaptureOrdinal
locationCapture :: CaptureOrdinal
          -- ^ 0, when matching the top-level string
          -- matched by the whole RE, 1 for the top-most,
          -- left-most redex captured by bracketed
          -- sub-REs, etc.
    }
  deriving (Int -> RELocation -> ShowS
[RELocation] -> ShowS
RELocation -> String
(Int -> RELocation -> ShowS)
-> (RELocation -> String)
-> ([RELocation] -> ShowS)
-> Show RELocation
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [RELocation] -> ShowS
$cshowList :: [RELocation] -> ShowS
show :: RELocation -> String
$cshow :: RELocation -> String
showsPrec :: Int -> RELocation -> ShowS
$cshowsPrec :: Int -> RELocation -> ShowS
Show)
\end{code}

\begin{code}
-- | True iff the location references a complete match
-- (i.e., not a bracketed capture)
isTopLocation :: RELocation -> Bool
isTopLocation :: RELocation -> Bool
isTopLocation = (CaptureOrdinal -> CaptureOrdinal -> Bool
forall a. Eq a => a -> a -> Bool
==CaptureOrdinal
0) (CaptureOrdinal -> Bool)
-> (RELocation -> CaptureOrdinal) -> RELocation -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RELocation -> CaptureOrdinal
locationCapture
\end{code}

\begin{code}
-- | replace all with a template, $0 for whole text, $1 for first
-- capture, etc.
replaceAll :: Replace a
           => a
           -> Matches a
           -> a
replaceAll :: a -> Matches a -> a
replaceAll a
tpl Matches a
ac = REContext
-> (Match a -> RELocation -> Capture a -> Maybe a)
-> Matches a
-> a
forall a.
Replace a =>
REContext
-> (Match a -> RELocation -> Capture a -> Maybe a)
-> Matches a
-> a
replaceAllCaptures REContext
TOP (a -> Match a -> RELocation -> Capture a -> Maybe a
forall a.
Replace a =>
a -> Match a -> RELocation -> Capture a -> Maybe a
parseTemplateR a
tpl) Matches a
ac
\end{code}

\begin{code}
-- | substitutes using a function that takes the full Match
-- context and returns the same replacement text as the _phi_phi
-- context.
replaceAllCaptures :: Replace a
                   => REContext
                   -> (Match a->RELocation->Capture a->Maybe a)
                   -> Matches a
                   -> a
\end{code}

\begin{code}
replaceAllCaptures :: REContext
-> (Match a -> RELocation -> Capture a -> Maybe a)
-> Matches a
-> a
replaceAllCaptures = ReplaceMethods a
-> REContext
-> (Match a -> RELocation -> Capture a -> Maybe a)
-> Matches a
-> a
forall a.
Extract a =>
ReplaceMethods a
-> REContext
-> (Match a -> RELocation -> Capture a -> Maybe a)
-> Matches a
-> a
replaceAllCaptures_ ReplaceMethods a
forall a. Replace a => ReplaceMethods a
replaceMethods
\end{code}

\begin{code}
-- | replaceAllCaptures_ is like like replaceAllCaptures but takes the
-- Replace methods through the ReplaceMethods argument
replaceAllCaptures_ :: Extract a
                    => ReplaceMethods a
                    -> REContext
                    -> (Match a->RELocation->Capture a->Maybe a)
                    -> Matches a
                    -> a
replaceAllCaptures_ :: ReplaceMethods a
-> REContext
-> (Match a -> RELocation -> Capture a -> Maybe a)
-> Matches a
-> a
replaceAllCaptures_ ReplaceMethods a
s REContext
ctx Match a -> RELocation -> Capture a -> Maybe a
phi Matches a
ac =
    Identity a -> a
forall a. Identity a -> a
runIdentity (Identity a -> a) -> Identity a -> a
forall a b. (a -> b) -> a -> b
$ ReplaceMethods a
-> REContext
-> (Match a -> RELocation -> Capture a -> Identity (Maybe a))
-> Matches a
-> Identity a
forall a (m :: * -> *).
(Extract a, Monad m) =>
ReplaceMethods a
-> REContext
-> (Match a -> RELocation -> Capture a -> m (Maybe a))
-> Matches a
-> m a
replaceAllCapturesM ReplaceMethods a
s REContext
ctx ((Match a -> RELocation -> Capture a -> Maybe a)
-> Match a -> RELocation -> Capture a -> Identity (Maybe a)
forall (m :: * -> *) a.
Monad m =>
(Match a -> RELocation -> Capture a -> Maybe a)
-> Match a -> RELocation -> Capture a -> m (Maybe a)
lift_phi Match a -> RELocation -> Capture a -> Maybe a
phi) Matches a
ac
\end{code}

\begin{code}
-- | replaceAllCapturesM is just a monadically generalised version of
-- replaceAllCaptures_
replaceAllCapturesM :: (Extract a,Monad m)
                    => ReplaceMethods a
                    -> REContext
                    -> (Match a->RELocation->Capture a->m (Maybe a))
                    -> Matches a
                    -> m a
replaceAllCapturesM :: ReplaceMethods a
-> REContext
-> (Match a -> RELocation -> Capture a -> m (Maybe a))
-> Matches a
-> m a
replaceAllCapturesM ReplaceMethods a
r REContext
ctx Match a -> RELocation -> Capture a -> m (Maybe a)
phi_ Matches{a
[Match a]
allMatches :: forall a. Matches a -> [Match a]
matchesSource :: forall a. Matches a -> a
allMatches :: [Match a]
matchesSource :: a
..} =
    ReplaceMethods a
-> REContext
-> (Match a -> RELocation -> Capture a -> m (Maybe a))
-> Match a
-> m a
forall (m :: * -> *) a.
(Monad m, Extract a) =>
ReplaceMethods a
-> REContext
-> (Match a -> RELocation -> Capture a -> m (Maybe a))
-> Match a
-> m a
replaceCapturesM ReplaceMethods a
r REContext
ALL Match a -> RELocation -> Capture a -> m (Maybe a)
phi (Match a -> m a) -> Match a -> m a
forall a b. (a -> b) -> a -> b
$ a -> CaptureNames -> Array CaptureOrdinal (Capture a) -> Match a
forall a.
a -> CaptureNames -> Array CaptureOrdinal (Capture a) -> Match a
Match a
matchesSource CaptureNames
cnms Array CaptureOrdinal (Capture a)
arr
  where
    phi :: Match a -> RELocation -> Capture a -> m (Maybe a)
phi Match a
_ (RELocation Int
_ CaptureOrdinal
i) = case Array CaptureOrdinal (Maybe (Match a))
arr_cArray CaptureOrdinal (Maybe (Match a))
-> CaptureOrdinal -> Maybe (Match a)
forall i e. Ix i => Array i e -> i -> e
!CaptureOrdinal
i of
      Just Match a
caps -> Match a -> RELocation -> Capture a -> m (Maybe a)
phi_ Match a
caps (RELocation -> Capture a -> m (Maybe a))
-> ((Int, CaptureOrdinal) -> RELocation)
-> (Int, CaptureOrdinal)
-> Capture a
-> m (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> CaptureOrdinal -> RELocation)
-> (Int, CaptureOrdinal) -> RELocation
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Int -> CaptureOrdinal -> RELocation
RELocation ((Int, CaptureOrdinal) -> Capture a -> m (Maybe a))
-> (Int, CaptureOrdinal) -> Capture a -> m (Maybe a)
forall a b. (a -> b) -> a -> b
$ Array CaptureOrdinal (Int, CaptureOrdinal)
arr_i Array CaptureOrdinal (Int, CaptureOrdinal)
-> CaptureOrdinal -> (Int, CaptureOrdinal)
forall i e. Ix i => Array i e -> i -> e
! CaptureOrdinal
i
      Maybe (Match a)
Nothing   -> m (Maybe a) -> Capture a -> m (Maybe a)
forall a b. a -> b -> a
const (m (Maybe a) -> Capture a -> m (Maybe a))
-> m (Maybe a) -> Capture a -> m (Maybe a)
forall a b. (a -> b) -> a -> b
$ Maybe a -> m (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing

    arr_c :: Array CaptureOrdinal (Maybe (Match a))
arr_c = (CaptureOrdinal, CaptureOrdinal)
-> [Maybe (Match a)] -> Array CaptureOrdinal (Maybe (Match a))
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (CaptureOrdinal, CaptureOrdinal)
bds ([Maybe (Match a)] -> Array CaptureOrdinal (Maybe (Match a)))
-> [Maybe (Match a)] -> Array CaptureOrdinal (Maybe (Match a))
forall a b. (a -> b) -> a -> b
$
      [[Maybe (Match a)]] -> [Maybe (Match a)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Maybe (Match a)]] -> [Maybe (Match a)])
-> [[Maybe (Match a)]] -> [Maybe (Match a)]
forall a b. (a -> b) -> a -> b
$
        [ Int -> Match a -> [Maybe (Match a)]
repl ((CaptureOrdinal, CaptureOrdinal) -> Int
forall a. Ix a => (a, a) -> Int
rangeSize ((CaptureOrdinal, CaptureOrdinal) -> Int)
-> (CaptureOrdinal, CaptureOrdinal) -> Int
forall a b. (a -> b) -> a -> b
$ Array CaptureOrdinal (Capture a)
-> (CaptureOrdinal, CaptureOrdinal)
forall i e. Array i e -> (i, i)
bounds (Array CaptureOrdinal (Capture a)
 -> (CaptureOrdinal, CaptureOrdinal))
-> Array CaptureOrdinal (Capture a)
-> (CaptureOrdinal, CaptureOrdinal)
forall a b. (a -> b) -> a -> b
$ Match a -> Array CaptureOrdinal (Capture a)
forall a. Match a -> Array CaptureOrdinal (Capture a)
matchArray Match a
cs) Match a
cs
            | Match a
cs <- [Match a]
allMatches
            ]

    arr_i :: Array CaptureOrdinal (Int, CaptureOrdinal)
arr_i = (CaptureOrdinal, CaptureOrdinal)
-> [(Int, CaptureOrdinal)]
-> Array CaptureOrdinal (Int, CaptureOrdinal)
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (CaptureOrdinal, CaptureOrdinal)
bds [(Int, CaptureOrdinal)]
j_ks

    arr :: Array CaptureOrdinal (Capture a)
arr   = (CaptureOrdinal, CaptureOrdinal)
-> [Capture a] -> Array CaptureOrdinal (Capture a)
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (CaptureOrdinal, CaptureOrdinal)
bds ([Capture a] -> Array CaptureOrdinal (Capture a))
-> [Capture a] -> Array CaptureOrdinal (Capture a)
forall a b. (a -> b) -> a -> b
$
        [ Array CaptureOrdinal (Capture a)
arr_ Array CaptureOrdinal (Capture a) -> CaptureOrdinal -> Capture a
forall i e. Ix i => Array i e -> i -> e
! CaptureOrdinal
k
            | Array CaptureOrdinal (Capture a)
arr_ <- (Match a -> Array CaptureOrdinal (Capture a))
-> [Match a] -> [Array CaptureOrdinal (Capture a)]
forall a b. (a -> b) -> [a] -> [b]
map Match a -> Array CaptureOrdinal (Capture a)
forall a. Match a -> Array CaptureOrdinal (Capture a)
matchArray [Match a]
allMatches
            , CaptureOrdinal
k    <- Array CaptureOrdinal (Capture a) -> [CaptureOrdinal]
forall i e. Ix i => Array i e -> [i]
indices Array CaptureOrdinal (Capture a)
arr_
            ]

    bds :: (CaptureOrdinal, CaptureOrdinal)
bds   = (CaptureOrdinal
0,Int -> CaptureOrdinal
CaptureOrdinal (Int -> CaptureOrdinal) -> Int -> CaptureOrdinal
forall a b. (a -> b) -> a -> b
$ [(Int, CaptureOrdinal)] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Int, CaptureOrdinal)]
j_ksInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)

    j_ks :: [(Int, CaptureOrdinal)]
j_ks  =
        [ (Int
j,CaptureOrdinal
k)
            | (Int
j,Array CaptureOrdinal (Capture a)
arr_) <- [Int]
-> [Array CaptureOrdinal (Capture a)]
-> [(Int, Array CaptureOrdinal (Capture a))]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..] ([Array CaptureOrdinal (Capture a)]
 -> [(Int, Array CaptureOrdinal (Capture a))])
-> [Array CaptureOrdinal (Capture a)]
-> [(Int, Array CaptureOrdinal (Capture a))]
forall a b. (a -> b) -> a -> b
$ (Match a -> Array CaptureOrdinal (Capture a))
-> [Match a] -> [Array CaptureOrdinal (Capture a)]
forall a b. (a -> b) -> [a] -> [b]
map Match a -> Array CaptureOrdinal (Capture a)
forall a. Match a -> Array CaptureOrdinal (Capture a)
matchArray [Match a]
allMatches
            ,  CaptureOrdinal
k       <- Array CaptureOrdinal (Capture a) -> [CaptureOrdinal]
forall i e. Ix i => Array i e -> [i]
indices Array CaptureOrdinal (Capture a)
arr_
            ]

    repl :: Int -> Match a -> [Maybe (Match a)]
repl Int
0 Match a
_ = []
    repl Int
n Match a
x = case REContext
ctx of
      REContext
TOP -> Match a -> Maybe (Match a)
forall a. a -> Maybe a
Just Match a
x  Maybe (Match a) -> [Maybe (Match a)] -> [Maybe (Match a)]
forall a. a -> [a] -> [a]
: Int -> Maybe (Match a) -> [Maybe (Match a)]
forall a. Int -> a -> [a]
replicate (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) Maybe (Match a)
forall a. Maybe a
Nothing
      REContext
SUB -> Maybe (Match a)
forall a. Maybe a
Nothing Maybe (Match a) -> [Maybe (Match a)] -> [Maybe (Match a)]
forall a. a -> [a] -> [a]
: Int -> Maybe (Match a) -> [Maybe (Match a)]
forall a. Int -> a -> [a]
replicate (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) (Match a -> Maybe (Match a)
forall a. a -> Maybe a
Just Match a
x)
      REContext
ALL -> Int -> Maybe (Match a) -> [Maybe (Match a)]
forall a. Int -> a -> [a]
replicate Int
n (Maybe (Match a) -> [Maybe (Match a)])
-> Maybe (Match a) -> [Maybe (Match a)]
forall a b. (a -> b) -> a -> b
$ Match a -> Maybe (Match a)
forall a. a -> Maybe a
Just Match a
x

    cnms :: CaptureNames
cnms = CaptureNames -> Maybe CaptureNames -> CaptureNames
forall a. a -> Maybe a -> a
fromMaybe CaptureNames
noCaptureNames (Maybe CaptureNames -> CaptureNames)
-> Maybe CaptureNames -> CaptureNames
forall a b. (a -> b) -> a -> b
$ [CaptureNames] -> Maybe CaptureNames
forall a. [a] -> Maybe a
listToMaybe ([CaptureNames] -> Maybe CaptureNames)
-> [CaptureNames] -> Maybe CaptureNames
forall a b. (a -> b) -> a -> b
$ (Match a -> CaptureNames) -> [Match a] -> [CaptureNames]
forall a b. (a -> b) -> [a] -> [b]
map Match a -> CaptureNames
forall a. Match a -> CaptureNames
captureNames [Match a]
allMatches
\end{code}

\begin{code}
-- | replace with a template containing $0 for whole text,
-- $1 for first capture, etc.
replace :: Replace a
        => a
        -> Match a
        -> a
replace :: a -> Match a -> a
replace a
tpl Match a
c = REContext
-> (Match a -> RELocation -> Capture a -> Maybe a) -> Match a -> a
forall a.
Replace a =>
REContext
-> (Match a -> RELocation -> Capture a -> Maybe a) -> Match a -> a
replaceCaptures REContext
TOP (a -> Match a -> RELocation -> Capture a -> Maybe a
forall a.
Replace a =>
a -> Match a -> RELocation -> Capture a -> Maybe a
parseTemplateR a
tpl) Match a
c
\end{code}

\begin{code}
-- | substitutes using a function that takes the full Match
-- context and returns the same replacement text as the _phi_phi
-- context.
replaceCaptures :: Replace a
                 => REContext
                 -> (Match a->RELocation->Capture a->Maybe a)
                 -> Match a
                 -> a
replaceCaptures :: REContext
-> (Match a -> RELocation -> Capture a -> Maybe a) -> Match a -> a
replaceCaptures = ReplaceMethods a
-> REContext
-> (Match a -> RELocation -> Capture a -> Maybe a)
-> Match a
-> a
forall a.
Extract a =>
ReplaceMethods a
-> REContext
-> (Match a -> RELocation -> Capture a -> Maybe a)
-> Match a
-> a
replaceCaptures_ ReplaceMethods a
forall a. Replace a => ReplaceMethods a
replaceMethods
\end{code}

\begin{code}
-- | replaceCaptures_ is like replaceCaptures but takes the Replace methods
-- through the ReplaceMethods argument
replaceCaptures_ :: Extract a
                 => ReplaceMethods a
                 -> REContext
                 -> (Match a->RELocation->Capture a->Maybe a)
                 -> Match a
                 -> a
replaceCaptures_ :: ReplaceMethods a
-> REContext
-> (Match a -> RELocation -> Capture a -> Maybe a)
-> Match a
-> a
replaceCaptures_ ReplaceMethods a
s REContext
ctx Match a -> RELocation -> Capture a -> Maybe a
phi Match a
caps =
  Identity a -> a
forall a. Identity a -> a
runIdentity (Identity a -> a) -> Identity a -> a
forall a b. (a -> b) -> a -> b
$ ReplaceMethods a
-> REContext
-> (Match a -> RELocation -> Capture a -> Identity (Maybe a))
-> Match a
-> Identity a
forall (m :: * -> *) a.
(Monad m, Extract a) =>
ReplaceMethods a
-> REContext
-> (Match a -> RELocation -> Capture a -> m (Maybe a))
-> Match a
-> m a
replaceCapturesM ReplaceMethods a
s REContext
ctx ((Match a -> RELocation -> Capture a -> Maybe a)
-> Match a -> RELocation -> Capture a -> Identity (Maybe a)
forall (m :: * -> *) a.
Monad m =>
(Match a -> RELocation -> Capture a -> Maybe a)
-> Match a -> RELocation -> Capture a -> m (Maybe a)
lift_phi Match a -> RELocation -> Capture a -> Maybe a
phi) Match a
caps
\end{code}

\begin{code}
-- | replaceCapturesM is just a monadically generalised version of
-- replaceCaptures_
replaceCapturesM :: (Monad m,Extract a)
                 => ReplaceMethods a
                 -> REContext
                 -> (Match a->RELocation->Capture a->m (Maybe a))
                 -> Match a
                 -> m a
replaceCapturesM :: ReplaceMethods a
-> REContext
-> (Match a -> RELocation -> Capture a -> m (Maybe a))
-> Match a
-> m a
replaceCapturesM ReplaceMethods{a -> Int
(a -> a) -> Capture a -> a
methodSubst :: forall a. ReplaceMethods a -> (a -> a) -> Capture a -> a
methodLength :: forall a. ReplaceMethods a -> a -> Int
methodSubst :: (a -> a) -> Capture a -> a
methodLength :: a -> Int
..} REContext
ctx Match a -> RELocation -> Capture a -> m (Maybe a)
phi_ caps :: Match a
caps@Match{a
Array CaptureOrdinal (Capture a)
CaptureNames
matchSource :: forall a. Match a -> a
matchArray :: Array CaptureOrdinal (Capture a)
captureNames :: CaptureNames
matchSource :: a
captureNames :: forall a. Match a -> CaptureNames
matchArray :: forall a. Match a -> Array CaptureOrdinal (Capture a)
..} = do
    (a
hay',[(Int, Int)]
_) <- ((CaptureOrdinal, Capture a)
 -> m (a, [(Int, Int)]) -> m (a, [(Int, Int)]))
-> m (a, [(Int, Int)])
-> [(CaptureOrdinal, Capture a)]
-> m (a, [(Int, Int)])
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (CaptureOrdinal, Capture a)
-> m (a, [(Int, Int)]) -> m (a, [(Int, Int)])
sc ((a, [(Int, Int)]) -> m (a, [(Int, Int)])
forall (m :: * -> *) a. Monad m => a -> m a
return (a
matchSource,[])) ([(CaptureOrdinal, Capture a)] -> m (a, [(Int, Int)]))
-> [(CaptureOrdinal, Capture a)] -> m (a, [(Int, Int)])
forall a b. (a -> b) -> a -> b
$
                    [CaptureOrdinal] -> [Capture a] -> [(CaptureOrdinal, Capture a)]
forall a b. [a] -> [b] -> [(a, b)]
zip [CaptureOrdinal
0..] ([Capture a] -> [(CaptureOrdinal, Capture a)])
-> [Capture a] -> [(CaptureOrdinal, Capture a)]
forall a b. (a -> b) -> a -> b
$ Array CaptureOrdinal (Capture a) -> [Capture a]
forall i e. Array i e -> [e]
elems Array CaptureOrdinal (Capture a)
matchArray
    a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
hay'
  where
    sc :: (CaptureOrdinal, Capture a)
-> m (a, [(Int, Int)]) -> m (a, [(Int, Int)])
sc (CaptureOrdinal
i,Capture a
cap0) m (a, [(Int, Int)])
act = do
      (a
hay,[(Int, Int)]
ds) <- m (a, [(Int, Int)])
act
      let ndl :: a
ndl  = Capture a -> a
forall a. Capture a -> a
capturedText Capture a
cap
          cap :: Capture a
cap  = a -> [(Int, Int)] -> Capture a -> Capture a
forall source a.
Extract source =>
source -> [(Int, Int)] -> Capture a -> Capture source
adj a
hay [(Int, Int)]
ds Capture a
cap0
      Maybe a
mb <- CaptureOrdinal -> Capture a -> m (Maybe a)
phi CaptureOrdinal
i Capture a
cap
      case Maybe a
mb of
        Maybe a
Nothing   -> (a, [(Int, Int)]) -> m (a, [(Int, Int)])
forall (m :: * -> *) a. Monad m => a -> m a
return (a
hay,[(Int, Int)]
ds)
        Just a
ndl' ->
            (a, [(Int, Int)]) -> m (a, [(Int, Int)])
forall (m :: * -> *) a. Monad m => a -> m a
return
              ( (a -> a) -> Capture a -> a
methodSubst (a -> a -> a
forall a b. a -> b -> a
const a
ndl') Capture a
cap
              , (Capture a -> Int
forall a. Capture a -> Int
captureOffset Capture a
cap,Int
len'Int -> Int -> Int
forall a. Num a => a -> a -> a
-Int
len) (Int, Int) -> [(Int, Int)] -> [(Int, Int)]
forall a. a -> [a] -> [a]
: [(Int, Int)]
ds
              )
          where
            len' :: Int
len' = a -> Int
methodLength a
ndl'
            len :: Int
len  = a -> Int
methodLength a
ndl

    adj :: source -> [(Int, Int)] -> Capture a -> Capture source
adj source
hay [(Int, Int)]
ds Capture a
cap =
      Capture :: forall a. a -> a -> Int -> Int -> Capture a
Capture
        { captureSource :: source
captureSource = source
hay
        , capturedText :: source
capturedText  = Int -> source -> source
forall source. Extract source => Int -> source -> source
before Int
len (source -> source) -> source -> source
forall a b. (a -> b) -> a -> b
$ Int -> source -> source
forall source. Extract source => Int -> source -> source
after Int
off0 source
hay
        , captureOffset :: Int
captureOffset = Int
off0
        , captureLength :: Int
captureLength = Int
len
        }
      where
        len :: Int
len  = Int
len0 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum
          [ Int
delta
            | (Int
off,Int
delta) <- [(Int, Int)]
ds
            , Int
off Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
off0 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len0
            ]
        len0 :: Int
len0 = Capture a -> Int
forall a. Capture a -> Int
captureLength Capture a
cap
        off0 :: Int
off0 = Capture a -> Int
forall a. Capture a -> Int
captureOffset Capture a
cap

    phi :: CaptureOrdinal -> Capture a -> m (Maybe a)
phi CaptureOrdinal
i Capture a
cap = case REContext
ctx of
      REContext
TOP | CaptureOrdinal
iCaptureOrdinal -> CaptureOrdinal -> Bool
forall a. Eq a => a -> a -> Bool
/=CaptureOrdinal
0 -> Maybe a -> m (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing
      REContext
SUB | CaptureOrdinal
iCaptureOrdinal -> CaptureOrdinal -> Bool
forall a. Eq a => a -> a -> Bool
==CaptureOrdinal
0 ->Maybe a -> m (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return  Maybe a
forall a. Maybe a
Nothing
      REContext
_          ->
        case Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Capture a -> Bool
forall a. Capture a -> Bool
hasCaptured Capture a
cap of
          Bool
True  -> Maybe a -> m (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing
          Bool
False -> Match a -> RELocation -> Capture a -> m (Maybe a)
phi_ Match a
caps (Int -> CaptureOrdinal -> RELocation
RELocation Int
0 CaptureOrdinal
i) Capture a
cap
\end{code}

expandMacros
------------

\begin{code}
-- | expand all of the @{..} macros in the RE in the argument String
-- according to the Macros argument, preprocessing the RE String
-- according to the Mode argument (used internally)
expandMacros :: (r->String) -> Macros r -> String -> String
expandMacros :: (r -> String) -> Macros r -> ShowS
expandMacros r -> String
x_src Macros r
hm String
s =
  case Macros r -> Bool
forall k v. HashMap k v -> Bool
HM.null Macros r
hm of
    Bool
True  -> String
s
    Bool
False -> (MacroID -> Maybe String) -> ShowS
expandMacros' ((r -> String) -> Maybe r -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap r -> String
x_src (Maybe r -> Maybe String)
-> (MacroID -> Maybe r) -> MacroID -> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MacroID -> Macros r -> Maybe r) -> Macros r -> MacroID -> Maybe r
forall a b c. (a -> b -> c) -> b -> a -> c
flip MacroID -> Macros r -> Maybe r
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HM.lookup Macros r
hm) String
s
\end{code}

\begin{code}
-- | expand the @{..} macros in the argument string using the given
-- function
expandMacros' :: (MacroID->Maybe String) -> String -> String
expandMacros' :: (MacroID -> Maybe String) -> ShowS
expandMacros' MacroID -> Maybe String
lu = ShowS -> ShowS
forall a. Eq a => (a -> a) -> a -> a
fixpoint ShowS
e_m
  where
    e_m :: ShowS
e_m String
re_s = REContext
-> (Match String -> RELocation -> Capture String -> Maybe String)
-> Matches String
-> String
forall a.
Replace a =>
REContext
-> (Match a -> RELocation -> Capture a -> Maybe a)
-> Matches a
-> a
replaceAllCaptures REContext
TOP Match String -> RELocation -> Capture String -> Maybe String
phi (Matches String -> String) -> Matches String -> String
forall a b. (a -> b) -> a -> b
$ String
re_s String -> String -> Matches String
forall source target.
(RegexContext Regex source target,
 RegexMaker Regex CompOption ExecOption String) =>
source -> String -> target
$=~ String
"@(@|\\{([^{}]+)\\})"
      where
        phi :: Match String -> RELocation -> Capture String -> Maybe String
phi Match String
mtch RELocation
_ Capture String
cap = case String
txt String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"@@" of
            Bool
True  -> String -> Maybe String
forall a. a -> Maybe a
Just   String
"@"
            Bool
False -> String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
txt (Maybe String -> String) -> Maybe String -> String
forall a b. (a -> b) -> a -> b
$ MacroID -> Maybe String
lu MacroID
ide
          where
            txt :: String
txt = Capture String -> String
forall a. Capture a -> a
capturedText Capture String
cap
            ide :: MacroID
ide = String -> MacroID
MacroID (String -> MacroID) -> String -> MacroID
forall a b. (a -> b) -> a -> b
$ Capture String -> String
forall a. Capture a -> a
capturedText (Capture String -> String) -> Capture String -> String
forall a b. (a -> b) -> a -> b
$ CaptureID -> Match String -> Capture String
forall a. CaptureID -> Match a -> Capture a
capture CaptureID
c2 Match String
mtch
            c2 :: CaptureID
c2  = CaptureOrdinal -> CaptureID
IsCaptureOrdinal (CaptureOrdinal -> CaptureID) -> CaptureOrdinal -> CaptureID
forall a b. (a -> b) -> a -> b
$ Int -> CaptureOrdinal
CaptureOrdinal Int
2
\end{code}

\begin{code}
lift_phi :: Monad m
         => (Match a->RELocation->Capture a->Maybe a)
         -> (Match a->RELocation->Capture a->m (Maybe a))
lift_phi :: (Match a -> RELocation -> Capture a -> Maybe a)
-> Match a -> RELocation -> Capture a -> m (Maybe a)
lift_phi Match a -> RELocation -> Capture a -> Maybe a
phi_ = Match a -> RELocation -> Capture a -> m (Maybe a)
phi
  where
    phi :: Match a -> RELocation -> Capture a -> m (Maybe a)
phi Match a
caps' RELocation
loc' Capture a
cap' = Maybe a -> m (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> m (Maybe a)) -> Maybe a -> m (Maybe a)
forall a b. (a -> b) -> a -> b
$ Match a -> RELocation -> Capture a -> Maybe a
phi_ Match a
caps' RELocation
loc' Capture a
cap'
\end{code}


templateCaptures
----------------

\begin{code}
-- | list all of the CaptureID references in the replace template in
-- the second argument
templateCaptures :: ( Replace a
                    , RegexContext Regex a (Matches a)
                    , RegexMaker   Regex CompOption ExecOption String
                    )
                 => (a->String)
                 -> a
                 -> [CaptureID]
templateCaptures :: (a -> String) -> a -> [CaptureID]
templateCaptures a -> String
unpack a
tpl =
    [ CaptureID
cid
      | Match a
mtch <- Matches a -> [Match a]
forall a. Matches a -> [Match a]
allMatches (Matches a -> [Match a]) -> Matches a -> [Match a]
forall a b. (a -> b) -> a -> b
$ a -> Matches a
forall a.
(Replace a, RegexContext Regex a (Matches a),
 RegexMaker Regex CompOption ExecOption String) =>
a -> Matches a
scan_template a
tpl
      , Right CaptureID
cid <- [(a -> String) -> Match a -> Either a CaptureID
forall a. (a -> String) -> Match a -> Either a CaptureID
parse_template_capture a -> String
unpack Match a
mtch]
      ]

-- | parse a Match generated by acan_template, returning @Left "$")
-- iff the capture reference is an escaped @$@ (i.e., @$$@)
parse_template_capture :: (a->String) -> Match a -> Either a CaptureID
parse_template_capture :: (a -> String) -> Match a -> Either a CaptureID
parse_template_capture a -> String
unpack Match a
t_mtch = case Match a
t_mtch Match a -> CaptureID -> Maybe (Capture a)
forall a. Match a -> CaptureID -> Maybe (Capture a)
!$? CaptureID
c2 of
  Just Capture a
cap -> case String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe String
stg of
      Maybe Int
Nothing -> CaptureID -> Either a CaptureID
forall a b. b -> Either a b
Right (CaptureID -> Either a CaptureID)
-> CaptureID -> Either a CaptureID
forall a b. (a -> b) -> a -> b
$ CaptureName -> CaptureID
IsCaptureName    (CaptureName -> CaptureID) -> CaptureName -> CaptureID
forall a b. (a -> b) -> a -> b
$ Text -> CaptureName
CaptureName (Text -> CaptureName) -> Text -> CaptureName
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack String
stg
      Just Int
cn -> CaptureID -> Either a CaptureID
forall a b. b -> Either a b
Right (CaptureID -> Either a CaptureID)
-> CaptureID -> Either a CaptureID
forall a b. (a -> b) -> a -> b
$ CaptureOrdinal -> CaptureID
IsCaptureOrdinal (CaptureOrdinal -> CaptureID) -> CaptureOrdinal -> CaptureID
forall a b. (a -> b) -> a -> b
$ Int -> CaptureOrdinal
CaptureOrdinal Int
cn
    where
      stg :: String
stg = a -> String
unpack (a -> String) -> a -> String
forall a b. (a -> b) -> a -> b
$ Capture a -> a
forall a. Capture a -> a
capturedText Capture a
cap
  Maybe (Capture a)
Nothing -> case String
s String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"$" of
    Bool
True  -> a -> Either a CaptureID
forall a b. a -> Either a b
Left a
t
    Bool
False -> CaptureID -> Either a CaptureID
forall a b. b -> Either a b
Right (CaptureID -> Either a CaptureID)
-> CaptureID -> Either a CaptureID
forall a b. (a -> b) -> a -> b
$ CaptureOrdinal -> CaptureID
IsCaptureOrdinal (CaptureOrdinal -> CaptureID) -> CaptureOrdinal -> CaptureID
forall a b. (a -> b) -> a -> b
$ Int -> CaptureOrdinal
CaptureOrdinal (Int -> CaptureOrdinal) -> Int -> CaptureOrdinal
forall a b. (a -> b) -> a -> b
$ String -> Int
forall a. Read a => String -> a
read String
s
  where
    s :: String
s = a -> String
unpack a
t
    t :: a
t = Capture a -> a
forall a. Capture a -> a
capturedText (Capture a -> a) -> Capture a -> a
forall a b. (a -> b) -> a -> b
$ CaptureID -> Match a -> Capture a
forall a. CaptureID -> Match a -> Capture a
capture CaptureID
c1 Match a
t_mtch

    c1 :: CaptureID
c1 = CaptureOrdinal -> CaptureID
IsCaptureOrdinal (CaptureOrdinal -> CaptureID) -> CaptureOrdinal -> CaptureID
forall a b. (a -> b) -> a -> b
$ Int -> CaptureOrdinal
CaptureOrdinal Int
1
    c2 :: CaptureID
c2 = CaptureOrdinal -> CaptureID
IsCaptureOrdinal (CaptureOrdinal -> CaptureID) -> CaptureOrdinal -> CaptureID
forall a b. (a -> b) -> a -> b
$ Int -> CaptureOrdinal
CaptureOrdinal Int
2

-- | scan a replacement template, returning a Match for each capture
-- reference in the template (like $1, ${foo})
scan_template :: ( Replace a
                 , RegexContext Regex a (Matches a)
                 , RegexMaker   Regex CompOption ExecOption String
                 )
              => a
              -> Matches a
scan_template :: a -> Matches a
scan_template a
tpl = a
tpl a -> String -> Matches a
forall source target.
(RegexContext Regex source target,
 RegexMaker Regex CompOption ExecOption String) =>
source -> String -> target
$=~ String
"\\$(\\$|[0-9]|\\{([^{}]+)\\})"
\end{code}


Replace and ReplaceMethods
--------------------------

\begin{code}
-- | Replace provides the missing needed to replace the matched
-- text in a @Replace a => Match a@.
class (Show a,Eq a,Ord a,Extract a,Monoid a) => Replace a where
  -- | length function for a
  lengthR        :: a -> Int
  -- | inject String into a
  packR          :: String -> a
  -- | project a onto a String
  unpackR        :: a -> String
  -- | inject into Text
  textifyR       :: a -> T.Text
  -- | project Text onto a
  detextifyR     :: T.Text -> a
  -- | split into lines
  linesR         :: a -> [a]
  -- | concatenate a list of lines
  unlinesR       :: [a] -> a
  -- | append a newline
  appendNewlineR :: a -> a
  -- | apply a substitution function to a Capture
  substR         :: (a->a) -> Capture a -> a
  -- | convert a template containing $0, $1, etc., in the first
  -- argument, into a 'phi' replacement function for use with
  -- replaceAllCaptures and replaceCaptures
  parseTemplateR :: a -> Match a -> RELocation -> Capture a -> Maybe a

  textifyR       = String -> Text
T.pack (String -> Text) -> (a -> String) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Replace a => a -> String
unpackR
  detextifyR     = String -> a
forall a. Replace a => String -> a
packR  (String -> a) -> (Text -> String) -> Text -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack
  appendNewlineR = (a -> a -> a
forall a. Semigroup a => a -> a -> a
M.<> String -> a
forall a. Replace a => String -> a
packR String
"\n")

  substR a -> a
f m :: Capture a
m@Capture{a
Int
captureLength :: Int
captureOffset :: Int
capturedText :: a
captureSource :: a
captureLength :: forall a. Capture a -> Int
captureSource :: forall a. Capture a -> a
captureOffset :: forall a. Capture a -> Int
capturedText :: forall a. Capture a -> a
..} =
    Capture a -> a
forall a. Extract a => Capture a -> a
capturePrefix Capture a
m a -> a -> a
forall a. Semigroup a => a -> a -> a
M.<> a -> a
f a
capturedText a -> a -> a
forall a. Semigroup a => a -> a -> a
M.<> Capture a -> a
forall a. Extract a => Capture a -> a
captureSuffix Capture a
m
\end{code}

\begin{code}
-- | a selection of the Replace methods can be encapsulated with ReplaceMethods
-- for the higher-order replacement functions
data ReplaceMethods a =
  ReplaceMethods
    { ReplaceMethods a -> a -> Int
methodLength :: a -> Int
    , ReplaceMethods a -> (a -> a) -> Capture a -> a
methodSubst  :: (a->a) -> Capture a -> a
    }

-- | replaceMethods encapsulates ReplaceMethods a from a Replace a context
replaceMethods :: Replace a => ReplaceMethods a
replaceMethods :: ReplaceMethods a
replaceMethods =
  ReplaceMethods :: forall a.
(a -> Int) -> ((a -> a) -> Capture a -> a) -> ReplaceMethods a
ReplaceMethods
    { methodLength :: a -> Int
methodLength = a -> Int
forall a. Replace a => a -> Int
lengthR
    , methodSubst :: (a -> a) -> Capture a -> a
methodSubst  = (a -> a) -> Capture a -> a
forall a. Replace a => (a -> a) -> Capture a -> a
substR
    }
\end{code}


The Replace Instances
---------------------

\begin{code}
instance Replace [Char] where
  lengthR :: String -> Int
lengthR         = String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length
  packR :: ShowS
packR           = ShowS
forall a. a -> a
id
  unpackR :: ShowS
unpackR         = ShowS
forall a. a -> a
id
  textifyR :: String -> Text
textifyR        = String -> Text
T.pack
  detextifyR :: Text -> String
detextifyR      = Text -> String
T.unpack
  linesR :: String -> [String]
linesR          = String -> [String]
lines
  unlinesR :: [String] -> String
unlinesR        = [String] -> String
unlines
  appendNewlineR :: ShowS
appendNewlineR  = (String -> ShowS
forall a. Semigroup a => a -> a -> a
M.<>String
"\n")
  parseTemplateR :: String
-> Match String -> RELocation -> Capture String -> Maybe String
parseTemplateR  = ShowS
-> String
-> Match String
-> RELocation
-> Capture String
-> Maybe String
forall a.
(Replace a, RegexContext Regex a (Matches a),
 RegexMaker Regex CompOption ExecOption String) =>
(a -> String) -> a -> Match a -> RELocation -> Capture a -> Maybe a
parseTemplateR' ShowS
forall a. a -> a
id

instance Replace B.ByteString where
  lengthR :: ByteString -> Int
lengthR         = ByteString -> Int
B.length
  packR :: String -> ByteString
packR           = String -> ByteString
B.pack
  unpackR :: ByteString -> String
unpackR         = ByteString -> String
B.unpack
  textifyR :: ByteString -> Text
textifyR        = ByteString -> Text
TE.decodeUtf8
  detextifyR :: Text -> ByteString
detextifyR      = Text -> ByteString
TE.encodeUtf8
  linesR :: ByteString -> [ByteString]
linesR          = ByteString -> [ByteString]
B.lines
  unlinesR :: [ByteString] -> ByteString
unlinesR        = [ByteString] -> ByteString
B.unlines
  appendNewlineR :: ByteString -> ByteString
appendNewlineR  = (ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
M.<>ByteString
"\n")
  parseTemplateR :: ByteString
-> Match ByteString
-> RELocation
-> Capture ByteString
-> Maybe ByteString
parseTemplateR  = (ByteString -> String)
-> ByteString
-> Match ByteString
-> RELocation
-> Capture ByteString
-> Maybe ByteString
forall a.
(Replace a, RegexContext Regex a (Matches a),
 RegexMaker Regex CompOption ExecOption String) =>
(a -> String) -> a -> Match a -> RELocation -> Capture a -> Maybe a
parseTemplateR' ByteString -> String
B.unpack

instance Replace LBS.ByteString where
  lengthR :: ByteString -> Int
lengthR         = Int64 -> Int
forall a. Enum a => a -> Int
fromEnum (Int64 -> Int) -> (ByteString -> Int64) -> ByteString -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Int64
LBS.length
  packR :: String -> ByteString
packR           = String -> ByteString
LBS.pack
  unpackR :: ByteString -> String
unpackR         = ByteString -> String
LBS.unpack
  textifyR :: ByteString -> Text
textifyR        = ByteString -> Text
TE.decodeUtf8  (ByteString -> Text)
-> (ByteString -> ByteString) -> ByteString -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
LBS.toStrict
  linesR :: ByteString -> [ByteString]
linesR          = ByteString -> [ByteString]
LBS.lines
  unlinesR :: [ByteString] -> ByteString
unlinesR        = [ByteString] -> ByteString
LBS.unlines
  detextifyR :: Text -> ByteString
detextifyR      = ByteString -> ByteString
LBS.fromStrict (ByteString -> ByteString)
-> (Text -> ByteString) -> Text -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
TE.encodeUtf8
  appendNewlineR :: ByteString -> ByteString
appendNewlineR  = (ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
M.<>ByteString
"\n")
  parseTemplateR :: ByteString
-> Match ByteString
-> RELocation
-> Capture ByteString
-> Maybe ByteString
parseTemplateR  = (ByteString -> String)
-> ByteString
-> Match ByteString
-> RELocation
-> Capture ByteString
-> Maybe ByteString
forall a.
(Replace a, RegexContext Regex a (Matches a),
 RegexMaker Regex CompOption ExecOption String) =>
(a -> String) -> a -> Match a -> RELocation -> Capture a -> Maybe a
parseTemplateR' ByteString -> String
LBS.unpack

instance Replace (S.Seq Char) where
  lengthR :: Seq Char -> Int
lengthR         = Seq Char -> Int
forall a. Seq a -> Int
S.length
  packR :: String -> Seq Char
packR           = String -> Seq Char
forall a. [a] -> Seq a
S.fromList
  unpackR :: Seq Char -> String
unpackR         = Seq Char -> String
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList
  linesR :: Seq Char -> [Seq Char]
linesR          = (String -> Seq Char) -> [String] -> [Seq Char]
forall a b. (a -> b) -> [a] -> [b]
map String -> Seq Char
forall a. Replace a => String -> a
packR ([String] -> [Seq Char])
-> (Seq Char -> [String]) -> Seq Char -> [Seq Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
lines (String -> [String])
-> (Seq Char -> String) -> Seq Char -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Seq Char -> String
forall a. Replace a => a -> String
unpackR
  unlinesR :: [Seq Char] -> Seq Char
unlinesR        = String -> Seq Char
forall a. Replace a => String -> a
packR (String -> Seq Char)
-> ([Seq Char] -> String) -> [Seq Char] -> Seq Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
unlines ([String] -> String)
-> ([Seq Char] -> [String]) -> [Seq Char] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Seq Char -> String) -> [Seq Char] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Seq Char -> String
forall a. Replace a => a -> String
unpackR
  parseTemplateR :: Seq Char
-> Match (Seq Char)
-> RELocation
-> Capture (Seq Char)
-> Maybe (Seq Char)
parseTemplateR  = (Seq Char -> String)
-> Seq Char
-> Match (Seq Char)
-> RELocation
-> Capture (Seq Char)
-> Maybe (Seq Char)
forall a.
(Replace a, RegexContext Regex a (Matches a),
 RegexMaker Regex CompOption ExecOption String) =>
(a -> String) -> a -> Match a -> RELocation -> Capture a -> Maybe a
parseTemplateR' Seq Char -> String
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList

instance Replace T.Text where
  lengthR :: Text -> Int
lengthR         = Text -> Int
T.length
  packR :: String -> Text
packR           = String -> Text
T.pack
  unpackR :: Text -> String
unpackR         = Text -> String
T.unpack
  textifyR :: Text -> Text
textifyR        = Text -> Text
forall a. a -> a
id
  detextifyR :: Text -> Text
detextifyR      = Text -> Text
forall a. a -> a
id
  linesR :: Text -> [Text]
linesR          = Text -> [Text]
T.lines
  unlinesR :: [Text] -> Text
unlinesR        = [Text] -> Text
T.unlines
  appendNewlineR :: Text -> Text
appendNewlineR  = (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
M.<>Text
"\n")
  parseTemplateR :: Text -> Match Text -> RELocation -> Capture Text -> Maybe Text
parseTemplateR  = (Text -> String)
-> Text -> Match Text -> RELocation -> Capture Text -> Maybe Text
forall a.
(Replace a, RegexContext Regex a (Matches a),
 RegexMaker Regex CompOption ExecOption String) =>
(a -> String) -> a -> Match a -> RELocation -> Capture a -> Maybe a
parseTemplateR' Text -> String
T.unpack

instance Replace LT.Text where
  lengthR :: Text -> Int
lengthR         = Int64 -> Int
forall a. Enum a => a -> Int
fromEnum (Int64 -> Int) -> (Text -> Int64) -> Text -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Int64
LT.length
  packR :: String -> Text
packR           = String -> Text
LT.pack
  unpackR :: Text -> String
unpackR         = Text -> String
LT.unpack
  textifyR :: Text -> Text
textifyR        = Text -> Text
LT.toStrict
  detextifyR :: Text -> Text
detextifyR      = Text -> Text
LT.fromStrict
  linesR :: Text -> [Text]
linesR          = Text -> [Text]
LT.lines
  unlinesR :: [Text] -> Text
unlinesR        = [Text] -> Text
LT.unlines
  appendNewlineR :: Text -> Text
appendNewlineR  = (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
M.<>Text
"\n")
  parseTemplateR :: Text -> Match Text -> RELocation -> Capture Text -> Maybe Text
parseTemplateR  = (Text -> String)
-> Text -> Match Text -> RELocation -> Capture Text -> Maybe Text
forall a.
(Replace a, RegexContext Regex a (Matches a),
 RegexMaker Regex CompOption ExecOption String) =>
(a -> String) -> a -> Match a -> RELocation -> Capture a -> Maybe a
parseTemplateR' Text -> String
LT.unpack
\end{code}


Parsing Replace Templates
-------------------------

\begin{code}
-- | parse the replacement template in second argument, substituting
-- the capture references with corresponding captures from the Match
-- in the third argument (the result of a single match of the RE
-- against the input text to be matched); Nothing is returned if the
-- inputs are not well formed (currently all inputs are well formed)
parseTemplateR' :: ( Replace a
                   , RegexContext Regex a (Matches a)
                   , RegexMaker   Regex CompOption ExecOption String
                   )
                   => (a->String)
                   -> a
                   -> Match a
                   -> RELocation
                   -> Capture a
                   -> Maybe a
parseTemplateR' :: (a -> String) -> a -> Match a -> RELocation -> Capture a -> Maybe a
parseTemplateR' a -> String
unpack a
tpl Match a
mtch RELocation
_ Capture a
_ =
    a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$ REContext
-> (Match a -> RELocation -> Capture a -> Maybe a)
-> Matches a
-> a
forall a.
Replace a =>
REContext
-> (Match a -> RELocation -> Capture a -> Maybe a)
-> Matches a
-> a
replaceAllCaptures REContext
TOP Match a -> RELocation -> Capture a -> Maybe a
phi (Matches a -> a) -> Matches a -> a
forall a b. (a -> b) -> a -> b
$ a -> Matches a
forall a.
(Replace a, RegexContext Regex a (Matches a),
 RegexMaker Regex CompOption ExecOption String) =>
a -> Matches a
scan_template a
tpl
  where
    phi :: Match a -> RELocation -> Capture a -> Maybe a
phi Match a
t_mtch RELocation
_ Capture a
_ = (a -> Maybe a)
-> (CaptureID -> Maybe a) -> Either a CaptureID -> Maybe a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either a -> Maybe a
forall a. a -> Maybe a
Just CaptureID -> Maybe a
this (Either a CaptureID -> Maybe a) -> Either a CaptureID -> Maybe a
forall a b. (a -> b) -> a -> b
$ (a -> String) -> Match a -> Either a CaptureID
forall a. (a -> String) -> Match a -> Either a CaptureID
parse_template_capture a -> String
unpack Match a
t_mtch

    this :: CaptureID -> Maybe a
this CaptureID
cid       = Capture a -> a
forall a. Capture a -> a
capturedText (Capture a -> a) -> Maybe (Capture a) -> Maybe a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Match a
mtch Match a -> CaptureID -> Maybe (Capture a)
forall a. Match a -> CaptureID -> Maybe (Capture a)
!$? CaptureID
cid
\end{code}


Helpers
-------

\begin{code}
fixpoint :: (Eq a) => (a->a) -> a -> a
fixpoint :: (a -> a) -> a -> a
fixpoint a -> a
f = [a] -> a
forall a. Eq a => [a] -> a
chk ([a] -> a) -> (a -> [a]) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> a) -> a -> [a]
forall a. (a -> a) -> a -> [a]
iterate a -> a
f
  where
    chk :: [a] -> a
chk (a
x:a
x':[a]
_) | a
xa -> a -> Bool
forall a. Eq a => a -> a -> Bool
==a
x' = a
x
    chk [a]
xs               = [a] -> a
chk ([a] -> a) -> [a] -> a
forall a b. (a -> b) -> a -> b
$ [a] -> [a]
forall a. [a] -> [a]
tail [a]
xs
\end{code}

\begin{code}
($=~) :: ( RegexContext Regex source target
         , RegexMaker   Regex CompOption ExecOption String
         )
      => source -> String -> target
$=~ :: source -> String -> target
($=~) = source -> String -> target
forall source source1 target.
(RegexMaker Regex CompOption ExecOption source,
 RegexContext Regex source1 target) =>
source1 -> source -> target
(=~)
\end{code}