-- | This module is a subset of the defunct regex-compat-tdfa.
module Darcs.Util.Regex
    ( Regex
    , mkRegex
    , mkRegexWithOpts
    , matchRegex
    ) where

import Darcs.Prelude

import Text.Regex.Base
    ( RegexContext(matchM)
    , RegexMaker(makeRegexOpts)
    , defaultCompOpt
    , defaultExecOpt
    )
import Text.Regex.TDFA (Regex, caseSensitive, multiline, newSyntax)

-- | Makes a regular expression with the default options (multi-line,
-- case-sensitive).  The syntax of regular expressions is
-- otherwise that of @egrep@ (i.e. POSIX \"extended\" regular
-- expressions).
mkRegex :: String -> Regex
mkRegex :: String -> Regex
mkRegex String
s = CompOption -> ExecOption -> String -> Regex
forall regex compOpt execOpt source.
RegexMaker regex compOpt execOpt source =>
compOpt -> execOpt -> source -> regex
makeRegexOpts CompOption
opt ExecOption
forall regex compOpt execOpt.
RegexOptions regex compOpt execOpt =>
execOpt
defaultExecOpt String
s
  where
    opt :: CompOption
opt = CompOption
forall regex compOpt execOpt.
RegexOptions regex compOpt execOpt =>
compOpt
defaultCompOpt {newSyntax :: Bool
newSyntax = Bool
True, multiline :: Bool
multiline = Bool
True}

-- | Makes a regular expression, where the multi-line and
-- case-sensitive options can be changed from the default settings.
mkRegexWithOpts
   :: String  -- ^ The regular expression to compile
   -> Bool    -- ^ 'True' @\<=>@ @\'^\'@ and @\'$\'@ match the beginning and 
              -- end of individual lines respectively, and @\'.\'@ does /not/
              -- match the newline character.
   -> Bool    -- ^ 'True' @\<=>@ matching is case-sensitive
   -> Regex   -- ^ Returns: the compiled regular expression
mkRegexWithOpts :: String -> Bool -> Bool -> Regex
mkRegexWithOpts String
s Bool
single_line Bool
case_sensitive
  = let opt :: CompOption
opt = CompOption
forall regex compOpt execOpt.
RegexOptions regex compOpt execOpt =>
compOpt
defaultCompOpt
                { multiline :: Bool
multiline    = (if Bool
single_line then Bool
True else Bool
False)
                , caseSensitive :: Bool
caseSensitive = (if Bool
case_sensitive then Bool
True else Bool
False)
                , newSyntax :: Bool
newSyntax     = Bool
True }
    in CompOption -> ExecOption -> String -> Regex
forall regex compOpt execOpt source.
RegexMaker regex compOpt execOpt source =>
compOpt -> execOpt -> source -> regex
makeRegexOpts CompOption
opt ExecOption
forall regex compOpt execOpt.
RegexOptions regex compOpt execOpt =>
execOpt
defaultExecOpt String
s

-- | Match a regular expression against a string
matchRegex ::
     Regex -- ^ The regular expression
  -> String -- ^ The string to match against
  -> Maybe [String] -- ^ Returns: @'Just' strs@ if the match succeeded
                      -- (and @strs@ is the list of subexpression matches),
                      -- or 'Nothing' otherwise.
matchRegex :: Regex -> String -> Maybe [String]
matchRegex Regex
p String
str = ((String, String, String, [String]) -> [String])
-> Maybe (String, String, String, [String]) -> Maybe [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String, String, String, [String]) -> [String]
go (Regex -> String -> Maybe (String, String, String, [String])
forall regex source target (m :: * -> *).
(RegexContext regex source target, MonadFail m) =>
regex -> source -> m target
matchM Regex
p String
str)
  where
    go :: (String, String, String, [String]) -> [String]
    go :: (String, String, String, [String]) -> [String]
go (String
_, String
_, String
_, [String]
ss) = [String]
ss