regex 0.6.0.1 → 0.7.0.0
raw patch · 37 files changed
+1380/−1307 lines, 37 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Text.RE: Alert :: Severity
- Text.RE: CaptureName :: Text -> CaptureName
- Text.RE: CaptureOrdinal :: Int -> CaptureOrdinal
- Text.RE: Crit :: Severity
- Text.RE: Debug :: Severity
- Text.RE: Delete :: LineEdit s
- Text.RE: Emerg :: Severity
- Text.RE: Err :: Severity
- Text.RE: Function :: Context -> (LineNo -> Match s -> Location -> Capture s -> m (Maybe s)) -> Edit m s
- Text.RE: Info :: Severity
- Text.RE: IsCaptureName :: CaptureName -> CaptureID
- Text.RE: IsCaptureOrdinal :: CaptureOrdinal -> CaptureID
- Text.RE: Line :: LineNo -> Matches ByteString -> Line
- Text.RE: LineEdit :: (LineNo -> Matches s -> m (LineEdit s)) -> Edit m s
- Text.RE: MacroID :: String -> MacroID
- Text.RE: NoEdit :: LineEdit s
- Text.RE: Notice :: Severity
- Text.RE: Options :: !(Macros r) -> !c -> !e -> Options_ r c e
- Text.RE: Pipe :: [(re, Edit m s)] -> Edits m re s
- Text.RE: ReplaceWith :: s -> LineEdit s
- Text.RE: Select :: [(re, Edit m s)] -> Edits m re s
- Text.RE: Template :: s -> Edit m s
- Text.RE: Warning :: Severity
- Text.RE: ZeroBasedLineNo :: Int -> LineNo
- Text.RE: [getCaptureName] :: CaptureName -> Text
- Text.RE: [getCaptureOrdinal] :: CaptureOrdinal -> Int
- Text.RE: [getLineMatches] :: Line -> Matches ByteString
- Text.RE: [getLineNumber] :: Line -> LineNo
- Text.RE: [getMacroID] :: MacroID -> String
- Text.RE: [getZeroBasedLineNo] :: LineNo -> Int
- Text.RE: [optionsComp] :: Options_ r c e -> !c
- Text.RE: [optionsExec] :: Options_ r c e -> !e
- Text.RE: [optionsMacs] :: Options_ r c e -> !(Macros r)
- Text.RE: alex :: IsRegex re s => [(re, Match s -> Maybe t)] -> t -> s -> [t]
- Text.RE: alex' :: Replace s => (re -> s -> Match s) -> [(re, Match s -> Maybe t)] -> t -> s -> [t]
- Text.RE: applyEdit :: (IsRegex re s, Monad m, Functor m) => (s -> s) -> LineNo -> re -> Edit m s -> s -> m (Maybe s)
- Text.RE: applyEdits :: (IsRegex re s, Monad m, Functor m) => LineNo -> Edits m re s -> s -> m s
- Text.RE: applyLineEdit :: Monoid s => (s -> s) -> LineEdit s -> Maybe s
- Text.RE: class IsOption o r c e | e -> r, c -> e, e -> c, r -> c, c -> r, r -> e
- Text.RE: class Replace s => IsRegex re s
- Text.RE: data Edit m s
- Text.RE: data Edits m re s
- Text.RE: data Line
- Text.RE: data LineEdit s
- Text.RE: data Options_ r c e
- Text.RE: data Severity
- Text.RE: emptyMacros :: Macros r
- Text.RE: findCaptureID :: CaptureID -> CaptureNames -> Int
- Text.RE: firstLine :: LineNo
- Text.RE: getLineNo :: LineNo -> Int
- Text.RE: grep :: IsRegex re ByteString => re -> FilePath -> IO ()
- Text.RE: grepLines :: IsRegex re ByteString => re -> FilePath -> IO [Line]
- Text.RE: grepScript :: IsRegex re s => GrepScript re s t -> [s] -> [t]
- Text.RE: lineNo :: Int -> LineNo
- Text.RE: linesMatched :: [Line] -> [Line]
- Text.RE: makeOptions :: IsOption o r c e => o -> Options_ r c e
- Text.RE: matchMany :: IsRegex re s => re -> s -> Matches s
- Text.RE: matchOnce :: IsRegex re s => re -> s -> Match s
- Text.RE: newtype CaptureName
- Text.RE: newtype CaptureOrdinal
- Text.RE: newtype LineNo
- Text.RE: newtype MacroID
- Text.RE: noCaptureNames :: CaptureNames
- Text.RE: parseDate :: Replace a => a -> Maybe Day
- Text.RE: parseDateTime :: Replace a => a -> Maybe UTCTime
- Text.RE: parseDateTime8601 :: Replace a => a -> Maybe UTCTime
- Text.RE: parseDateTimeCLF :: Replace a => a -> Maybe UTCTime
- Text.RE: parseDouble :: Replace a => a -> Maybe Double
- Text.RE: parseHex :: Replace a => a -> Maybe Int
- Text.RE: parseIPv4Address :: Replace a => a -> Maybe IPV4Address
- Text.RE: parseInteger :: Replace a => a -> Maybe Int
- Text.RE: parseSeverity :: Replace a => a -> Maybe Severity
- Text.RE: parseShortMonth :: Replace a => a -> Maybe Int
- Text.RE: parseSimpleString :: Replace a => a -> Maybe Text
- Text.RE: parseSlashesDate :: Replace a => a -> Maybe Day
- Text.RE: parseString :: Replace a => a -> Maybe Text
- Text.RE: parseTimeOfDay :: Replace a => a -> Maybe TimeOfDay
- Text.RE: parseTimeZone :: Replace a => a -> Maybe TimeZone
- Text.RE: regexSource :: IsRegex re s => re -> String
- Text.RE: sed :: IsRegex re ByteString => SedScript re -> FilePath -> FilePath -> IO ()
- Text.RE: sed' :: (IsRegex re ByteString, Monad m, Functor m) => Edits m re ByteString -> ByteString -> m ByteString
- Text.RE: severityKeywords :: Severity -> (Text, [Text])
- Text.RE: shortMonthArray :: Array Int Text
- Text.RE: type CaptureNames = HashMap CaptureName CaptureOrdinal
- Text.RE: type GrepScript re s t = [(re, LineNo -> Matches s -> Maybe t)]
- Text.RE: type IPV4Address = (Word8, Word8, Word8, Word8)
- Text.RE: type Macros r = HashMap MacroID r
- Text.RE: type SedScript re = Edits IO re ByteString
- Text.RE.Capture: (!$$) :: Match a -> CaptureID -> a
- Text.RE.Capture: (!$$?) :: Match a -> CaptureID -> Maybe a
- Text.RE.Capture: (!$) :: Match a -> CaptureID -> Capture a
- Text.RE.Capture: (!$?) :: Match a -> CaptureID -> Maybe (Capture a)
- Text.RE.Capture: Capture :: !a -> !a -> !Int -> !Int -> Capture a
- Text.RE.Capture: Match :: !a -> !CaptureNames -> !(Array CaptureOrdinal (Capture a)) -> Match a
- Text.RE.Capture: Matches :: !a -> ![Match a] -> Matches a
- Text.RE.Capture: [allMatches] :: Matches a -> ![Match a]
- Text.RE.Capture: [captureLength] :: Capture a -> !Int
- Text.RE.Capture: [captureNames] :: Match a -> !CaptureNames
- Text.RE.Capture: [captureOffset] :: Capture a -> !Int
- Text.RE.Capture: [captureSource] :: Capture a -> !a
- Text.RE.Capture: [capturedText] :: Capture a -> !a
- Text.RE.Capture: [matchArray] :: Match a -> !(Array CaptureOrdinal (Capture a))
- Text.RE.Capture: [matchSource] :: Match a -> !a
- Text.RE.Capture: [matchesSource] :: Matches a -> !a
- Text.RE.Capture: anyMatches :: Matches a -> Bool
- Text.RE.Capture: capture :: CaptureID -> Match a -> Capture a
- Text.RE.Capture: captureMaybe :: CaptureID -> Match a -> Maybe (Capture a)
- Text.RE.Capture: capturePrefix :: Extract a => Capture a -> a
- Text.RE.Capture: captureSuffix :: Extract a => Capture a -> a
- Text.RE.Capture: captureText :: CaptureID -> Match a -> a
- Text.RE.Capture: captureTextMaybe :: CaptureID -> Match a -> Maybe a
- Text.RE.Capture: countMatches :: Matches a -> Int
- Text.RE.Capture: data Capture a
- Text.RE.Capture: data Match a
- Text.RE.Capture: data Matches a
- Text.RE.Capture: emptyMatchArray :: Array CaptureOrdinal (Capture a)
- Text.RE.Capture: hasCaptured :: Capture a -> Bool
- Text.RE.Capture: infixl 9 !$
- Text.RE.Capture: instance (Text.Regex.Base.RegexLike.RegexContext regex source (Text.Regex.Base.RegexLike.AllTextSubmatches (GHC.Arr.Array GHC.Types.Int) (source, (GHC.Types.Int, GHC.Types.Int))), Text.Regex.Base.RegexLike.RegexLike regex source) => Text.Regex.Base.RegexLike.RegexContext regex source (Text.RE.Capture.Match source)
- Text.RE.Capture: instance (Text.Regex.Base.RegexLike.RegexContext regex source [Text.Regex.Base.RegexLike.MatchText source], Text.Regex.Base.RegexLike.RegexLike regex source) => Text.Regex.Base.RegexLike.RegexContext regex source (Text.RE.Capture.Matches source)
- Text.RE.Capture: instance GHC.Base.Functor Text.RE.Capture.Capture
- Text.RE.Capture: instance GHC.Base.Functor Text.RE.Capture.Match
- Text.RE.Capture: instance GHC.Base.Functor Text.RE.Capture.Matches
- Text.RE.Capture: instance GHC.Classes.Eq a => GHC.Classes.Eq (Text.RE.Capture.Capture a)
- Text.RE.Capture: instance GHC.Classes.Eq a => GHC.Classes.Eq (Text.RE.Capture.Match a)
- Text.RE.Capture: instance GHC.Classes.Eq a => GHC.Classes.Eq (Text.RE.Capture.Matches a)
- Text.RE.Capture: instance GHC.Show.Show a => GHC.Show.Show (Text.RE.Capture.Capture a)
- Text.RE.Capture: instance GHC.Show.Show a => GHC.Show.Show (Text.RE.Capture.Match a)
- Text.RE.Capture: instance GHC.Show.Show a => GHC.Show.Show (Text.RE.Capture.Matches a)
- Text.RE.Capture: mainCaptures :: Matches a -> [Capture a]
- Text.RE.Capture: matchCapture :: Match a -> Maybe (Capture a)
- Text.RE.Capture: matchCaptures :: Match a -> Maybe (Capture a, [Capture a])
- Text.RE.Capture: matched :: Match a -> Bool
- Text.RE.Capture: matchedText :: Match a -> Maybe a
- Text.RE.Capture: matches :: Matches a -> [a]
- Text.RE.Capture: noMatch :: a -> Match a
- Text.RE.CaptureID: CaptureName :: Text -> CaptureName
- Text.RE.CaptureID: CaptureOrdinal :: Int -> CaptureOrdinal
- Text.RE.CaptureID: IsCaptureName :: CaptureName -> CaptureID
- Text.RE.CaptureID: IsCaptureOrdinal :: CaptureOrdinal -> CaptureID
- Text.RE.CaptureID: [getCaptureName] :: CaptureName -> Text
- Text.RE.CaptureID: [getCaptureOrdinal] :: CaptureOrdinal -> Int
- Text.RE.CaptureID: data CaptureID
- Text.RE.CaptureID: findCaptureID :: CaptureID -> CaptureNames -> Int
- Text.RE.CaptureID: instance Data.Hashable.Class.Hashable Text.RE.CaptureID.CaptureName
- Text.RE.CaptureID: instance GHC.Arr.Ix Text.RE.CaptureID.CaptureOrdinal
- Text.RE.CaptureID: instance GHC.Classes.Eq Text.RE.CaptureID.CaptureID
- Text.RE.CaptureID: instance GHC.Classes.Eq Text.RE.CaptureID.CaptureName
- Text.RE.CaptureID: instance GHC.Classes.Eq Text.RE.CaptureID.CaptureOrdinal
- Text.RE.CaptureID: instance GHC.Classes.Ord Text.RE.CaptureID.CaptureID
- Text.RE.CaptureID: instance GHC.Classes.Ord Text.RE.CaptureID.CaptureName
- Text.RE.CaptureID: instance GHC.Classes.Ord Text.RE.CaptureID.CaptureOrdinal
- Text.RE.CaptureID: instance GHC.Enum.Enum Text.RE.CaptureID.CaptureOrdinal
- Text.RE.CaptureID: instance GHC.Num.Num Text.RE.CaptureID.CaptureOrdinal
- Text.RE.CaptureID: instance GHC.Show.Show Text.RE.CaptureID.CaptureID
- Text.RE.CaptureID: instance GHC.Show.Show Text.RE.CaptureID.CaptureName
- Text.RE.CaptureID: instance GHC.Show.Show Text.RE.CaptureID.CaptureOrdinal
- Text.RE.CaptureID: newtype CaptureName
- Text.RE.CaptureID: newtype CaptureOrdinal
- Text.RE.CaptureID: noCaptureNames :: CaptureNames
- Text.RE.CaptureID: type CaptureNames = HashMap CaptureName CaptureOrdinal
- Text.RE.Edit: Delete :: LineEdit s
- Text.RE.Edit: Function :: Context -> (LineNo -> Match s -> Location -> Capture s -> m (Maybe s)) -> Edit m s
- Text.RE.Edit: LineEdit :: (LineNo -> Matches s -> m (LineEdit s)) -> Edit m s
- Text.RE.Edit: NoEdit :: LineEdit s
- Text.RE.Edit: Pipe :: [(re, Edit m s)] -> Edits m re s
- Text.RE.Edit: ReplaceWith :: s -> LineEdit s
- Text.RE.Edit: Select :: [(re, Edit m s)] -> Edits m re s
- Text.RE.Edit: Template :: s -> Edit m s
- Text.RE.Edit: applyEdit :: (IsRegex re s, Monad m, Functor m) => (s -> s) -> LineNo -> re -> Edit m s -> s -> m (Maybe s)
- Text.RE.Edit: applyEdits :: (IsRegex re s, Monad m, Functor m) => LineNo -> Edits m re s -> s -> m s
- Text.RE.Edit: applyLineEdit :: Monoid s => (s -> s) -> LineEdit s -> Maybe s
- Text.RE.Edit: data Edit m s
- Text.RE.Edit: data Edits m re s
- Text.RE.Edit: data LineEdit s
- Text.RE.Edit: data LineNo
- Text.RE.Edit: instance GHC.Show.Show s => GHC.Show.Show (Text.RE.Edit.LineEdit s)
- Text.RE.Internal.PreludeMacros: PCRE :: TestBenchMatcher -> RegexType
- Text.RE.Internal.PreludeMacros: TDFA :: TestBenchMatcher -> RegexType
- Text.RE.IsRegex: class Replace s => IsRegex re s
- Text.RE.IsRegex: matchMany :: IsRegex re s => re -> s -> Matches s
- Text.RE.IsRegex: matchOnce :: IsRegex re s => re -> s -> Match s
- Text.RE.IsRegex: regexSource :: IsRegex re s => re -> String
- Text.RE.LineNo: ZeroBasedLineNo :: Int -> LineNo
- Text.RE.LineNo: [getZeroBasedLineNo] :: LineNo -> Int
- Text.RE.LineNo: firstLine :: LineNo
- Text.RE.LineNo: getLineNo :: LineNo -> Int
- Text.RE.LineNo: instance GHC.Enum.Enum Text.RE.LineNo.LineNo
- Text.RE.LineNo: instance GHC.Show.Show Text.RE.LineNo.LineNo
- Text.RE.LineNo: lineNo :: Int -> LineNo
- Text.RE.LineNo: newtype LineNo
- Text.RE.Options: BlockInsensitive :: SimpleRegexOptions
- Text.RE.Options: BlockSensitive :: SimpleRegexOptions
- Text.RE.Options: MacroID :: String -> MacroID
- Text.RE.Options: MultilineInsensitive :: SimpleRegexOptions
- Text.RE.Options: MultilineSensitive :: SimpleRegexOptions
- Text.RE.Options: Options :: !(Macros r) -> !c -> !e -> Options_ r c e
- Text.RE.Options: [getMacroID] :: MacroID -> String
- Text.RE.Options: [optionsComp] :: Options_ r c e -> !c
- Text.RE.Options: [optionsExec] :: Options_ r c e -> !e
- Text.RE.Options: [optionsMacs] :: Options_ r c e -> !(Macros r)
- Text.RE.Options: class IsOption o r c e | e -> r, c -> e, e -> c, r -> c, c -> r, r -> e
- Text.RE.Options: data Options_ r c e
- Text.RE.Options: data SimpleRegexOptions
- Text.RE.Options: emptyMacros :: Macros r
- Text.RE.Options: instance (GHC.Show.Show e, GHC.Show.Show c, GHC.Show.Show r) => GHC.Show.Show (Text.RE.Options.Options_ r c e)
- Text.RE.Options: instance Data.Hashable.Class.Hashable Text.RE.Options.MacroID
- Text.RE.Options: instance Data.String.IsString Text.RE.Options.MacroID
- Text.RE.Options: instance GHC.Classes.Eq Text.RE.Options.MacroID
- Text.RE.Options: instance GHC.Classes.Eq Text.RE.Options.SimpleRegexOptions
- Text.RE.Options: instance GHC.Classes.Ord Text.RE.Options.MacroID
- Text.RE.Options: instance GHC.Classes.Ord Text.RE.Options.SimpleRegexOptions
- Text.RE.Options: instance GHC.Enum.Bounded Text.RE.Options.SimpleRegexOptions
- Text.RE.Options: instance GHC.Enum.Enum Text.RE.Options.SimpleRegexOptions
- Text.RE.Options: instance GHC.Show.Show Text.RE.Options.MacroID
- Text.RE.Options: instance GHC.Show.Show Text.RE.Options.SimpleRegexOptions
- Text.RE.Options: instance Language.Haskell.TH.Syntax.Lift Text.RE.Options.SimpleRegexOptions
- Text.RE.Options: makeOptions :: IsOption o r c e => o -> Options_ r c e
- Text.RE.Options: newtype MacroID
- Text.RE.Options: type Macros r = HashMap MacroID r
- Text.RE.Parsers: Alert :: Severity
- Text.RE.Parsers: Crit :: Severity
- Text.RE.Parsers: Debug :: Severity
- Text.RE.Parsers: Emerg :: Severity
- Text.RE.Parsers: Err :: Severity
- Text.RE.Parsers: Info :: Severity
- Text.RE.Parsers: Notice :: Severity
- Text.RE.Parsers: Warning :: Severity
- Text.RE.Parsers: data Severity
- Text.RE.Parsers: instance GHC.Classes.Eq Text.RE.Parsers.Severity
- Text.RE.Parsers: instance GHC.Classes.Ord Text.RE.Parsers.Severity
- Text.RE.Parsers: instance GHC.Enum.Bounded Text.RE.Parsers.Severity
- Text.RE.Parsers: instance GHC.Enum.Enum Text.RE.Parsers.Severity
- Text.RE.Parsers: instance GHC.Show.Show Text.RE.Parsers.Severity
- Text.RE.Parsers: parseDate :: Replace a => a -> Maybe Day
- Text.RE.Parsers: parseDateTime :: Replace a => a -> Maybe UTCTime
- Text.RE.Parsers: parseDateTime8601 :: Replace a => a -> Maybe UTCTime
- Text.RE.Parsers: parseDateTimeCLF :: Replace a => a -> Maybe UTCTime
- Text.RE.Parsers: parseDouble :: Replace a => a -> Maybe Double
- Text.RE.Parsers: parseHex :: Replace a => a -> Maybe Int
- Text.RE.Parsers: parseIPv4Address :: Replace a => a -> Maybe IPV4Address
- Text.RE.Parsers: parseInteger :: Replace a => a -> Maybe Int
- Text.RE.Parsers: parseSeverity :: Replace a => a -> Maybe Severity
- Text.RE.Parsers: parseShortMonth :: Replace a => a -> Maybe Int
- Text.RE.Parsers: parseSimpleString :: Replace a => a -> Maybe Text
- Text.RE.Parsers: parseSlashesDate :: Replace a => a -> Maybe Day
- Text.RE.Parsers: parseString :: Replace a => a -> Maybe Text
- Text.RE.Parsers: parseTimeOfDay :: Replace a => a -> Maybe TimeOfDay
- Text.RE.Parsers: parseTimeZone :: Replace a => a -> Maybe TimeZone
- Text.RE.Parsers: severityKeywords :: Severity -> (Text, [Text])
- Text.RE.Parsers: shortMonthArray :: Array Int Text
- Text.RE.Parsers: type IPV4Address = (Word8, Word8, Word8, Word8)
- Text.RE.Replace: ALL :: Context
- Text.RE.Replace: Location :: Int -> CaptureOrdinal -> Location
- Text.RE.Replace: ReplaceMethods :: (a -> Int) -> ((a -> a) -> Capture a -> a) -> ReplaceMethods a
- Text.RE.Replace: SUB :: Context
- Text.RE.Replace: TOP :: Context
- Text.RE.Replace: [locationCapture] :: Location -> CaptureOrdinal
- Text.RE.Replace: [locationMatch] :: Location -> Int
- Text.RE.Replace: [methodLength] :: ReplaceMethods a -> a -> Int
- Text.RE.Replace: [methodSubst] :: ReplaceMethods a -> (a -> a) -> Capture a -> a
- Text.RE.Replace: appendNewlineE :: Replace a => a -> a
- Text.RE.Replace: class (Extract a, Monoid a) => Replace a where textifyE = pack . unpackE detextifyE = packE . unpack appendNewlineE = (<> packE "\n") substE f m@(Capture {..}) = capturePrefix m <> f capturedText <> captureSuffix m
- Text.RE.Replace: data Context
- Text.RE.Replace: data Location
- Text.RE.Replace: data ReplaceMethods a
- Text.RE.Replace: detextifyE :: Replace a => Text -> a
- Text.RE.Replace: expandMacros :: (r -> String) -> Macros r -> String -> String
- Text.RE.Replace: expandMacros' :: (MacroID -> Maybe String) -> String -> String
- Text.RE.Replace: instance GHC.Show.Show Text.RE.Replace.Context
- Text.RE.Replace: instance GHC.Show.Show Text.RE.Replace.Location
- Text.RE.Replace: instance Text.RE.Replace.Replace (Data.Sequence.Seq GHC.Types.Char)
- Text.RE.Replace: instance Text.RE.Replace.Replace Data.ByteString.Internal.ByteString
- Text.RE.Replace: instance Text.RE.Replace.Replace Data.ByteString.Lazy.Internal.ByteString
- Text.RE.Replace: instance Text.RE.Replace.Replace Data.Text.Internal.Lazy.Text
- Text.RE.Replace: instance Text.RE.Replace.Replace Data.Text.Internal.Text
- Text.RE.Replace: instance Text.RE.Replace.Replace [GHC.Types.Char]
- Text.RE.Replace: isTopLocation :: Location -> Bool
- Text.RE.Replace: lengthE :: Replace a => a -> Int
- Text.RE.Replace: packE :: Replace a => String -> a
- Text.RE.Replace: parseTemplateE :: Replace a => a -> Match a -> Location -> Capture a -> Maybe a
- Text.RE.Replace: replace :: Replace a => Match a -> a -> a
- Text.RE.Replace: replaceAll :: Replace a => a -> Matches a -> a
- Text.RE.Replace: replaceAllCaptures :: Replace a => Context -> (Match a -> Location -> Capture a -> Maybe a) -> Matches a -> a
- Text.RE.Replace: replaceAllCapturesM :: (Extract a, Monad m) => ReplaceMethods a -> Context -> (Match a -> Location -> Capture a -> m (Maybe a)) -> Matches a -> m a
- Text.RE.Replace: replaceAllCaptures_ :: Extract a => ReplaceMethods a -> Context -> (Match a -> Location -> Capture a -> Maybe a) -> Matches a -> a
- Text.RE.Replace: replaceCaptures :: Replace a => Context -> (Match a -> Location -> Capture a -> Maybe a) -> Match a -> a
- Text.RE.Replace: replaceCapturesM :: (Monad m, Extract a) => ReplaceMethods a -> Context -> (Match a -> Location -> Capture a -> m (Maybe a)) -> Match a -> m a
- Text.RE.Replace: replaceCaptures_ :: Extract a => ReplaceMethods a -> Context -> (Match a -> Location -> Capture a -> Maybe a) -> Match a -> a
- Text.RE.Replace: replaceMethods :: Replace a => ReplaceMethods a
- Text.RE.Replace: substE :: Replace a => (a -> a) -> Capture a -> a
- Text.RE.Replace: textifyE :: Replace a => a -> Text
- Text.RE.Replace: unpackE :: Replace a => a -> String
- Text.RE.TDFA.ByteString: instance Text.RE.IsRegex.IsRegex Text.RE.TDFA.RE.RE Data.ByteString.Internal.ByteString
- Text.RE.TDFA.ByteString.Lazy: instance Text.RE.IsRegex.IsRegex Text.RE.TDFA.RE.RE Data.ByteString.Lazy.Internal.ByteString
- Text.RE.TDFA.RE: instance Text.RE.Options.IsOption () Text.RE.TDFA.RE.RE Text.Regex.TDFA.Common.CompOption Text.Regex.TDFA.Common.ExecOption
- Text.RE.TDFA.RE: instance Text.RE.Options.IsOption (Text.RE.Options.Macros Text.RE.TDFA.RE.RE) Text.RE.TDFA.RE.RE Text.Regex.TDFA.Common.CompOption Text.Regex.TDFA.Common.ExecOption
- Text.RE.TDFA.RE: instance Text.RE.Options.IsOption Text.RE.Options.SimpleRegexOptions Text.RE.TDFA.RE.RE Text.Regex.TDFA.Common.CompOption Text.Regex.TDFA.Common.ExecOption
- Text.RE.TDFA.RE: instance Text.RE.Options.IsOption Text.RE.TDFA.RE.Options Text.RE.TDFA.RE.RE Text.Regex.TDFA.Common.CompOption Text.Regex.TDFA.Common.ExecOption
- Text.RE.TDFA.RE: instance Text.RE.Options.IsOption Text.Regex.TDFA.Common.CompOption Text.RE.TDFA.RE.RE Text.Regex.TDFA.Common.CompOption Text.Regex.TDFA.Common.ExecOption
- Text.RE.TDFA.RE: instance Text.RE.Options.IsOption Text.Regex.TDFA.Common.ExecOption Text.RE.TDFA.RE.RE Text.Regex.TDFA.Common.CompOption Text.Regex.TDFA.Common.ExecOption
- Text.RE.TDFA.Sequence: instance Text.RE.IsRegex.IsRegex Text.RE.TDFA.RE.RE (Data.Sequence.Seq GHC.Types.Char)
- Text.RE.TDFA.String: instance Text.RE.IsRegex.IsRegex Text.RE.TDFA.RE.RE GHC.Base.String
- Text.RE.TDFA.Text: instance Text.RE.IsRegex.IsRegex Text.RE.TDFA.RE.RE Data.Text.Internal.Text
- Text.RE.TDFA.Text.Lazy: instance Text.RE.IsRegex.IsRegex Text.RE.TDFA.RE.RE Data.Text.Internal.Lazy.Text
- Text.RE.TestBench: PCRE :: TestBenchMatcher -> RegexType
- Text.RE.TestBench: TDFA :: TestBenchMatcher -> RegexType
+ Text.RE: linesE :: Replace a => a -> [a]
+ Text.RE: unlinesE :: Replace a => [a] -> a
+ Text.RE.TDFA.ByteString: instance Text.RE.Types.IsRegex.IsRegex Text.RE.TDFA.RE.RE Data.ByteString.Internal.ByteString
+ Text.RE.TDFA.ByteString.Lazy: instance Text.RE.Types.IsRegex.IsRegex Text.RE.TDFA.RE.RE Data.ByteString.Lazy.Internal.ByteString
+ Text.RE.TDFA.RE: compileRegexWith :: (Functor m, Monad m) => SimpleRegexOptions -> String -> m RE
+ Text.RE.TDFA.RE: compileRegexWithOptions :: (IsOption o RE CompOption ExecOption, Functor m, Monad m) => o -> String -> m RE
+ Text.RE.TDFA.RE: instance Text.RE.Types.Options.IsOption () Text.RE.TDFA.RE.RE Text.Regex.TDFA.Common.CompOption Text.Regex.TDFA.Common.ExecOption
+ Text.RE.TDFA.RE: instance Text.RE.Types.Options.IsOption (Text.RE.Types.Options.Macros Text.RE.TDFA.RE.RE) Text.RE.TDFA.RE.RE Text.Regex.TDFA.Common.CompOption Text.Regex.TDFA.Common.ExecOption
+ Text.RE.TDFA.RE: instance Text.RE.Types.Options.IsOption Text.RE.TDFA.RE.Options Text.RE.TDFA.RE.RE Text.Regex.TDFA.Common.CompOption Text.Regex.TDFA.Common.ExecOption
+ Text.RE.TDFA.RE: instance Text.RE.Types.Options.IsOption Text.RE.Types.Options.SimpleRegexOptions Text.RE.TDFA.RE.RE Text.Regex.TDFA.Common.CompOption Text.Regex.TDFA.Common.ExecOption
+ Text.RE.TDFA.RE: instance Text.RE.Types.Options.IsOption Text.Regex.TDFA.Common.CompOption Text.RE.TDFA.RE.RE Text.Regex.TDFA.Common.CompOption Text.Regex.TDFA.Common.ExecOption
+ Text.RE.TDFA.RE: instance Text.RE.Types.Options.IsOption Text.Regex.TDFA.Common.ExecOption Text.RE.TDFA.RE.RE Text.Regex.TDFA.Common.CompOption Text.Regex.TDFA.Common.ExecOption
+ Text.RE.TDFA.Sequence: instance Text.RE.Types.IsRegex.IsRegex Text.RE.TDFA.RE.RE (Data.Sequence.Seq GHC.Types.Char)
+ Text.RE.TDFA.String: instance Text.RE.Types.IsRegex.IsRegex Text.RE.TDFA.RE.RE GHC.Base.String
+ Text.RE.TDFA.Text: instance Text.RE.Types.IsRegex.IsRegex Text.RE.TDFA.RE.RE Data.Text.Internal.Text
+ Text.RE.TDFA.Text.Lazy: instance Text.RE.Types.IsRegex.IsRegex Text.RE.TDFA.RE.RE Data.Text.Internal.Lazy.Text
+ Text.RE.TestBench: mkPCRE :: TestBenchMatcher -> RegexType
+ Text.RE.TestBench: mkTDFA :: TestBenchMatcher -> RegexType
+ Text.RE.TestBench.Parsers: Alert :: Severity
+ Text.RE.TestBench.Parsers: Crit :: Severity
+ Text.RE.TestBench.Parsers: Debug :: Severity
+ Text.RE.TestBench.Parsers: Emerg :: Severity
+ Text.RE.TestBench.Parsers: Err :: Severity
+ Text.RE.TestBench.Parsers: Info :: Severity
+ Text.RE.TestBench.Parsers: Notice :: Severity
+ Text.RE.TestBench.Parsers: Warning :: Severity
+ Text.RE.TestBench.Parsers: data Severity
+ Text.RE.TestBench.Parsers: instance GHC.Classes.Eq Text.RE.TestBench.Parsers.Severity
+ Text.RE.TestBench.Parsers: instance GHC.Classes.Ord Text.RE.TestBench.Parsers.Severity
+ Text.RE.TestBench.Parsers: instance GHC.Enum.Bounded Text.RE.TestBench.Parsers.Severity
+ Text.RE.TestBench.Parsers: instance GHC.Enum.Enum Text.RE.TestBench.Parsers.Severity
+ Text.RE.TestBench.Parsers: instance GHC.Show.Show Text.RE.TestBench.Parsers.Severity
+ Text.RE.TestBench.Parsers: parseDate :: Replace a => a -> Maybe Day
+ Text.RE.TestBench.Parsers: parseDateTime :: Replace a => a -> Maybe UTCTime
+ Text.RE.TestBench.Parsers: parseDateTime8601 :: Replace a => a -> Maybe UTCTime
+ Text.RE.TestBench.Parsers: parseDateTimeCLF :: Replace a => a -> Maybe UTCTime
+ Text.RE.TestBench.Parsers: parseDouble :: Replace a => a -> Maybe Double
+ Text.RE.TestBench.Parsers: parseHex :: Replace a => a -> Maybe Int
+ Text.RE.TestBench.Parsers: parseIPv4Address :: Replace a => a -> Maybe IPV4Address
+ Text.RE.TestBench.Parsers: parseInteger :: Replace a => a -> Maybe Int
+ Text.RE.TestBench.Parsers: parseSeverity :: Replace a => a -> Maybe Severity
+ Text.RE.TestBench.Parsers: parseShortMonth :: Replace a => a -> Maybe Int
+ Text.RE.TestBench.Parsers: parseSimpleString :: Replace a => a -> Maybe Text
+ Text.RE.TestBench.Parsers: parseSlashesDate :: Replace a => a -> Maybe Day
+ Text.RE.TestBench.Parsers: parseString :: Replace a => a -> Maybe Text
+ Text.RE.TestBench.Parsers: parseTimeOfDay :: Replace a => a -> Maybe TimeOfDay
+ Text.RE.TestBench.Parsers: parseTimeZone :: Replace a => a -> Maybe TimeZone
+ Text.RE.TestBench.Parsers: severityKeywords :: Severity -> (Text, [Text])
+ Text.RE.TestBench.Parsers: shortMonthArray :: Array Int Text
+ Text.RE.TestBench.Parsers: type IPV4Address = (Word8, Word8, Word8, Word8)
+ Text.RE.Tools.Edit: Delete :: LineEdit s
+ Text.RE.Tools.Edit: Function :: Context -> (LineNo -> Match s -> Location -> Capture s -> m (Maybe s)) -> Edit m s
+ Text.RE.Tools.Edit: LineEdit :: (LineNo -> Matches s -> m (LineEdit s)) -> Edit m s
+ Text.RE.Tools.Edit: NoEdit :: LineEdit s
+ Text.RE.Tools.Edit: Pipe :: [(re, Edit m s)] -> Edits m re s
+ Text.RE.Tools.Edit: ReplaceWith :: s -> LineEdit s
+ Text.RE.Tools.Edit: Select :: [(re, Edit m s)] -> Edits m re s
+ Text.RE.Tools.Edit: Template :: s -> Edit m s
+ Text.RE.Tools.Edit: applyEdit :: (IsRegex re s, Monad m, Functor m) => (s -> s) -> LineNo -> re -> Edit m s -> s -> m (Maybe s)
+ Text.RE.Tools.Edit: applyEdits :: (IsRegex re s, Monad m, Functor m) => LineNo -> Edits m re s -> s -> m s
+ Text.RE.Tools.Edit: applyLineEdit :: Monoid s => (s -> s) -> LineEdit s -> Maybe s
+ Text.RE.Tools.Edit: data Edit m s
+ Text.RE.Tools.Edit: data Edits m re s
+ Text.RE.Tools.Edit: data LineEdit s
+ Text.RE.Tools.Edit: data LineNo
+ Text.RE.Tools.Edit: instance GHC.Show.Show s => GHC.Show.Show (Text.RE.Tools.Edit.LineEdit s)
+ Text.RE.Types.Capture: Capture :: !a -> !a -> !Int -> !Int -> Capture a
+ Text.RE.Types.Capture: [captureLength] :: Capture a -> !Int
+ Text.RE.Types.Capture: [captureOffset] :: Capture a -> !Int
+ Text.RE.Types.Capture: [captureSource] :: Capture a -> !a
+ Text.RE.Types.Capture: [capturedText] :: Capture a -> !a
+ Text.RE.Types.Capture: capturePrefix :: Extract a => Capture a -> a
+ Text.RE.Types.Capture: captureSuffix :: Extract a => Capture a -> a
+ Text.RE.Types.Capture: data Capture a
+ Text.RE.Types.Capture: hasCaptured :: Capture a -> Bool
+ Text.RE.Types.Capture: instance GHC.Base.Functor Text.RE.Types.Capture.Capture
+ Text.RE.Types.Capture: instance GHC.Classes.Eq a => GHC.Classes.Eq (Text.RE.Types.Capture.Capture a)
+ Text.RE.Types.Capture: instance GHC.Show.Show a => GHC.Show.Show (Text.RE.Types.Capture.Capture a)
+ Text.RE.Types.CaptureID: CaptureName :: Text -> CaptureName
+ Text.RE.Types.CaptureID: CaptureOrdinal :: Int -> CaptureOrdinal
+ Text.RE.Types.CaptureID: IsCaptureName :: CaptureName -> CaptureID
+ Text.RE.Types.CaptureID: IsCaptureOrdinal :: CaptureOrdinal -> CaptureID
+ Text.RE.Types.CaptureID: [getCaptureName] :: CaptureName -> Text
+ Text.RE.Types.CaptureID: [getCaptureOrdinal] :: CaptureOrdinal -> Int
+ Text.RE.Types.CaptureID: data CaptureID
+ Text.RE.Types.CaptureID: findCaptureID :: CaptureID -> CaptureNames -> Int
+ Text.RE.Types.CaptureID: instance Data.Hashable.Class.Hashable Text.RE.Types.CaptureID.CaptureName
+ Text.RE.Types.CaptureID: instance GHC.Arr.Ix Text.RE.Types.CaptureID.CaptureOrdinal
+ Text.RE.Types.CaptureID: instance GHC.Classes.Eq Text.RE.Types.CaptureID.CaptureID
+ Text.RE.Types.CaptureID: instance GHC.Classes.Eq Text.RE.Types.CaptureID.CaptureName
+ Text.RE.Types.CaptureID: instance GHC.Classes.Eq Text.RE.Types.CaptureID.CaptureOrdinal
+ Text.RE.Types.CaptureID: instance GHC.Classes.Ord Text.RE.Types.CaptureID.CaptureID
+ Text.RE.Types.CaptureID: instance GHC.Classes.Ord Text.RE.Types.CaptureID.CaptureName
+ Text.RE.Types.CaptureID: instance GHC.Classes.Ord Text.RE.Types.CaptureID.CaptureOrdinal
+ Text.RE.Types.CaptureID: instance GHC.Enum.Enum Text.RE.Types.CaptureID.CaptureOrdinal
+ Text.RE.Types.CaptureID: instance GHC.Num.Num Text.RE.Types.CaptureID.CaptureOrdinal
+ Text.RE.Types.CaptureID: instance GHC.Show.Show Text.RE.Types.CaptureID.CaptureID
+ Text.RE.Types.CaptureID: instance GHC.Show.Show Text.RE.Types.CaptureID.CaptureName
+ Text.RE.Types.CaptureID: instance GHC.Show.Show Text.RE.Types.CaptureID.CaptureOrdinal
+ Text.RE.Types.CaptureID: newtype CaptureName
+ Text.RE.Types.CaptureID: newtype CaptureOrdinal
+ Text.RE.Types.CaptureID: noCaptureNames :: CaptureNames
+ Text.RE.Types.CaptureID: type CaptureNames = HashMap CaptureName CaptureOrdinal
+ Text.RE.Types.IsRegex: class Replace s => IsRegex re s
+ Text.RE.Types.IsRegex: makeRegex :: (IsRegex re s, Functor m, Monad m) => s -> m re
+ Text.RE.Types.IsRegex: makeRegexWith :: (IsRegex re s, Functor m, Monad m) => SimpleRegexOptions -> s -> m re
+ Text.RE.Types.IsRegex: matchMany :: IsRegex re s => re -> s -> Matches s
+ Text.RE.Types.IsRegex: matchOnce :: IsRegex re s => re -> s -> Match s
+ Text.RE.Types.IsRegex: regexSource :: IsRegex re s => re -> s
+ Text.RE.Types.LineNo: ZeroBasedLineNo :: Int -> LineNo
+ Text.RE.Types.LineNo: [getZeroBasedLineNo] :: LineNo -> Int
+ Text.RE.Types.LineNo: firstLine :: LineNo
+ Text.RE.Types.LineNo: getLineNo :: LineNo -> Int
+ Text.RE.Types.LineNo: instance GHC.Enum.Enum Text.RE.Types.LineNo.LineNo
+ Text.RE.Types.LineNo: instance GHC.Show.Show Text.RE.Types.LineNo.LineNo
+ Text.RE.Types.LineNo: lineNo :: Int -> LineNo
+ Text.RE.Types.LineNo: newtype LineNo
+ Text.RE.Types.Match: (!$$) :: Match a -> CaptureID -> a
+ Text.RE.Types.Match: (!$$?) :: Match a -> CaptureID -> Maybe a
+ Text.RE.Types.Match: (!$) :: Match a -> CaptureID -> Capture a
+ Text.RE.Types.Match: (!$?) :: Match a -> CaptureID -> Maybe (Capture a)
+ Text.RE.Types.Match: Match :: !a -> !CaptureNames -> !(Array CaptureOrdinal (Capture a)) -> Match a
+ Text.RE.Types.Match: [captureNames] :: Match a -> !CaptureNames
+ Text.RE.Types.Match: [matchArray] :: Match a -> !(Array CaptureOrdinal (Capture a))
+ Text.RE.Types.Match: [matchSource] :: Match a -> !a
+ Text.RE.Types.Match: capture :: CaptureID -> Match a -> Capture a
+ Text.RE.Types.Match: captureMaybe :: CaptureID -> Match a -> Maybe (Capture a)
+ Text.RE.Types.Match: captureText :: CaptureID -> Match a -> a
+ Text.RE.Types.Match: captureTextMaybe :: CaptureID -> Match a -> Maybe a
+ Text.RE.Types.Match: convertMatchText :: source -> MatchText source -> Match source
+ Text.RE.Types.Match: data Match a
+ Text.RE.Types.Match: emptyMatchArray :: Array CaptureOrdinal (Capture a)
+ Text.RE.Types.Match: infixl 9 !$
+ Text.RE.Types.Match: instance (Text.Regex.Base.RegexLike.RegexContext regex source (Text.Regex.Base.RegexLike.AllTextSubmatches (GHC.Arr.Array GHC.Types.Int) (source, (GHC.Types.Int, GHC.Types.Int))), Text.Regex.Base.RegexLike.RegexLike regex source) => Text.Regex.Base.RegexLike.RegexContext regex source (Text.RE.Types.Match.Match source)
+ Text.RE.Types.Match: instance GHC.Base.Functor Text.RE.Types.Match.Match
+ Text.RE.Types.Match: instance GHC.Classes.Eq a => GHC.Classes.Eq (Text.RE.Types.Match.Match a)
+ Text.RE.Types.Match: instance GHC.Show.Show a => GHC.Show.Show (Text.RE.Types.Match.Match a)
+ Text.RE.Types.Match: matchCapture :: Match a -> Maybe (Capture a)
+ Text.RE.Types.Match: matchCaptures :: Match a -> Maybe (Capture a, [Capture a])
+ Text.RE.Types.Match: matched :: Match a -> Bool
+ Text.RE.Types.Match: matchedText :: Match a -> Maybe a
+ Text.RE.Types.Match: noMatch :: a -> Match a
+ Text.RE.Types.Matches: Matches :: !a -> ![Match a] -> Matches a
+ Text.RE.Types.Matches: [allMatches] :: Matches a -> ![Match a]
+ Text.RE.Types.Matches: [matchesSource] :: Matches a -> !a
+ Text.RE.Types.Matches: anyMatches :: Matches a -> Bool
+ Text.RE.Types.Matches: countMatches :: Matches a -> Int
+ Text.RE.Types.Matches: data Matches a
+ Text.RE.Types.Matches: instance (Text.Regex.Base.RegexLike.RegexContext regex source [Text.Regex.Base.RegexLike.MatchText source], Text.Regex.Base.RegexLike.RegexLike regex source) => Text.Regex.Base.RegexLike.RegexContext regex source (Text.RE.Types.Matches.Matches source)
+ Text.RE.Types.Matches: instance GHC.Base.Functor Text.RE.Types.Matches.Matches
+ Text.RE.Types.Matches: instance GHC.Classes.Eq a => GHC.Classes.Eq (Text.RE.Types.Matches.Matches a)
+ Text.RE.Types.Matches: instance GHC.Show.Show a => GHC.Show.Show (Text.RE.Types.Matches.Matches a)
+ Text.RE.Types.Matches: mainCaptures :: Matches a -> [Capture a]
+ Text.RE.Types.Matches: matches :: Matches a -> [a]
+ Text.RE.Types.Options: BlockInsensitive :: SimpleRegexOptions
+ Text.RE.Types.Options: BlockSensitive :: SimpleRegexOptions
+ Text.RE.Types.Options: MacroID :: String -> MacroID
+ Text.RE.Types.Options: MultilineInsensitive :: SimpleRegexOptions
+ Text.RE.Types.Options: MultilineSensitive :: SimpleRegexOptions
+ Text.RE.Types.Options: Options :: !(Macros r) -> !c -> !e -> Options_ r c e
+ Text.RE.Types.Options: [getMacroID] :: MacroID -> String
+ Text.RE.Types.Options: [optionsComp] :: Options_ r c e -> !c
+ Text.RE.Types.Options: [optionsExec] :: Options_ r c e -> !e
+ Text.RE.Types.Options: [optionsMacs] :: Options_ r c e -> !(Macros r)
+ Text.RE.Types.Options: class IsOption o r c e | e -> r, c -> e, e -> c, r -> c, c -> r, r -> e
+ Text.RE.Types.Options: data Options_ r c e
+ Text.RE.Types.Options: data SimpleRegexOptions
+ Text.RE.Types.Options: emptyMacros :: Macros r
+ Text.RE.Types.Options: instance (GHC.Show.Show e, GHC.Show.Show c, GHC.Show.Show r) => GHC.Show.Show (Text.RE.Types.Options.Options_ r c e)
+ Text.RE.Types.Options: instance Data.Hashable.Class.Hashable Text.RE.Types.Options.MacroID
+ Text.RE.Types.Options: instance Data.String.IsString Text.RE.Types.Options.MacroID
+ Text.RE.Types.Options: instance GHC.Classes.Eq Text.RE.Types.Options.MacroID
+ Text.RE.Types.Options: instance GHC.Classes.Eq Text.RE.Types.Options.SimpleRegexOptions
+ Text.RE.Types.Options: instance GHC.Classes.Ord Text.RE.Types.Options.MacroID
+ Text.RE.Types.Options: instance GHC.Classes.Ord Text.RE.Types.Options.SimpleRegexOptions
+ Text.RE.Types.Options: instance GHC.Enum.Bounded Text.RE.Types.Options.SimpleRegexOptions
+ Text.RE.Types.Options: instance GHC.Enum.Enum Text.RE.Types.Options.SimpleRegexOptions
+ Text.RE.Types.Options: instance GHC.Show.Show Text.RE.Types.Options.MacroID
+ Text.RE.Types.Options: instance GHC.Show.Show Text.RE.Types.Options.SimpleRegexOptions
+ Text.RE.Types.Options: instance Language.Haskell.TH.Syntax.Lift Text.RE.Types.Options.SimpleRegexOptions
+ Text.RE.Types.Options: makeOptions :: IsOption o r c e => o -> Options_ r c e
+ Text.RE.Types.Options: newtype MacroID
+ Text.RE.Types.Options: type Macros r = HashMap MacroID r
+ Text.RE.Types.Replace: ALL :: Context
+ Text.RE.Types.Replace: Location :: Int -> CaptureOrdinal -> Location
+ Text.RE.Types.Replace: ReplaceMethods :: (a -> Int) -> ((a -> a) -> Capture a -> a) -> ReplaceMethods a
+ Text.RE.Types.Replace: SUB :: Context
+ Text.RE.Types.Replace: TOP :: Context
+ Text.RE.Types.Replace: [locationCapture] :: Location -> CaptureOrdinal
+ Text.RE.Types.Replace: [locationMatch] :: Location -> Int
+ Text.RE.Types.Replace: [methodLength] :: ReplaceMethods a -> a -> Int
+ Text.RE.Types.Replace: [methodSubst] :: ReplaceMethods a -> (a -> a) -> Capture a -> a
+ Text.RE.Types.Replace: appendNewlineE :: Replace a => a -> a
+ Text.RE.Types.Replace: class (Show a, Eq a, Ord a, Extract a, Monoid a) => Replace a where textifyE = pack . unpackE detextifyE = packE . unpack appendNewlineE = (<> packE "\n") substE f m@(Capture {..}) = capturePrefix m <> f capturedText <> captureSuffix m
+ Text.RE.Types.Replace: data Context
+ Text.RE.Types.Replace: data Location
+ Text.RE.Types.Replace: data ReplaceMethods a
+ Text.RE.Types.Replace: detextifyE :: Replace a => Text -> a
+ Text.RE.Types.Replace: expandMacros :: (r -> String) -> Macros r -> String -> String
+ Text.RE.Types.Replace: expandMacros' :: (MacroID -> Maybe String) -> String -> String
+ Text.RE.Types.Replace: instance GHC.Show.Show Text.RE.Types.Replace.Context
+ Text.RE.Types.Replace: instance GHC.Show.Show Text.RE.Types.Replace.Location
+ Text.RE.Types.Replace: instance Text.RE.Types.Replace.Replace (Data.Sequence.Seq GHC.Types.Char)
+ Text.RE.Types.Replace: instance Text.RE.Types.Replace.Replace Data.ByteString.Internal.ByteString
+ Text.RE.Types.Replace: instance Text.RE.Types.Replace.Replace Data.ByteString.Lazy.Internal.ByteString
+ Text.RE.Types.Replace: instance Text.RE.Types.Replace.Replace Data.Text.Internal.Lazy.Text
+ Text.RE.Types.Replace: instance Text.RE.Types.Replace.Replace Data.Text.Internal.Text
+ Text.RE.Types.Replace: instance Text.RE.Types.Replace.Replace [GHC.Types.Char]
+ Text.RE.Types.Replace: isTopLocation :: Location -> Bool
+ Text.RE.Types.Replace: lengthE :: Replace a => a -> Int
+ Text.RE.Types.Replace: linesE :: Replace a => a -> [a]
+ Text.RE.Types.Replace: packE :: Replace a => String -> a
+ Text.RE.Types.Replace: parseTemplateE :: Replace a => a -> Match a -> Location -> Capture a -> Maybe a
+ Text.RE.Types.Replace: replace :: Replace a => Match a -> a -> a
+ Text.RE.Types.Replace: replaceAll :: Replace a => a -> Matches a -> a
+ Text.RE.Types.Replace: replaceAllCaptures :: Replace a => Context -> (Match a -> Location -> Capture a -> Maybe a) -> Matches a -> a
+ Text.RE.Types.Replace: replaceAllCapturesM :: (Extract a, Monad m) => ReplaceMethods a -> Context -> (Match a -> Location -> Capture a -> m (Maybe a)) -> Matches a -> m a
+ Text.RE.Types.Replace: replaceAllCaptures_ :: Extract a => ReplaceMethods a -> Context -> (Match a -> Location -> Capture a -> Maybe a) -> Matches a -> a
+ Text.RE.Types.Replace: replaceCaptures :: Replace a => Context -> (Match a -> Location -> Capture a -> Maybe a) -> Match a -> a
+ Text.RE.Types.Replace: replaceCapturesM :: (Monad m, Extract a) => ReplaceMethods a -> Context -> (Match a -> Location -> Capture a -> m (Maybe a)) -> Match a -> m a
+ Text.RE.Types.Replace: replaceCaptures_ :: Extract a => ReplaceMethods a -> Context -> (Match a -> Location -> Capture a -> Maybe a) -> Match a -> a
+ Text.RE.Types.Replace: replaceMethods :: Replace a => ReplaceMethods a
+ Text.RE.Types.Replace: substE :: Replace a => (a -> a) -> Capture a -> a
+ Text.RE.Types.Replace: textifyE :: Replace a => a -> Text
+ Text.RE.Types.Replace: unlinesE :: Replace a => [a] -> a
+ Text.RE.Types.Replace: unpackE :: Replace a => a -> String
- Text.RE: class (Extract a, Monoid a) => Replace a where textifyE = pack . unpackE detextifyE = packE . unpack appendNewlineE = (<> packE "\n") substE f m@(Capture {..}) = capturePrefix m <> f capturedText <> captureSuffix m
+ Text.RE: class (Show a, Eq a, Ord a, Extract a, Monoid a) => Replace a where textifyE = pack . unpackE detextifyE = packE . unpack appendNewlineE = (<> packE "\n") substE f m@(Capture {..}) = capturePrefix m <> f capturedText <> captureSuffix m
- Text.RE.TDFA.RE: compileRegex :: (IsOption o RE CompOption ExecOption, Functor m, Monad m) => o -> String -> m RE
+ Text.RE.TDFA.RE: compileRegex :: (Functor m, Monad m) => String -> m RE
- Text.RE.Tools.Sed: sed' :: (IsRegex re ByteString, Monad m, Functor m) => Edits m re ByteString -> ByteString -> m ByteString
+ Text.RE.Tools.Sed: sed' :: (IsRegex re a, Monad m, Functor m) => Edits m re a -> a -> m a
Files
- README.markdown +6/−2
- Text/RE.hs +7/−71
- Text/RE/Capture.lhs +0/−292
- Text/RE/CaptureID.hs +0/−49
- Text/RE/Edit.lhs +0/−96
- Text/RE/Internal/AddCaptureNames.hs +1/−0
- Text/RE/Internal/NamedCaptures.lhs +2/−0
- Text/RE/Internal/PreludeMacros.hs +18/−17
- Text/RE/IsRegex.lhs +0/−17
- Text/RE/LineNo.hs +0/−18
- Text/RE/Options.lhs +0/−69
- Text/RE/Parsers.hs +0/−166
- Text/RE/Replace.lhs +0/−453
- Text/RE/TDFA.hs +1/−0
- Text/RE/TDFA/ByteString.hs +6/−3
- Text/RE/TDFA/ByteString/Lazy.hs +6/−3
- Text/RE/TDFA/RE.hs +19/−9
- Text/RE/TDFA/Sequence.hs +6/−3
- Text/RE/TDFA/String.hs +6/−3
- Text/RE/TDFA/Text.hs +6/−3
- Text/RE/TDFA/Text/Lazy.hs +6/−3
- Text/RE/TestBench.lhs +12/−4
- Text/RE/TestBench/Parsers.hs +166/−0
- Text/RE/Tools/Edit.lhs +98/−0
- Text/RE/Tools/Grep.lhs +6/−3
- Text/RE/Tools/Lex.lhs +8/−4
- Text/RE/Tools/Sed.lhs +14/−9
- Text/RE/Types/Capture.lhs +61/−0
- Text/RE/Types/CaptureID.hs +49/−0
- Text/RE/Types/IsRegex.lhs +25/−0
- Text/RE/Types/LineNo.hs +18/−0
- Text/RE/Types/Match.lhs +193/−0
- Text/RE/Types/Matches.lhs +81/−0
- Text/RE/Types/Options.lhs +69/−0
- Text/RE/Types/Replace.lhs +471/−0
- changelog +7/−0
- regex.cabal +12/−10
README.markdown view
@@ -53,9 +53,13 @@ ☒ 2017-03-13 v0.6.0.0 [Split out PCRE](https://github.com/iconnect/regex/milestone/7) - ☒ 2017-03-13 v0.6.0.1 [Fix .travis.yml release-stack scriptRE](https://github.com/iconnect/regex/milestone/7)+ ☒ 2017-03-13 v0.6.0.1 [Fix .travis.yml release-stack script](https://github.com/iconnect/regex/issues/67) - ☐ 2017-03-20 v1.0.0.0 [First stable release](https://github.com/iconnect/regex/milestone/3)+ ☒ 2017-03-15 v0.7.0.0 [Better organization of API](https://github.com/iconnect/regex/milestone/8)++ ☐ 2017-03-17 v0.8.0.0 [Add type-safe replacement templates and use TemplateHaskellQuotes](https://github.com/iconnect/regex/milestone/9)++ ☐ 2017-03-31 v1.0.0.0 [First stable release](https://github.com/iconnect/regex/milestone/3) ☐ 2017-08-31 v2.0.0.0 [Fast text replacement with benchmarks](https://github.com/iconnect/regex/milestone/4)
Text/RE.hs view
@@ -45,54 +45,10 @@ , hasCaptured , capturePrefix , captureSuffix- -- * IsRegex- , IsRegex(..) -- * Options- , Options_(..)- , IsOption(..)- , MacroID(..)- , Macros- , emptyMacros , SimpleRegexOptions(..) -- * CaptureID- , CaptureID(..)- , CaptureNames- , noCaptureNames- , CaptureName(..)- , CaptureOrdinal(..)- , findCaptureID- -- * Edit- , Edits(..)- , Edit(..)- , LineEdit(..)- , applyEdits- , applyEdit- , applyLineEdit- -- * LineNo- , LineNo(..)- , firstLine- , getLineNo- , lineNo- -- * Parsers- , parseInteger- , parseHex- , parseDouble- , parseString- , parseSimpleString- , parseDate- , parseSlashesDate- , parseTimeOfDay- , parseTimeZone- , parseDateTime- , parseDateTime8601- , parseDateTimeCLF- , parseShortMonth- , shortMonthArray- , IPV4Address- , parseIPv4Address- , Severity(..)- , parseSeverity- , severityKeywords+ , CaptureID -- * Replace , Replace(..) , ReplaceMethods(..)@@ -110,34 +66,14 @@ , replaceCapturesM , expandMacros , expandMacros'- -- * Tools- -- ** Grep- , Line(..)- , grep- , grepLines- , GrepScript- , grepScript- , linesMatched- -- ** Lex- , alex- , alex'- -- ** Sed- , SedScript- , sed- , sed' ) where -import Text.RE.Capture-import Text.RE.CaptureID-import Text.RE.Edit-import Text.RE.IsRegex-import Text.RE.LineNo-import Text.RE.Options-import Text.RE.Parsers-import Text.RE.Replace-import Text.RE.Tools.Grep-import Text.RE.Tools.Lex-import Text.RE.Tools.Sed+import Text.RE.Types.Capture+import Text.RE.Types.CaptureID+import Text.RE.Types.Match+import Text.RE.Types.Matches+import Text.RE.Types.Options+import Text.RE.Types.Replace -- $tutorial -- We have a regex tutorial at <http://tutorial.regex.uk>. These API
− Text/RE/Capture.lhs
@@ -1,292 +0,0 @@-\begin{code}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE DeriveDataTypeable #-}-\end{code}--\begin{code}-module Text.RE.Capture- ( Matches(..)- , Match(..)- , Capture(..)- , noMatch- , emptyMatchArray- -- Matches functions- , anyMatches- , countMatches- , matches- , mainCaptures- -- Match functions- , matched- , matchedText- , matchCapture- , matchCaptures- , (!$$)- , captureText- , (!$$?)- , captureTextMaybe- , (!$)- , capture- , (!$?)- , captureMaybe- -- Capture functions- , hasCaptured- , capturePrefix- , captureSuffix- ) where-\end{code}--\begin{code}-import Data.Array-import Data.Maybe-import Data.Typeable-import Text.Regex.Base-import Text.RE.CaptureID--infixl 9 !$, !$$-\end{code}----\begin{code}--- | the result type to use when every match is needed, not just the--- first match of the RE against the source-data Matches a =- Matches- { matchesSource :: !a -- ^ the source text being matched- , allMatches :: ![Match a] -- ^ all captures found, left to right- }- deriving (Show,Eq,Typeable)-\end{code}--\begin{code}--- | the result of matching a RE to a text once, listing the text that--- was matched and the named captures in the RE and all of the substrings--- matched, with the text captured by the whole RE; a complete failure--- to match will be represented with an empty array (with bounds (0,-1))-data Match a =- Match- { matchSource :: !a -- ^ the whole source text- , captureNames :: !CaptureNames -- ^ the RE's capture names- , matchArray :: !(Array CaptureOrdinal (Capture a))- -- ^ 0..n-1 captures,- -- starting with the- -- text matched by the- -- whole RE- }- deriving (Show,Eq,Typeable)-\end{code}--\begin{code}--- | the matching of a single sub-expression against part of the source--- text-data Capture a =- Capture- { captureSource :: !a -- ^ the whole text that was searched- , capturedText :: !a -- ^ the text that was matched- , captureOffset :: !Int -- ^ the number of characters preceding the- -- match with -1 used if no text was captured- -- by the RE (not even the empty string)- , captureLength :: !Int -- ^ the number of chacter in the captured- -- sub-string- }- deriving (Show,Eq)-\end{code}--\begin{code}--- | Construct a Match that does not match anything.-noMatch :: a -> Match a-noMatch t = Match t noCaptureNames emptyMatchArray---- | an empty array of Capture-emptyMatchArray :: Array CaptureOrdinal (Capture a)-emptyMatchArray = listArray (CaptureOrdinal 0,CaptureOrdinal $ -1) []-\end{code}--\begin{code}-instance Functor Matches where- fmap f Matches{..} =- Matches- { matchesSource = f matchesSource- , allMatches = map (fmap f) allMatches- }--instance Functor Match where- fmap f Match{..} =- Match- { matchSource = f matchSource- , captureNames = captureNames- , matchArray = fmap (fmap f) matchArray- }--instance Functor Capture where- fmap f c@Capture{..} =- c- { captureSource = f captureSource- , capturedText = f capturedText- }-\end{code}--\begin{code}--- | tests whether the RE matched the source text at all-anyMatches :: Matches a -> Bool-anyMatches = not . null . allMatches---- | count the matches-countMatches :: Matches a -> Int-countMatches = length . allMatches--matches :: Matches a -> [a]-matches = map capturedText . mainCaptures---- | extract the main capture from each match-mainCaptures :: Matches a -> [Capture a]-mainCaptures ac = [ capture c0 cs | cs<-allMatches ac ]- where- c0 = IsCaptureOrdinal $ CaptureOrdinal 0-\end{code}----\begin{code}--- | tests whether the RE matched the source text at all-matched :: Match a -> Bool-matched = isJust . matchCapture---- | tests whether the RE matched the source text at all-matchedText :: Match a -> Maybe a-matchedText = fmap capturedText . matchCapture---- | the top-level capture if the source text matched the RE,--- Nothing otherwise-matchCapture :: Match a -> Maybe (Capture a)-matchCapture = fmap fst . matchCaptures---- | the top-level capture and the sub captures if the text matched--- the RE, Nothing otherwise-matchCaptures :: Match a -> Maybe (Capture a,[Capture a])-matchCaptures Match{..} = case rangeSize (bounds matchArray) == 0 of- True -> Nothing- False -> Just (matchArray!0,drop 1 $ elems matchArray)---- | an alternative for captureText-(!$$) :: Match a -> CaptureID -> a-(!$$) = flip captureText---- | look up the text of the nth capture, 0 being the match of the whole--- RE against the source text, 1, the first bracketed sub-expression to--- be matched and so on-captureText :: CaptureID -> Match a -> a-captureText cid mtch = capturedText $ capture cid mtch---- | an alternative for captureTextMaybe-(!$$?) :: Match a -> CaptureID -> Maybe a-(!$$?) = flip captureTextMaybe---- | look up the text of the nth capture (0 being the match of the--- whole), returning Nothing if the Match doesn't contain the capture-captureTextMaybe :: CaptureID -> Match a -> Maybe a-captureTextMaybe cid mtch = do- cap <- mtch !$? cid- case hasCaptured cap of- True -> Just $ capturedText cap- False -> Nothing---- | an alternative for capture-(!$) :: Match a -> CaptureID -> Capture a-(!$) = flip capture---- | look up the nth capture, 0 being the match of the whole RE against--- the source text, 1, the first bracketed sub-expression to be matched--- and so on-capture :: CaptureID -> Match a -> Capture a-capture cid mtch = fromMaybe oops $ mtch !$? cid- where- oops = error $ "capture: out of bounds (" ++ show cid ++ ")"---- | an alternative for capture captureMaybe-(!$?) :: Match a -> CaptureID -> Maybe (Capture a)-(!$?) = flip captureMaybe---- | look up the nth capture, 0 being the match of the whole RE against--- the source text, 1, the first bracketed sub-expression to be matched--- and so on, returning Nothing if there is no such capture, or if the--- capture failed to capture anything (being in a failed alternate)-captureMaybe :: CaptureID -> Match a -> Maybe (Capture a)-captureMaybe cid mtch@Match{..} = do- cap <- case bounds matchArray `inRange` CaptureOrdinal i of- True -> Just $ matchArray ! CaptureOrdinal i- False -> Nothing- case hasCaptured cap of- True -> Just cap- False -> Nothing- where- i = lookupCaptureID cid mtch--lookupCaptureID :: CaptureID -> Match a -> Int-lookupCaptureID cid Match{..} = findCaptureID cid captureNames-\end{code}---\begin{code}--- | test if the capture has matched any text-hasCaptured :: Capture a -> Bool-hasCaptured = (>=0) . captureOffset---- | returns the text preceding the match-capturePrefix :: Extract a => Capture a -> a-capturePrefix Capture{..} = before captureOffset captureSource---- | returns the text after the match-captureSuffix :: Extract a => Capture a -> a-captureSuffix Capture{..} = after (captureOffset+captureLength) captureSource-\end{code}---\begin{code}--- | for matching just the first RE against the source text-instance- ( RegexContext regex source (AllTextSubmatches (Array Int) (source,(Int,Int)))- , RegexLike regex source- ) =>- RegexContext regex source (Match source) where- match r s = cvt s $ getAllTextSubmatches $ match r s- matchM r s = do- y <- matchM r s- return $ cvt s $ getAllTextSubmatches y---- | for matching all REs against the source text-instance- ( RegexContext regex source [MatchText source]- , RegexLike regex source- ) =>- RegexContext regex source (Matches source) where- match r s = Matches s $ map (cvt s) $ match r s- matchM r s = do- y <- matchM r s- return $ Matches s $ map (cvt s) y-\end{code}--\begin{code}-cvt :: source -> MatchText source -> Match source-cvt hay arr =- Match- { matchSource = hay- , captureNames = noCaptureNames- , matchArray =- ixmap (CaptureOrdinal lo,CaptureOrdinal hi) getCaptureOrdinal $- fmap f arr- }- where- (lo,hi) = bounds arr-- f (ndl,(off,len)) =- Capture- { captureSource = hay- , capturedText = ndl- , captureOffset = off- , captureLength = len- }-\end{code}
− Text/RE/CaptureID.hs
@@ -1,49 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}--module Text.RE.CaptureID where--import Data.Ix-import Data.Hashable-import qualified Data.HashMap.Strict as HMS-import Data.Maybe-import qualified Data.Text as T----- | CaptureID identifies captures, either by number--- (e.g., [cp|1|]) or name (e.g., [cp|foo|]).-data CaptureID- = IsCaptureOrdinal CaptureOrdinal- | IsCaptureName CaptureName- deriving (Show,Ord,Eq)---- | the dictionary for named captures stored in compiled regular--- expressions associates-type CaptureNames = HMS.HashMap CaptureName CaptureOrdinal---- | an empty 'CaptureNames' dictionary-noCaptureNames :: CaptureNames-noCaptureNames = HMS.empty---- | a 'CaptureName' is just the text of the name-newtype CaptureName = CaptureName { getCaptureName :: T.Text }- deriving (Show,Ord,Eq)--instance Hashable CaptureName where- hashWithSalt i = hashWithSalt i . getCaptureName---- | a 'CaptureOrdinal' is just the number of the capture, starting--- with 0 for the whole of the text matched, then in leftmost,--- outermost-newtype CaptureOrdinal = CaptureOrdinal { getCaptureOrdinal :: Int }- deriving (Show,Ord,Eq,Enum,Ix,Num)---- | look up a 'CaptureID' in the 'CaptureNames' dictionary-findCaptureID :: CaptureID -> CaptureNames -> Int-findCaptureID (IsCaptureOrdinal o) _ = getCaptureOrdinal o-findCaptureID (IsCaptureName n) hms =- getCaptureOrdinal $ fromMaybe oops $ HMS.lookup n hms- where- oops = error $ unlines $- ("lookupCaptureID: " ++ T.unpack t ++ " not found in:") :- [ " "++T.unpack (getCaptureName nm) | nm <- HMS.keys hms ]- t = getCaptureName n
− Text/RE/Edit.lhs
@@ -1,96 +0,0 @@-\begin{code}-{-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE CPP #-}-#if __GLASGOW_HASKELL__ >= 800-{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}-#endif--module Text.RE.Edit- ( LineNo- , Edits(..)- , Edit(..)- , LineEdit(..)- , applyEdits- , applyEdit- , applyLineEdit- ) where--import Data.Maybe-import Prelude.Compat-import Text.RE.Capture-import Text.RE.IsRegex-import Text.RE.LineNo-import Text.RE.Replace---data Edits m re s- = Select [(re,Edit m s)]- | Pipe [(re,Edit m s)]--data Edit m s- = Template s- | Function Context (LineNo->Match s->Location->Capture s->m (Maybe s))- | LineEdit (LineNo->Matches s->m (LineEdit s))--data LineEdit s- = NoEdit- | ReplaceWith s- | Delete- deriving (Show)--applyEdits :: (IsRegex re s,Monad m,Functor m)- => LineNo- -> Edits m re s- -> s- -> m s-applyEdits lno ez0 s0 = case ez0 of- Select ez -> select_edit_scripts lno ez s0- Pipe ez -> pipe_edit_scripts lno ez s0--applyEdit :: (IsRegex re s,Monad m,Functor m)- => (s->s)- -> LineNo- -> re- -> Edit m s- -> s- -> m (Maybe s)-applyEdit anl lno re edit s =- case allMatches acs of- [] -> return Nothing- _ -> fmap Just $ case edit of- Template tpl -> return $ anl $ replaceAll tpl acs- Function ctx f -> anl <$> replaceAllCapturesM replaceMethods ctx (f lno) acs- LineEdit g -> fromMaybe s' . applyLineEdit anl <$> g lno acs- where- s' = anl s- acs = matchMany re s--applyLineEdit :: Monoid s => (s->s) -> LineEdit s -> Maybe s-applyLineEdit _ NoEdit = Nothing-applyLineEdit anl (ReplaceWith s) = Just $ anl s-applyLineEdit _ Delete = Just $ mempty--select_edit_scripts :: (IsRegex re s,Monad m,Functor m)- => LineNo- -> [(re,Edit m s)]- -> s- -> m s-select_edit_scripts lno ps0 s = select ps0- where- select [] = return $ appendNewlineE s- select ((re,es):ps) =- applyEdit appendNewlineE lno re es s >>= maybe (select ps) return--pipe_edit_scripts :: (IsRegex re s,Monad m,Functor m)- => LineNo- -> [(re,Edit m s)]- -> s- -> m s-pipe_edit_scripts lno ez s0 =- appendNewlineE <$> foldr f (return s0) ez- where- f (re,es) act = do- s <- act- fromMaybe s <$> applyEdit id lno re es s-\end{code}
Text/RE/Internal/AddCaptureNames.hs view
@@ -15,6 +15,7 @@ import qualified Data.Text.Lazy as TL import Prelude.Compat import Text.RE+import Text.RE.Types.CaptureID import Unsafe.Coerce
Text/RE/Internal/NamedCaptures.lhs view
@@ -27,6 +27,8 @@ import Text.RE.Internal.PreludeMacros import Text.RE.Internal.QQ import Text.RE.TestBench+import Text.RE.Tools.Lex+import Text.RE.Types.CaptureID import Text.Regex.TDFA
Text/RE/Internal/PreludeMacros.hs view
@@ -8,7 +8,7 @@ #endif module Text.RE.Internal.PreludeMacros- ( RegexType(..)+ ( RegexType , WithCaptures(..) , MacroDescriptor(..) , RegexSource(..)@@ -30,8 +30,8 @@ import qualified Data.Text as T import Data.Time import Prelude.Compat-import Text.RE.Options-import Text.RE.Parsers+import Text.RE.Types.Options+import Text.RE.TestBench.Parsers import Text.RE.TestBench @@ -266,17 +266,18 @@ -> MacroEnv -> PreludeMacro -> Maybe MacroDescriptor-string_macro (PCRE _) _ _ = Nothing-string_macro rty@(TDFA _) env pm =- Just $ run_tests rty (fmap T.unpack . parseString) samples env pm- MacroDescriptor- { _md_source = "\"(?:[^\"\\]+|\\\\[\\\"])*\""- , _md_samples = map fst samples- , _md_counter_samples = counter_samples- , _md_test_results = []- , _md_parser = Just "parseString"- , _md_description = "a double-quote string, with simple \\ escapes for \\s and \"s"- }+string_macro rty env pm+ | isPCRE rty = Nothing+ | otherwise =+ Just $ run_tests rty (fmap T.unpack . parseString) samples env pm+ MacroDescriptor+ { _md_source = "\"(?:[^\"\\]+|\\\\[\\\"])*\""+ , _md_samples = map fst samples+ , _md_counter_samples = counter_samples+ , _md_test_results = []+ , _md_parser = Just "parseString"+ , _md_description = "a double-quote string, with simple \\ escapes for \\s and \"s"+ } where samples :: [(String,String)] samples =@@ -788,9 +789,9 @@ , "ALERT" ] - re = case rty of- PCRE _ -> re_pcre- TDFA _ -> re_tdfa+ re = if isPCRE rty+ then re_pcre+ else re_tdfa re_tdfa = bracketedRegexSource $ intercalate "|" $
− Text/RE/IsRegex.lhs
@@ -1,17 +0,0 @@-\begin{code}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE AllowAmbiguousTypes #-}--module Text.RE.IsRegex where--import Text.RE.Capture-import Text.RE.Replace-\end{code}---\begin{code}-class Replace s => IsRegex re s where- matchOnce :: re -> s -> Match s- matchMany :: re -> s -> Matches s- regexSource :: re -> String-\end{code}
− Text/RE/LineNo.hs
@@ -1,18 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}--module Text.RE.LineNo where---newtype LineNo =- ZeroBasedLineNo { getZeroBasedLineNo :: Int }- deriving (Show,Enum)---firstLine :: LineNo-firstLine = ZeroBasedLineNo 0--getLineNo :: LineNo -> Int-getLineNo = (+1) . getZeroBasedLineNo--lineNo :: Int -> LineNo-lineNo = ZeroBasedLineNo . (\x->x-1)
− Text/RE/Options.lhs
@@ -1,69 +0,0 @@-\begin{code}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FunctionalDependencies #-}--module Text.RE.Options where--import Data.Hashable-import qualified Data.HashMap.Strict as HM-import Data.String-import Language.Haskell.TH-import Language.Haskell.TH.Syntax-\end{code}--\begin{code}-data Options_ r c e =- Options- { optionsMacs :: !(Macros r)- , optionsComp :: !c- , optionsExec :: !e- }- deriving (Show)-\end{code}--\begin{code}-class IsOption o r c e |- e -> r, c -> e , e -> c, r -> c, c -> r, r -> e where- makeOptions :: o -> Options_ r c e-\end{code}--\begin{code}-newtype MacroID =- MacroID { getMacroID :: String }- deriving (IsString,Ord,Eq,Show)-\end{code}--\begin{code}-instance Hashable MacroID where- hashWithSalt i = hashWithSalt i . getMacroID-\end{code}--\begin{code}-type Macros r = HM.HashMap MacroID r-\end{code}--\begin{code}-emptyMacros :: Macros r-emptyMacros = HM.empty-\end{code}--\begin{code}-data SimpleRegexOptions- = MultilineSensitive- | MultilineInsensitive- | BlockSensitive- | BlockInsensitive- deriving (Bounded,Enum,Eq,Ord,Show)-\end{code}--\begin{code}-instance Lift SimpleRegexOptions where- lift sro = case sro of- MultilineSensitive -> conE 'MultilineSensitive- MultilineInsensitive -> conE 'MultilineInsensitive- BlockSensitive -> conE 'BlockSensitive- BlockInsensitive -> conE 'BlockInsensitive-\end{code}
− Text/RE/Parsers.hs
@@ -1,166 +0,0 @@-{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}-{-# LANGUAGE OverloadedStrings #-}--module Text.RE.Parsers- ( parseInteger- , parseHex- , parseDouble- , parseString- , parseSimpleString- , parseDate- , parseSlashesDate- , parseTimeOfDay- , parseTimeZone- , parseDateTime- , parseDateTime8601- , parseDateTimeCLF- , parseShortMonth- , shortMonthArray- , IPV4Address- , parseIPv4Address- , Severity(..)- , parseSeverity- , severityKeywords- ) where--import Data.Array-import qualified Data.HashMap.Strict as HM-import Data.Maybe-import qualified Data.Text as T-import Data.Time-import qualified Data.Time.Locale.Compat as LC-import Data.Word-import Text.Printf-import Text.Read-import Text.RE.Replace---parseInteger :: Replace a => a -> Maybe Int-parseInteger = readMaybe . unpackE--parseHex :: Replace a => a -> Maybe Int-parseHex = readMaybe . ("0x"++) . unpackE--parseDouble :: Replace a => a -> Maybe Double-parseDouble = readMaybe . unpackE--parseString :: Replace a => a -> Maybe T.Text-parseString = readMaybe . unpackE--parseSimpleString :: Replace a => a -> Maybe T.Text-parseSimpleString = Just . T.dropEnd 1 . T.drop 1 . textifyE--date_templates, time_templates, timezone_templates,- date_time_8601_templates, date_time_templates :: [String]-date_templates = ["%F"]-time_templates = ["%H:%M:%S","%H:%M:%S%Q","%H:%M"]-timezone_templates = ["Z","%z"]-date_time_8601_templates =- [ printf "%sT%s%s" dt tm tz- | dt <- date_templates- , tm <- time_templates- , tz <- timezone_templates- ]-date_time_templates =- [ printf "%s%c%s%s" dt sc tm tz- | dt <- date_templates- , sc <- ['T',' ']- , tm <- time_templates- , tz <- timezone_templates ++ [" UTC",""]- ]--parseDate :: Replace a => a -> Maybe Day-parseDate = parse_time date_templates--parseSlashesDate :: Replace a => a -> Maybe Day-parseSlashesDate = parse_time ["%Y/%m/%d"]--parseTimeOfDay :: Replace a => a -> Maybe TimeOfDay-parseTimeOfDay = parse_time time_templates--parseTimeZone :: Replace a => a -> Maybe TimeZone-parseTimeZone = parse_time timezone_templates--parseDateTime :: Replace a => a -> Maybe UTCTime-parseDateTime = parse_time date_time_templates--parseDateTime8601 :: Replace a => a -> Maybe UTCTime-parseDateTime8601 = parse_time date_time_8601_templates--parseDateTimeCLF :: Replace a => a -> Maybe UTCTime-parseDateTimeCLF = parse_time ["%d/%b/%Y:%H:%M:%S %z"]--parseShortMonth :: Replace a => a -> Maybe Int-parseShortMonth = flip HM.lookup short_month_hm . unpackE--parse_time :: (ParseTime t,Replace s) => [String] -> s -> Maybe t-parse_time tpls = prs . unpackE- where- prs s = listToMaybe $ catMaybes- [ parseTime LC.defaultTimeLocale fmt s- | fmt<-tpls- ]--short_month_hm :: HM.HashMap String Int-short_month_hm = HM.fromList [ (T.unpack $ shortMonthArray!i,i) | i<-[1..12] ]--shortMonthArray :: Array Int T.Text-shortMonthArray = listArray (1,12) $- T.words "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"--type IPV4Address = (Word8,Word8,Word8,Word8)--parseIPv4Address :: Replace a => a -> Maybe IPV4Address-parseIPv4Address = prs . words_by (=='.') . unpackE- where- prs [a_s,b_s,c_s,d_s] = do- a <- readMaybe a_s- b <- readMaybe b_s- c <- readMaybe c_s- d <- readMaybe d_s- case all is_o [a,b,c,d] of- True -> Just (toEnum a,toEnum b,toEnum c,toEnum d)- False -> Nothing- prs _ = Nothing-- is_o x = 0 <= x && x <= 255--data Severity- = Emerg- | Alert- | Crit- | Err- | Warning- | Notice- | Info- | Debug- deriving (Bounded,Enum,Ord,Eq,Show)--parseSeverity :: Replace a => a -> Maybe Severity-parseSeverity = flip HM.lookup severity_hm . textifyE--severity_hm :: HM.HashMap T.Text Severity-severity_hm = HM.fromList- [ (kw,pri)- | pri<-[minBound..maxBound]- , let (kw0,kws) = severityKeywords pri- , kw <- kw0:kws- ]--severityKeywords :: Severity -> (T.Text,[T.Text])-severityKeywords pri = case pri of- Emerg -> (,) "emerg" ["panic"]- Alert -> (,) "alert" []- Crit -> (,) "crit" []- Err -> (,) "err" ["error"]- Warning -> (,) "warning" ["warn"]- Notice -> (,) "notice" []- Info -> (,) "info" []- Debug -> (,) "debug" []--words_by :: (Char->Bool) -> String -> [String]-words_by f s = case dropWhile f s of- "" -> []- s' -> w : words_by f s''- where- (w, s'') = break f s'
− Text/RE/Replace.lhs
@@ -1,453 +0,0 @@-\begin{code}-{-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}--module Text.RE.Replace- ( Replace(..)- , ReplaceMethods(..)- , replaceMethods- , Context(..)- , Location(..)- , isTopLocation- , replace- , replaceAll- , replaceAllCaptures- , replaceAllCaptures_- , replaceAllCapturesM- , replaceCaptures- , replaceCaptures_- , replaceCapturesM- , expandMacros- , expandMacros'- ) 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 Data.Monoid-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.Heredoc-import Text.RE.Capture-import Text.RE.CaptureID-import Text.RE.Options-import Text.Read-import Text.Regex.TDFA-import Text.Regex.TDFA.Text()-import Text.Regex.TDFA.Text.Lazy()-\end{code}--\begin{code}--- | Replace provides the missing methods needed to replace the matched--- text; lengthE is the minimum implementation-class (Extract a,Monoid a) => Replace a where- -- | length function for a- lengthE :: a -> Int- -- | inject String into a- packE :: String -> a- -- | project a onto a String- unpackE :: a -> String- -- | inject into Text- textifyE :: a -> T.Text- -- | project Text onto a- detextifyE :: T.Text -> a- -- | append a newline- appendNewlineE :: a -> a- -- | apply a substitution function to a Capture- substE :: (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- parseTemplateE :: a -> Match a -> Location -> Capture a -> Maybe a-- textifyE = T.pack . unpackE- detextifyE = packE . T.unpack- appendNewlineE = (<> packE "\n")-- substE f m@Capture{..} =- capturePrefix m <> f capturedText <> captureSuffix m-\end{code}--\begin{code}--- | a selction of the Replace methods can be encapsulated with ReplaceMethods--- for the higher-order replacement functions-data ReplaceMethods a =- ReplaceMethods- { methodLength :: a -> Int- , methodSubst :: (a->a) -> Capture a -> a- }---- | replaceMethods encapsulates ReplaceMethods a from a Replace a context-replaceMethods :: Replace a => ReplaceMethods a-replaceMethods =- ReplaceMethods- { methodLength = lengthE- , methodSubst = substE- }-\end{code}--\begin{code}--- | @Context@ specifies which contexts the substitutions should be applied-data Context- = 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 (Show)---- | the @Location@ information passed into the substitution function--- specifies which sub-expression is being substituted-data Location =- Location- { locationMatch :: Int- -- ^ the zero-based, i-th string to be matched,- -- when matching all strings, zero when only the- -- first string is being matched- , 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 (Show)-\end{code}--\begin{code}--- | True iff the location references a complete match--- (i.e., not a bracketed capture)-isTopLocation :: Location -> Bool-isTopLocation = (==0) . 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 tpl ac = replaceAllCaptures TOP (parseTemplateE tpl) 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- => Context- -> (Match a->Location->Capture a->Maybe a)- -> Matches a- -> a-\end{code}--\begin{code}-replaceAllCaptures = replaceAllCaptures_ replaceMethods-\end{code}--\begin{code}--- | replaceAllCaptures_ is like like replaceAllCaptures but takes the--- Replace methods through the ReplaceMethods argument-replaceAllCaptures_ :: Extract a- => ReplaceMethods a- -> Context- -> (Match a->Location->Capture a->Maybe a)- -> Matches a- -> a-replaceAllCaptures_ s ctx phi ac =- runIdentity $ replaceAllCapturesM s ctx (lift_phi phi) ac-\end{code}--\begin{code}--- | replaceAllCapturesM is just a monadically generalised version of--- replaceAllCaptures_-replaceAllCapturesM :: (Extract a,Monad m)- => ReplaceMethods a- -> Context- -> (Match a->Location->Capture a->m (Maybe a))- -> Matches a- -> m a-replaceAllCapturesM r ctx phi_ Matches{..} =- replaceCapturesM r ALL phi $ Match matchesSource cnms arr- where- phi _ (Location _ i) = case arr_c!i of- Just caps -> phi_ caps . uncurry Location $ arr_i ! i- Nothing -> const $ return Nothing-- arr_c = listArray bds $- concat $- [ repl (rangeSize $ bounds $ matchArray cs) cs- | cs <- allMatches- ]-- arr_i = listArray bds j_ks-- arr = listArray bds $- [ arr_ ! k- | arr_ <- map matchArray allMatches- , k <- indices arr_- ]-- bds = (0,CaptureOrdinal $ length j_ks-1)-- j_ks =- [ (j,k)- | (j,arr_) <- zip [0..] $ map matchArray allMatches- , k <- indices arr_- ]-- repl 0 _ = []- repl n x = case ctx of- TOP -> Just x : replicate (n-1) Nothing- SUB -> Nothing : replicate (n-1) (Just x)- ALL -> replicate n $ Just x-- cnms = fromMaybe noCaptureNames $ listToMaybe $ map captureNames allMatches-\end{code}--\begin{code}--- | replace with a template containing $0 for whole text,--- $1 for first capture, etc.-replace :: Replace a- => Match a- -> a- -> a-replace c tpl = replaceCaptures TOP (parseTemplateE tpl) 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- => Context- -> (Match a->Location->Capture a->Maybe a)- -> Match a- -> a-replaceCaptures = replaceCaptures_ replaceMethods-\end{code}--\begin{code}--- | replaceCaptures_ is like replaceCaptures but takes the Replace methods--- through the ReplaceMethods argument-replaceCaptures_ :: Extract a- => ReplaceMethods a- -> Context- -> (Match a->Location->Capture a->Maybe a)- -> Match a- -> a-replaceCaptures_ s ctx phi caps =- runIdentity $ replaceCapturesM s ctx (lift_phi phi) caps-\end{code}--\begin{code}--- | replaceCapturesM is just a monadically generalised version of--- replaceCaptures_-replaceCapturesM :: (Monad m,Extract a)- => ReplaceMethods a- -> Context- -> (Match a->Location->Capture a->m (Maybe a))- -> Match a- -> m a-replaceCapturesM ReplaceMethods{..} ctx phi_ caps@Match{..} = do- (hay',_) <- foldr sc (return (matchSource,[])) $- zip [0..] $ elems matchArray- return hay'- where- sc (i,cap0) act = do- (hay,ds) <- act- let ndl = capturedText cap- cap = adj hay ds cap0- mb <- phi i cap- case mb of- Nothing -> return (hay,ds)- Just ndl' ->- return- ( methodSubst (const ndl') cap- , (captureOffset cap,len'-len) : ds- )- where- len' = methodLength ndl'- len = methodLength ndl-- adj hay ds cap =- Capture- { captureSource = hay- , capturedText = before len $ after off0 hay- , captureOffset = off0- , captureLength = len- }- where- len = len0 + sum- [ delta- | (off,delta) <- ds- , off < off0 + len0- ]- len0 = captureLength cap- off0 = captureOffset cap-- phi i cap = case ctx of- TOP | i/=0 -> return Nothing- SUB | i==0 ->return Nothing- _ ->- case not $ hasCaptured cap of- True -> return Nothing- False -> phi_ caps (Location 0 i) cap-\end{code}--\begin{code}--- the Replace instances--instance Replace [Char] where- lengthE = length- packE = id- unpackE = id- textifyE = T.pack- detextifyE = T.unpack- appendNewlineE = (<>"\n")- parseTemplateE = parseTemplateE' id--instance Replace B.ByteString where- lengthE = B.length- packE = B.pack- unpackE = B.unpack- textifyE = TE.decodeUtf8- detextifyE = TE.encodeUtf8- appendNewlineE = (<>"\n")- parseTemplateE = parseTemplateE' B.unpack--instance Replace LBS.ByteString where- lengthE = fromEnum . LBS.length- packE = LBS.pack- unpackE = LBS.unpack- textifyE = TE.decodeUtf8 . LBS.toStrict- detextifyE = LBS.fromStrict . TE.encodeUtf8- appendNewlineE = (<>"\n")- parseTemplateE = parseTemplateE' LBS.unpack--instance Replace (S.Seq Char) where- lengthE = S.length- packE = S.fromList- unpackE = F.toList- parseTemplateE = parseTemplateE' F.toList--instance Replace T.Text where- lengthE = T.length- packE = T.pack- unpackE = T.unpack- textifyE = id- detextifyE = id- appendNewlineE = (<>"\n")- parseTemplateE = parseTemplateE' T.unpack--instance Replace LT.Text where- lengthE = fromEnum . LT.length- packE = LT.pack- unpackE = LT.unpack- textifyE = LT.toStrict- detextifyE = LT.fromStrict- appendNewlineE = (<>"\n")- parseTemplateE = parseTemplateE' LT.unpack-\end{code}--\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 x_src hm s =- case HM.null hm of- True -> s- False -> expandMacros' (fmap x_src . flip HM.lookup hm) s-\end{code}--\begin{code}--- | expand the @{..} macos in the argument string using the given--- function-expandMacros' :: (MacroID->Maybe String) -> String -> String-expandMacros' lu = fixpoint e_m- where- e_m re_s = replaceAllCaptures TOP phi $ re_s $=~ [here|@(@|\{([^{}]+)\})|]- where- phi mtch _ cap = case txt == "@@" of- True -> Just "@"- False -> Just $ fromMaybe txt $ lu ide- where- txt = capturedText cap- ide = MacroID $ capturedText $ capture c2 mtch- c2 = IsCaptureOrdinal $ CaptureOrdinal 2-\end{code}--\begin{code}-lift_phi :: Monad m- => (Match a->Location->Capture a->Maybe a)- -> (Match a->Location->Capture a->m (Maybe a))-lift_phi phi_ = phi- where- phi caps' loc' cap' = return $ phi_ caps' loc' cap'-\end{code}--\begin{code}-parseTemplateE' :: ( Replace a- , RegexContext Regex a (Matches a)- , RegexMaker Regex CompOption ExecOption String- )- => (a->String)- -> a- -> Match a- -> Location- -> Capture a- -> Maybe a-parseTemplateE' unpack tpl mtch _ _ =- Just $ replaceAllCaptures TOP phi $- tpl $=~ [here|\$(\$|[0-9]|\{([^{}]+)\})|]- where- phi t_mtch _ _ = case t_mtch !$? c2 of- Just cap -> case readMaybe stg of- Nothing -> this $ IsCaptureName $ CaptureName $ T.pack stg- Just cn -> this $ IsCaptureOrdinal $ CaptureOrdinal cn- where- stg = unpack $ capturedText cap- Nothing -> case s == "$" of- True -> Just t- False -> this $ IsCaptureOrdinal $ CaptureOrdinal $ read s- where- s = unpack t- t = capturedText $ capture c1 t_mtch-- this cid = capturedText <$> mtch !$? cid-- c1 = IsCaptureOrdinal $ CaptureOrdinal 1- c2 = IsCaptureOrdinal $ CaptureOrdinal 2-\end{code}--\begin{code}-fixpoint :: (Eq a) => (a->a) -> a -> a-fixpoint f = chk . iterate f- where- chk (x:x':_) | x==x' = x- chk xs = chk $ tail xs-\end{code}--\begin{code}-($=~) :: ( RegexContext Regex source target- , RegexMaker Regex CompOption ExecOption String- )- => source -> String -> target-($=~) = (=~)--\end{code}
Text/RE/TDFA.hs view
@@ -43,6 +43,7 @@ import Text.RE.TDFA.String() import Text.RE.TDFA.Text() import Text.RE.TDFA.Text.Lazy()+import Text.RE.Types.IsRegex -- | find all matches in text
Text/RE/TDFA/ByteString.hs view
@@ -31,6 +31,7 @@ import Data.Typeable import Text.Regex.Base import Text.RE+import Text.RE.Types.IsRegex import Text.RE.Internal.AddCaptureNames import Text.RE.TDFA.RE import qualified Text.Regex.TDFA as TDFA@@ -71,9 +72,11 @@ (=~~) bs rex = addCaptureNames (reCaptureNames rex) <$> matchM (reRegex rex) bs instance IsRegex RE B.ByteString where- matchOnce = flip (?=~)- matchMany = flip (*=~)- regexSource = reSource+ matchOnce = flip (?=~)+ matchMany = flip (*=~)+ makeRegexWith = \o -> compileRegexWith o . unpackE+ makeRegex = compileRegex . unpackE+ regexSource = packE . reSource -- $tutorial -- We have a regex tutorial at <http://tutorial.regex.uk>. These API
Text/RE/TDFA/ByteString/Lazy.hs view
@@ -31,6 +31,7 @@ import Data.Typeable import Text.Regex.Base import Text.RE+import Text.RE.Types.IsRegex import Text.RE.Internal.AddCaptureNames import Text.RE.TDFA.RE import qualified Text.Regex.TDFA as TDFA@@ -71,9 +72,11 @@ (=~~) bs rex = addCaptureNames (reCaptureNames rex) <$> matchM (reRegex rex) bs instance IsRegex RE LBS.ByteString where- matchOnce = flip (?=~)- matchMany = flip (*=~)- regexSource = reSource+ matchOnce = flip (?=~)+ matchMany = flip (*=~)+ makeRegexWith = \o -> compileRegexWith o . unpackE+ makeRegex = compileRegex . unpackE+ regexSource = packE . reSource -- $tutorial -- We have a regex tutorial at <http://tutorial.regex.uk>. These API
Text/RE/TDFA/RE.hs view
@@ -42,6 +42,8 @@ , preludeSource , unpackSimpleRegexOptions , compileRegex+ , compileRegexWith+ , compileRegexWithOptions , escape , escapeREString ) where@@ -56,6 +58,8 @@ import Text.RE.Internal.PreludeMacros import Text.RE.Internal.QQ import Text.RE.TestBench+import Text.RE.Types.CaptureID+import Text.RE.Types.Options import Text.Regex.TDFA @@ -83,7 +87,7 @@ regexType :: RegexType regexType =- TDFA $ \txt env md -> txt =~ mdRegexSource regexType ExclCaptures env md+ mkTDFA $ \txt env md -> txt =~ mdRegexSource regexType ExclCaptures env md data RE = RE@@ -156,14 +160,20 @@ BlockSensitive -> (,) False True BlockInsensitive -> (,) False False -compileRegex :: ( IsOption o RE CompOption ExecOption- , Functor m- , Monad m- )- => o- -> String- -> m RE-compileRegex = compileRegex_ . makeOptions+compileRegex :: (Functor m,Monad m) => String -> m RE+compileRegex = compileRegexWithOptions ()++compileRegexWith :: (Functor m,Monad m) => SimpleRegexOptions -> String -> m RE+compileRegexWith = compileRegexWithOptions++compileRegexWithOptions :: ( IsOption o RE CompOption ExecOption+ , Functor m+ , Monad m+ )+ => o+ -> String+ -> m RE+compileRegexWithOptions = compileRegex_ . makeOptions compileRegex_ :: (Functor m,Monad m) => Options
Text/RE/TDFA/Sequence.hs view
@@ -31,6 +31,7 @@ import Data.Typeable import Text.Regex.Base import Text.RE+import Text.RE.Types.IsRegex import Text.RE.Internal.AddCaptureNames import Text.RE.TDFA.RE import qualified Text.Regex.TDFA as TDFA@@ -71,9 +72,11 @@ (=~~) bs rex = addCaptureNames (reCaptureNames rex) <$> matchM (reRegex rex) bs instance IsRegex RE (S.Seq Char) where- matchOnce = flip (?=~)- matchMany = flip (*=~)- regexSource = reSource+ matchOnce = flip (?=~)+ matchMany = flip (*=~)+ makeRegexWith = \o -> compileRegexWith o . unpackE+ makeRegex = compileRegex . unpackE+ regexSource = packE . reSource -- $tutorial -- We have a regex tutorial at <http://tutorial.regex.uk>. These API
Text/RE/TDFA/String.hs view
@@ -31,6 +31,7 @@ import Data.Typeable import Text.Regex.Base import Text.RE+import Text.RE.Types.IsRegex import Text.RE.Internal.AddCaptureNames import Text.RE.TDFA.RE import qualified Text.Regex.TDFA as TDFA@@ -71,9 +72,11 @@ (=~~) bs rex = addCaptureNames (reCaptureNames rex) <$> matchM (reRegex rex) bs instance IsRegex RE String where- matchOnce = flip (?=~)- matchMany = flip (*=~)- regexSource = reSource+ matchOnce = flip (?=~)+ matchMany = flip (*=~)+ makeRegexWith = \o -> compileRegexWith o . unpackE+ makeRegex = compileRegex . unpackE+ regexSource = packE . reSource -- $tutorial -- We have a regex tutorial at <http://tutorial.regex.uk>. These API
Text/RE/TDFA/Text.hs view
@@ -31,6 +31,7 @@ import Data.Typeable import Text.Regex.Base import Text.RE+import Text.RE.Types.IsRegex import Text.RE.Internal.AddCaptureNames import Text.RE.TDFA.RE import qualified Text.Regex.TDFA as TDFA@@ -71,9 +72,11 @@ (=~~) bs rex = addCaptureNames (reCaptureNames rex) <$> matchM (reRegex rex) bs instance IsRegex RE T.Text where- matchOnce = flip (?=~)- matchMany = flip (*=~)- regexSource = reSource+ matchOnce = flip (?=~)+ matchMany = flip (*=~)+ makeRegexWith = \o -> compileRegexWith o . unpackE+ makeRegex = compileRegex . unpackE+ regexSource = packE . reSource -- $tutorial -- We have a regex tutorial at <http://tutorial.regex.uk>. These API
Text/RE/TDFA/Text/Lazy.hs view
@@ -31,6 +31,7 @@ import Data.Typeable import Text.Regex.Base import Text.RE+import Text.RE.Types.IsRegex import Text.RE.Internal.AddCaptureNames import Text.RE.TDFA.RE import qualified Text.Regex.TDFA as TDFA@@ -71,9 +72,11 @@ (=~~) bs rex = addCaptureNames (reCaptureNames rex) <$> matchM (reRegex rex) bs instance IsRegex RE TL.Text where- matchOnce = flip (?=~)- matchMany = flip (*=~)- regexSource = reSource+ matchOnce = flip (?=~)+ matchMany = flip (*=~)+ makeRegexWith = \o -> compileRegexWith o . unpackE+ makeRegex = compileRegex . unpackE+ regexSource = packE . reSource -- $tutorial -- We have a regex tutorial at <http://tutorial.regex.uk>. These API
Text/RE/TestBench.lhs view
@@ -10,7 +10,9 @@ module Text.RE.TestBench ( MacroID(..)- , RegexType(..)+ , RegexType+ , mkTDFA+ , mkPCRE , isTDFA , isPCRE , presentRegexType@@ -43,9 +45,11 @@ import Data.String import Text.Printf import Prelude.Compat-import Text.RE.Capture-import Text.RE.Options-import Text.RE.Replace+import Text.RE.Types.Capture+import Text.RE.Types.Options+import Text.RE.Types.Match+import Text.RE.Types.Matches+import Text.RE.Types.Replace \end{code} Types@@ -70,6 +74,10 @@ isPCRE (TDFA _) = False isPCRE (PCRE _) = True++mkTDFA, mkPCRE :: TestBenchMatcher -> RegexType+mkTDFA = TDFA+mkPCRE = PCRE presentRegexType :: RegexType -> String presentRegexType (TDFA _) = "TDFA"
+ Text/RE/TestBench/Parsers.hs view
@@ -0,0 +1,166 @@+{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}+{-# LANGUAGE OverloadedStrings #-}++module Text.RE.TestBench.Parsers+ ( parseInteger+ , parseHex+ , parseDouble+ , parseString+ , parseSimpleString+ , parseDate+ , parseSlashesDate+ , parseTimeOfDay+ , parseTimeZone+ , parseDateTime+ , parseDateTime8601+ , parseDateTimeCLF+ , parseShortMonth+ , shortMonthArray+ , IPV4Address+ , parseIPv4Address+ , Severity(..)+ , parseSeverity+ , severityKeywords+ ) where++import Data.Array+import qualified Data.HashMap.Strict as HM+import Data.Maybe+import qualified Data.Text as T+import Data.Time+import qualified Data.Time.Locale.Compat as LC+import Data.Word+import Text.Printf+import Text.Read+import Text.RE.Types.Replace+++parseInteger :: Replace a => a -> Maybe Int+parseInteger = readMaybe . unpackE++parseHex :: Replace a => a -> Maybe Int+parseHex = readMaybe . ("0x"++) . unpackE++parseDouble :: Replace a => a -> Maybe Double+parseDouble = readMaybe . unpackE++parseString :: Replace a => a -> Maybe T.Text+parseString = readMaybe . unpackE++parseSimpleString :: Replace a => a -> Maybe T.Text+parseSimpleString = Just . T.dropEnd 1 . T.drop 1 . textifyE++date_templates, time_templates, timezone_templates,+ date_time_8601_templates, date_time_templates :: [String]+date_templates = ["%F"]+time_templates = ["%H:%M:%S","%H:%M:%S%Q","%H:%M"]+timezone_templates = ["Z","%z"]+date_time_8601_templates =+ [ printf "%sT%s%s" dt tm tz+ | dt <- date_templates+ , tm <- time_templates+ , tz <- timezone_templates+ ]+date_time_templates =+ [ printf "%s%c%s%s" dt sc tm tz+ | dt <- date_templates+ , sc <- ['T',' ']+ , tm <- time_templates+ , tz <- timezone_templates ++ [" UTC",""]+ ]++parseDate :: Replace a => a -> Maybe Day+parseDate = parse_time date_templates++parseSlashesDate :: Replace a => a -> Maybe Day+parseSlashesDate = parse_time ["%Y/%m/%d"]++parseTimeOfDay :: Replace a => a -> Maybe TimeOfDay+parseTimeOfDay = parse_time time_templates++parseTimeZone :: Replace a => a -> Maybe TimeZone+parseTimeZone = parse_time timezone_templates++parseDateTime :: Replace a => a -> Maybe UTCTime+parseDateTime = parse_time date_time_templates++parseDateTime8601 :: Replace a => a -> Maybe UTCTime+parseDateTime8601 = parse_time date_time_8601_templates++parseDateTimeCLF :: Replace a => a -> Maybe UTCTime+parseDateTimeCLF = parse_time ["%d/%b/%Y:%H:%M:%S %z"]++parseShortMonth :: Replace a => a -> Maybe Int+parseShortMonth = flip HM.lookup short_month_hm . unpackE++parse_time :: (ParseTime t,Replace s) => [String] -> s -> Maybe t+parse_time tpls = prs . unpackE+ where+ prs s = listToMaybe $ catMaybes+ [ parseTime LC.defaultTimeLocale fmt s+ | fmt<-tpls+ ]++short_month_hm :: HM.HashMap String Int+short_month_hm = HM.fromList [ (T.unpack $ shortMonthArray!i,i) | i<-[1..12] ]++shortMonthArray :: Array Int T.Text+shortMonthArray = listArray (1,12) $+ T.words "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"++type IPV4Address = (Word8,Word8,Word8,Word8)++parseIPv4Address :: Replace a => a -> Maybe IPV4Address+parseIPv4Address = prs . words_by (=='.') . unpackE+ where+ prs [a_s,b_s,c_s,d_s] = do+ a <- readMaybe a_s+ b <- readMaybe b_s+ c <- readMaybe c_s+ d <- readMaybe d_s+ case all is_o [a,b,c,d] of+ True -> Just (toEnum a,toEnum b,toEnum c,toEnum d)+ False -> Nothing+ prs _ = Nothing++ is_o x = 0 <= x && x <= 255++data Severity+ = Emerg+ | Alert+ | Crit+ | Err+ | Warning+ | Notice+ | Info+ | Debug+ deriving (Bounded,Enum,Ord,Eq,Show)++parseSeverity :: Replace a => a -> Maybe Severity+parseSeverity = flip HM.lookup severity_hm . textifyE++severity_hm :: HM.HashMap T.Text Severity+severity_hm = HM.fromList+ [ (kw,pri)+ | pri<-[minBound..maxBound]+ , let (kw0,kws) = severityKeywords pri+ , kw <- kw0:kws+ ]++severityKeywords :: Severity -> (T.Text,[T.Text])+severityKeywords pri = case pri of+ Emerg -> (,) "emerg" ["panic"]+ Alert -> (,) "alert" []+ Crit -> (,) "crit" []+ Err -> (,) "err" ["error"]+ Warning -> (,) "warning" ["warn"]+ Notice -> (,) "notice" []+ Info -> (,) "info" []+ Debug -> (,) "debug" []++words_by :: (Char->Bool) -> String -> [String]+words_by f s = case dropWhile f s of+ "" -> []+ s' -> w : words_by f s''+ where+ (w, s'') = break f s'
+ Text/RE/Tools/Edit.lhs view
@@ -0,0 +1,98 @@+\begin{code}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE CPP #-}+#if __GLASGOW_HASKELL__ >= 800+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}+#endif++module Text.RE.Tools.Edit+ ( LineNo+ , Edits(..)+ , Edit(..)+ , LineEdit(..)+ , applyEdits+ , applyEdit+ , applyLineEdit+ ) where++import Data.Maybe+import Prelude.Compat+import Text.RE.Types.Capture+import Text.RE.Types.Match+import Text.RE.Types.Matches+import Text.RE.Types.IsRegex+import Text.RE.Types.LineNo+import Text.RE.Types.Replace+++data Edits m re s+ = Select [(re,Edit m s)]+ | Pipe [(re,Edit m s)]++data Edit m s+ = Template s+ | Function Context (LineNo->Match s->Location->Capture s->m (Maybe s))+ | LineEdit (LineNo->Matches s->m (LineEdit s))++data LineEdit s+ = NoEdit+ | ReplaceWith s+ | Delete+ deriving (Show)++applyEdits :: (IsRegex re s,Monad m,Functor m)+ => LineNo+ -> Edits m re s+ -> s+ -> m s+applyEdits lno ez0 s0 = case ez0 of+ Select ez -> select_edit_scripts lno ez s0+ Pipe ez -> pipe_edit_scripts lno ez s0++applyEdit :: (IsRegex re s,Monad m,Functor m)+ => (s->s)+ -> LineNo+ -> re+ -> Edit m s+ -> s+ -> m (Maybe s)+applyEdit anl lno re edit s =+ case allMatches acs of+ [] -> return Nothing+ _ -> fmap Just $ case edit of+ Template tpl -> return $ anl $ replaceAll tpl acs+ Function ctx f -> anl <$> replaceAllCapturesM replaceMethods ctx (f lno) acs+ LineEdit g -> fromMaybe s' . applyLineEdit anl <$> g lno acs+ where+ s' = anl s+ acs = matchMany re s++applyLineEdit :: Monoid s => (s->s) -> LineEdit s -> Maybe s+applyLineEdit _ NoEdit = Nothing+applyLineEdit anl (ReplaceWith s) = Just $ anl s+applyLineEdit _ Delete = Just $ mempty++select_edit_scripts :: (IsRegex re s,Monad m,Functor m)+ => LineNo+ -> [(re,Edit m s)]+ -> s+ -> m s+select_edit_scripts lno ps0 s = select ps0+ where+ select [] = return $ appendNewlineE s+ select ((re,es):ps) =+ applyEdit appendNewlineE lno re es s >>= maybe (select ps) return++pipe_edit_scripts :: (IsRegex re s,Monad m,Functor m)+ => LineNo+ -> [(re,Edit m s)]+ -> s+ -> m s+pipe_edit_scripts lno ez s0 =+ appendNewlineE <$> foldr f (return s0) ez+ where+ f (re,es) act = do+ s <- act+ fromMaybe s <$> applyEdit id lno re es s+\end{code}
Text/RE/Tools/Grep.lhs view
@@ -11,14 +11,17 @@ , GrepScript , grepScript , linesMatched+ , module Text.RE+ , module Text.RE.Types.IsRegex+ , module Text.RE.Types.LineNo ) where import qualified Data.ByteString.Lazy.Char8 as LBS import Prelude.Compat import Text.Printf-import Text.RE.Capture-import Text.RE.IsRegex-import Text.RE.LineNo+import Text.RE+import Text.RE.Types.IsRegex+import Text.RE.Types.LineNo data Line =
Text/RE/Tools/Lex.lhs view
@@ -1,12 +1,16 @@ \begin{code} {-# LANGUAGE NoImplicitPrelude #-} -module Text.RE.Tools.Lex where+module Text.RE.Tools.Lex+ ( alex+ , alex'+ , module Text.RE+ , module Text.RE.Types.IsRegex+ ) where import Prelude.Compat-import Text.RE.Capture-import Text.RE.IsRegex-import Text.RE.Replace+import Text.RE+import Text.RE.Types.IsRegex alex :: IsRegex re s => [(re,Match s->Maybe t)] -> t -> s -> [t]
Text/RE/Tools/Sed.lhs view
@@ -11,13 +11,18 @@ ( SedScript , sed , sed'+ , module Text.RE+ , module Text.RE.Types.IsRegex+ , module Text.RE.Tools.Edit+ , module Text.RE.Types.LineNo ) where import qualified Data.ByteString.Lazy.Char8 as LBS import Prelude.Compat-import Text.RE.Edit-import Text.RE.LineNo-import Text.RE.IsRegex+import Text.RE+import Text.RE.Tools.Edit+import Text.RE.Types.LineNo+import Text.RE.Types.IsRegex type SedScript re = Edits IO re LBS.ByteString@@ -35,14 +40,14 @@ ] write_file o_fp $ LBS.concat lns' -sed' :: (IsRegex re LBS.ByteString,Monad m,Functor m)- => Edits m re LBS.ByteString- -> LBS.ByteString- -> m LBS.ByteString+sed' :: (IsRegex re a,Monad m,Functor m)+ => Edits m re a+ -> a+ -> m a sed' as lbs = do- LBS.concat <$> sequence+ mconcat <$> sequence [ applyEdits lno as s- | (lno,s)<-zip [firstLine..] $ LBS.lines lbs+ | (lno,s)<-zip [firstLine..] $ linesE lbs ] read_file :: FilePath -> IO LBS.ByteString
+ Text/RE/Types/Capture.lhs view
@@ -0,0 +1,61 @@+\begin{code}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE DeriveDataTypeable #-}+\end{code}++\begin{code}+module Text.RE.Types.Capture+ ( Capture(..)+ , hasCaptured+ , capturePrefix+ , captureSuffix+ ) where+\end{code}++\begin{code}+import Text.Regex.Base+\end{code}++++\begin{code}+-- | the matching of a single sub-expression against part of the source+-- text+data Capture a =+ Capture+ { captureSource :: !a -- ^ the whole text that was searched+ , capturedText :: !a -- ^ the text that was matched+ , captureOffset :: !Int -- ^ the number of characters preceding the+ -- match with -1 used if no text was captured+ -- by the RE (not even the empty string)+ , captureLength :: !Int -- ^ the number of chacter in the captured+ -- sub-string+ }+ deriving (Show,Eq)+\end{code}++\begin{code}+instance Functor Capture where+ fmap f c@Capture{..} =+ c+ { captureSource = f captureSource+ , capturedText = f capturedText+ }+\end{code}++\begin{code}+-- | test if the capture has matched any text+hasCaptured :: Capture a -> Bool+hasCaptured = (>=0) . captureOffset++-- | returns the text preceding the match+capturePrefix :: Extract a => Capture a -> a+capturePrefix Capture{..} = before captureOffset captureSource++-- | returns the text after the match+captureSuffix :: Extract a => Capture a -> a+captureSuffix Capture{..} = after (captureOffset+captureLength) captureSource+\end{code}
+ Text/RE/Types/CaptureID.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Text.RE.Types.CaptureID where++import Data.Ix+import Data.Hashable+import qualified Data.HashMap.Strict as HMS+import Data.Maybe+import qualified Data.Text as T+++-- | CaptureID identifies captures, either by number+-- (e.g., [cp|1|]) or name (e.g., [cp|foo|]).+data CaptureID+ = IsCaptureOrdinal CaptureOrdinal+ | IsCaptureName CaptureName+ deriving (Show,Ord,Eq)++-- | the dictionary for named captures stored in compiled regular+-- expressions associates+type CaptureNames = HMS.HashMap CaptureName CaptureOrdinal++-- | an empty 'CaptureNames' dictionary+noCaptureNames :: CaptureNames+noCaptureNames = HMS.empty++-- | a 'CaptureName' is just the text of the name+newtype CaptureName = CaptureName { getCaptureName :: T.Text }+ deriving (Show,Ord,Eq)++instance Hashable CaptureName where+ hashWithSalt i = hashWithSalt i . getCaptureName++-- | a 'CaptureOrdinal' is just the number of the capture, starting+-- with 0 for the whole of the text matched, then in leftmost,+-- outermost+newtype CaptureOrdinal = CaptureOrdinal { getCaptureOrdinal :: Int }+ deriving (Show,Ord,Eq,Enum,Ix,Num)++-- | look up a 'CaptureID' in the 'CaptureNames' dictionary+findCaptureID :: CaptureID -> CaptureNames -> Int+findCaptureID (IsCaptureOrdinal o) _ = getCaptureOrdinal o+findCaptureID (IsCaptureName n) hms =+ getCaptureOrdinal $ fromMaybe oops $ HMS.lookup n hms+ where+ oops = error $ unlines $+ ("lookupCaptureID: " ++ T.unpack t ++ " not found in:") :+ [ " "++T.unpack (getCaptureName nm) | nm <- HMS.keys hms ]+ t = getCaptureName n
+ Text/RE/Types/IsRegex.lhs view
@@ -0,0 +1,25 @@+\begin{code}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE CPP #-}+#if __GLASGOW_HASKELL__ >= 800+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}+#endif++module Text.RE.Types.IsRegex where++import Text.RE.Types.Match+import Text.RE.Types.Matches+import Text.RE.Types.Options+import Text.RE.Types.Replace+\end{code}+++\begin{code}+class Replace s => IsRegex re s where+ matchOnce :: re -> s -> Match s+ matchMany :: re -> s -> Matches s+ makeRegex :: (Functor m,Monad m) => s -> m re+ makeRegexWith :: (Functor m,Monad m) => SimpleRegexOptions -> s -> m re+ regexSource :: re -> s+\end{code}
+ Text/RE/Types/LineNo.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Text.RE.Types.LineNo where+++newtype LineNo =+ ZeroBasedLineNo { getZeroBasedLineNo :: Int }+ deriving (Show,Enum)+++firstLine :: LineNo+firstLine = ZeroBasedLineNo 0++getLineNo :: LineNo -> Int+getLineNo = (+1) . getZeroBasedLineNo++lineNo :: Int -> LineNo+lineNo = ZeroBasedLineNo . (\x->x-1)
+ Text/RE/Types/Match.lhs view
@@ -0,0 +1,193 @@+\begin{code}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE DeriveDataTypeable #-}+\end{code}++\begin{code}+module Text.RE.Types.Match+ ( Match(..)+ , noMatch+ , emptyMatchArray+ , matched+ , matchedText+ , matchCapture+ , matchCaptures+ , (!$$)+ , captureText+ , (!$$?)+ , captureTextMaybe+ , (!$)+ , capture+ , (!$?)+ , captureMaybe+ , convertMatchText+ ) where+\end{code}++\begin{code}+import Data.Array+import Data.Maybe+import Data.Typeable+import Text.Regex.Base+import Text.RE.Types.Capture+import Text.RE.Types.CaptureID++infixl 9 !$, !$$+\end{code}++\begin{code}+-- | the result of matching a RE to a text once, listing the text that+-- was matched and the named captures in the RE and all of the substrings+-- matched, with the text captured by the whole RE; a complete failure+-- to match will be represented with an empty array (with bounds (0,-1))+data Match a =+ Match+ { matchSource :: !a -- ^ the whole source text+ , captureNames :: !CaptureNames -- ^ the RE's capture names+ , matchArray :: !(Array CaptureOrdinal (Capture a))+ -- ^ 0..n-1 captures,+ -- starting with the+ -- text matched by the+ -- whole RE+ }+ deriving (Show,Eq,Typeable)+\end{code}++\begin{code}+-- | Construct a Match that does not match anything.+noMatch :: a -> Match a+noMatch t = Match t noCaptureNames emptyMatchArray++-- | an empty array of Capture+emptyMatchArray :: Array CaptureOrdinal (Capture a)+emptyMatchArray = listArray (CaptureOrdinal 0,CaptureOrdinal $ -1) []+\end{code}++\begin{code}+instance Functor Match where+ fmap f Match{..} =+ Match+ { matchSource = f matchSource+ , captureNames = captureNames+ , matchArray = fmap (fmap f) matchArray+ }+\end{code}++\begin{code}+-- | tests whether the RE matched the source text at all+matched :: Match a -> Bool+matched = isJust . matchCapture++-- | tests whether the RE matched the source text at all+matchedText :: Match a -> Maybe a+matchedText = fmap capturedText . matchCapture++-- | the top-level capture if the source text matched the RE,+-- Nothing otherwise+matchCapture :: Match a -> Maybe (Capture a)+matchCapture = fmap fst . matchCaptures++-- | the top-level capture and the sub captures if the text matched+-- the RE, Nothing otherwise+matchCaptures :: Match a -> Maybe (Capture a,[Capture a])+matchCaptures Match{..} = case rangeSize (bounds matchArray) == 0 of+ True -> Nothing+ False -> Just (matchArray!0,drop 1 $ elems matchArray)++-- | an alternative for captureText+(!$$) :: Match a -> CaptureID -> a+(!$$) = flip captureText++-- | look up the text of the nth capture, 0 being the match of the whole+-- RE against the source text, 1, the first bracketed sub-expression to+-- be matched and so on+captureText :: CaptureID -> Match a -> a+captureText cid mtch = capturedText $ capture cid mtch++-- | an alternative for captureTextMaybe+(!$$?) :: Match a -> CaptureID -> Maybe a+(!$$?) = flip captureTextMaybe++-- | look up the text of the nth capture (0 being the match of the+-- whole), returning Nothing if the Match doesn't contain the capture+captureTextMaybe :: CaptureID -> Match a -> Maybe a+captureTextMaybe cid mtch = do+ cap <- mtch !$? cid+ case hasCaptured cap of+ True -> Just $ capturedText cap+ False -> Nothing++-- | an alternative for capture+(!$) :: Match a -> CaptureID -> Capture a+(!$) = flip capture++-- | look up the nth capture, 0 being the match of the whole RE against+-- the source text, 1, the first bracketed sub-expression to be matched+-- and so on+capture :: CaptureID -> Match a -> Capture a+capture cid mtch = fromMaybe oops $ mtch !$? cid+ where+ oops = error $ "capture: out of bounds (" ++ show cid ++ ")"++-- | an alternative for capture captureMaybe+(!$?) :: Match a -> CaptureID -> Maybe (Capture a)+(!$?) = flip captureMaybe++-- | look up the nth capture, 0 being the match of the whole RE against+-- the source text, 1, the first bracketed sub-expression to be matched+-- and so on, returning Nothing if there is no such capture, or if the+-- capture failed to capture anything (being in a failed alternate)+captureMaybe :: CaptureID -> Match a -> Maybe (Capture a)+captureMaybe cid mtch@Match{..} = do+ cap <- case bounds matchArray `inRange` CaptureOrdinal i of+ True -> Just $ matchArray ! CaptureOrdinal i+ False -> Nothing+ case hasCaptured cap of+ True -> Just cap+ False -> Nothing+ where+ i = lookupCaptureID cid mtch++lookupCaptureID :: CaptureID -> Match a -> Int+lookupCaptureID cid Match{..} = findCaptureID cid captureNames+\end{code}+++\begin{code}+-- | for matching just the first RE against the source text+instance+ ( RegexContext regex source (AllTextSubmatches (Array Int) (source,(Int,Int)))+ , RegexLike regex source+ ) =>+ RegexContext regex source (Match source) where+ match r s = convertMatchText s $ getAllTextSubmatches $ match r s+ matchM r s = do+ y <- matchM r s+ return $ convertMatchText s $ getAllTextSubmatches y+\end{code}++\begin{code}+-- | convert a regex-base native MatchText into a regex Match type+convertMatchText :: source -> MatchText source -> Match source+convertMatchText hay arr =+ Match+ { matchSource = hay+ , captureNames = noCaptureNames+ , matchArray =+ ixmap (CaptureOrdinal lo,CaptureOrdinal hi) getCaptureOrdinal $+ fmap f arr+ }+ where+ (lo,hi) = bounds arr++ f (ndl,(off,len)) =+ Capture+ { captureSource = hay+ , capturedText = ndl+ , captureOffset = off+ , captureLength = len+ }+\end{code}
+ Text/RE/Types/Matches.lhs view
@@ -0,0 +1,81 @@+\begin{code}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE DeriveDataTypeable #-}+\end{code}++\begin{code}+module Text.RE.Types.Matches+ ( Matches(..)+ , anyMatches+ , countMatches+ , matches+ , mainCaptures+ ) where+\end{code}++\begin{code}+import Data.Typeable+import Text.Regex.Base+import Text.RE.Types.Capture+import Text.RE.Types.CaptureID+import Text.RE.Types.Match+\end{code}++++\begin{code}+-- | the result type to use when every match is needed, not just the+-- first match of the RE against the source+data Matches a =+ Matches+ { matchesSource :: !a -- ^ the source text being matched+ , allMatches :: ![Match a] -- ^ all captures found, left to right+ }+ deriving (Show,Eq,Typeable)+\end{code}++\begin{code}+instance Functor Matches where+ fmap f Matches{..} =+ Matches+ { matchesSource = f matchesSource+ , allMatches = map (fmap f) allMatches+ }+\end{code}++\begin{code}+-- | tests whether the RE matched the source text at all+anyMatches :: Matches a -> Bool+anyMatches = not . null . allMatches++-- | count the matches+countMatches :: Matches a -> Int+countMatches = length . allMatches++-- | list the Matches+matches :: Matches a -> [a]+matches = map capturedText . mainCaptures++-- | extract the main capture from each match+mainCaptures :: Matches a -> [Capture a]+mainCaptures ac = [ capture c0 cs | cs<-allMatches ac ]+ where+ c0 = IsCaptureOrdinal $ CaptureOrdinal 0+\end{code}+++\begin{code}+-- | for matching all REs against the source text+instance+ ( RegexContext regex source [MatchText source]+ , RegexLike regex source+ ) =>+ RegexContext regex source (Matches source) where+ match r s = Matches s $ map (convertMatchText s) $ match r s+ matchM r s = do+ y <- matchM r s+ return $ Matches s $ map (convertMatchText s) y+\end{code}
+ Text/RE/Types/Options.lhs view
@@ -0,0 +1,69 @@+\begin{code}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FunctionalDependencies #-}++module Text.RE.Types.Options where++import Data.Hashable+import qualified Data.HashMap.Strict as HM+import Data.String+import Language.Haskell.TH+import Language.Haskell.TH.Syntax+\end{code}++\begin{code}+data Options_ r c e =+ Options+ { optionsMacs :: !(Macros r)+ , optionsComp :: !c+ , optionsExec :: !e+ }+ deriving (Show)+\end{code}++\begin{code}+class IsOption o r c e |+ e -> r, c -> e , e -> c, r -> c, c -> r, r -> e where+ makeOptions :: o -> Options_ r c e+\end{code}++\begin{code}+newtype MacroID =+ MacroID { getMacroID :: String }+ deriving (IsString,Ord,Eq,Show)+\end{code}++\begin{code}+instance Hashable MacroID where+ hashWithSalt i = hashWithSalt i . getMacroID+\end{code}++\begin{code}+type Macros r = HM.HashMap MacroID r+\end{code}++\begin{code}+emptyMacros :: Macros r+emptyMacros = HM.empty+\end{code}++\begin{code}+data SimpleRegexOptions+ = MultilineSensitive+ | MultilineInsensitive+ | BlockSensitive+ | BlockInsensitive+ deriving (Bounded,Enum,Eq,Ord,Show)+\end{code}++\begin{code}+instance Lift SimpleRegexOptions where+ lift sro = case sro of+ MultilineSensitive -> conE 'MultilineSensitive+ MultilineInsensitive -> conE 'MultilineInsensitive+ BlockSensitive -> conE 'BlockSensitive+ BlockInsensitive -> conE 'BlockInsensitive+\end{code}
+ Text/RE/Types/Replace.lhs view
@@ -0,0 +1,471 @@+\begin{code}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}++module Text.RE.Types.Replace+ ( Replace(..)+ , ReplaceMethods(..)+ , replaceMethods+ , Context(..)+ , Location(..)+ , isTopLocation+ , replace+ , replaceAll+ , replaceAllCaptures+ , replaceAllCaptures_+ , replaceAllCapturesM+ , replaceCaptures+ , replaceCaptures_+ , replaceCapturesM+ , expandMacros+ , expandMacros'+ ) 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 Data.Monoid+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.Heredoc+import Text.RE.Types.Capture+import Text.RE.Types.CaptureID+import Text.RE.Types.Match+import Text.RE.Types.Matches+import Text.RE.Types.Options+import Text.Read+import Text.Regex.TDFA+import Text.Regex.TDFA.Text()+import Text.Regex.TDFA.Text.Lazy()+\end{code}++\begin{code}+-- | Replace provides the missing methods needed to replace the matched+-- text; lengthE is the minimum implementation+class (Show a,Eq a,Ord a,Extract a,Monoid a) => Replace a where+ -- | length function for a+ lengthE :: a -> Int+ -- | inject String into a+ packE :: String -> a+ -- | project a onto a String+ unpackE :: a -> String+ -- | inject into Text+ textifyE :: a -> T.Text+ -- | project Text onto a+ detextifyE :: T.Text -> a+ -- | split into lines+ linesE :: a -> [a]+ -- | concatenate a list of lines+ unlinesE :: [a] -> a+ -- | append a newline+ appendNewlineE :: a -> a+ -- | apply a substitution function to a Capture+ substE :: (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+ parseTemplateE :: a -> Match a -> Location -> Capture a -> Maybe a++ textifyE = T.pack . unpackE+ detextifyE = packE . T.unpack+ appendNewlineE = (<> packE "\n")++ substE f m@Capture{..} =+ capturePrefix m <> f capturedText <> captureSuffix m+\end{code}++\begin{code}+-- | a selction of the Replace methods can be encapsulated with ReplaceMethods+-- for the higher-order replacement functions+data ReplaceMethods a =+ ReplaceMethods+ { methodLength :: a -> Int+ , methodSubst :: (a->a) -> Capture a -> a+ }++-- | replaceMethods encapsulates ReplaceMethods a from a Replace a context+replaceMethods :: Replace a => ReplaceMethods a+replaceMethods =+ ReplaceMethods+ { methodLength = lengthE+ , methodSubst = substE+ }+\end{code}++\begin{code}+-- | @Context@ specifies which contexts the substitutions should be applied+data Context+ = 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 (Show)++-- | the @Location@ information passed into the substitution function+-- specifies which sub-expression is being substituted+data Location =+ Location+ { locationMatch :: Int+ -- ^ the zero-based, i-th string to be matched,+ -- when matching all strings, zero when only the+ -- first string is being matched+ , 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 (Show)+\end{code}++\begin{code}+-- | True iff the location references a complete match+-- (i.e., not a bracketed capture)+isTopLocation :: Location -> Bool+isTopLocation = (==0) . 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 tpl ac = replaceAllCaptures TOP (parseTemplateE tpl) 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+ => Context+ -> (Match a->Location->Capture a->Maybe a)+ -> Matches a+ -> a+\end{code}++\begin{code}+replaceAllCaptures = replaceAllCaptures_ replaceMethods+\end{code}++\begin{code}+-- | replaceAllCaptures_ is like like replaceAllCaptures but takes the+-- Replace methods through the ReplaceMethods argument+replaceAllCaptures_ :: Extract a+ => ReplaceMethods a+ -> Context+ -> (Match a->Location->Capture a->Maybe a)+ -> Matches a+ -> a+replaceAllCaptures_ s ctx phi ac =+ runIdentity $ replaceAllCapturesM s ctx (lift_phi phi) ac+\end{code}++\begin{code}+-- | replaceAllCapturesM is just a monadically generalised version of+-- replaceAllCaptures_+replaceAllCapturesM :: (Extract a,Monad m)+ => ReplaceMethods a+ -> Context+ -> (Match a->Location->Capture a->m (Maybe a))+ -> Matches a+ -> m a+replaceAllCapturesM r ctx phi_ Matches{..} =+ replaceCapturesM r ALL phi $ Match matchesSource cnms arr+ where+ phi _ (Location _ i) = case arr_c!i of+ Just caps -> phi_ caps . uncurry Location $ arr_i ! i+ Nothing -> const $ return Nothing++ arr_c = listArray bds $+ concat $+ [ repl (rangeSize $ bounds $ matchArray cs) cs+ | cs <- allMatches+ ]++ arr_i = listArray bds j_ks++ arr = listArray bds $+ [ arr_ ! k+ | arr_ <- map matchArray allMatches+ , k <- indices arr_+ ]++ bds = (0,CaptureOrdinal $ length j_ks-1)++ j_ks =+ [ (j,k)+ | (j,arr_) <- zip [0..] $ map matchArray allMatches+ , k <- indices arr_+ ]++ repl 0 _ = []+ repl n x = case ctx of+ TOP -> Just x : replicate (n-1) Nothing+ SUB -> Nothing : replicate (n-1) (Just x)+ ALL -> replicate n $ Just x++ cnms = fromMaybe noCaptureNames $ listToMaybe $ map captureNames allMatches+\end{code}++\begin{code}+-- | replace with a template containing $0 for whole text,+-- $1 for first capture, etc.+replace :: Replace a+ => Match a+ -> a+ -> a+replace c tpl = replaceCaptures TOP (parseTemplateE tpl) 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+ => Context+ -> (Match a->Location->Capture a->Maybe a)+ -> Match a+ -> a+replaceCaptures = replaceCaptures_ replaceMethods+\end{code}++\begin{code}+-- | replaceCaptures_ is like replaceCaptures but takes the Replace methods+-- through the ReplaceMethods argument+replaceCaptures_ :: Extract a+ => ReplaceMethods a+ -> Context+ -> (Match a->Location->Capture a->Maybe a)+ -> Match a+ -> a+replaceCaptures_ s ctx phi caps =+ runIdentity $ replaceCapturesM s ctx (lift_phi phi) caps+\end{code}++\begin{code}+-- | replaceCapturesM is just a monadically generalised version of+-- replaceCaptures_+replaceCapturesM :: (Monad m,Extract a)+ => ReplaceMethods a+ -> Context+ -> (Match a->Location->Capture a->m (Maybe a))+ -> Match a+ -> m a+replaceCapturesM ReplaceMethods{..} ctx phi_ caps@Match{..} = do+ (hay',_) <- foldr sc (return (matchSource,[])) $+ zip [0..] $ elems matchArray+ return hay'+ where+ sc (i,cap0) act = do+ (hay,ds) <- act+ let ndl = capturedText cap+ cap = adj hay ds cap0+ mb <- phi i cap+ case mb of+ Nothing -> return (hay,ds)+ Just ndl' ->+ return+ ( methodSubst (const ndl') cap+ , (captureOffset cap,len'-len) : ds+ )+ where+ len' = methodLength ndl'+ len = methodLength ndl++ adj hay ds cap =+ Capture+ { captureSource = hay+ , capturedText = before len $ after off0 hay+ , captureOffset = off0+ , captureLength = len+ }+ where+ len = len0 + sum+ [ delta+ | (off,delta) <- ds+ , off < off0 + len0+ ]+ len0 = captureLength cap+ off0 = captureOffset cap++ phi i cap = case ctx of+ TOP | i/=0 -> return Nothing+ SUB | i==0 ->return Nothing+ _ ->+ case not $ hasCaptured cap of+ True -> return Nothing+ False -> phi_ caps (Location 0 i) cap+\end{code}++\begin{code}+-- the Replace instances++instance Replace [Char] where+ lengthE = length+ packE = id+ unpackE = id+ textifyE = T.pack+ detextifyE = T.unpack+ linesE = lines+ unlinesE = unlines+ appendNewlineE = (<>"\n")+ parseTemplateE = parseTemplateE' id++instance Replace B.ByteString where+ lengthE = B.length+ packE = B.pack+ unpackE = B.unpack+ textifyE = TE.decodeUtf8+ detextifyE = TE.encodeUtf8+ linesE = B.lines+ unlinesE = B.unlines+ appendNewlineE = (<>"\n")+ parseTemplateE = parseTemplateE' B.unpack++instance Replace LBS.ByteString where+ lengthE = fromEnum . LBS.length+ packE = LBS.pack+ unpackE = LBS.unpack+ textifyE = TE.decodeUtf8 . LBS.toStrict+ linesE = LBS.lines+ unlinesE = LBS.unlines+ detextifyE = LBS.fromStrict . TE.encodeUtf8+ appendNewlineE = (<>"\n")+ parseTemplateE = parseTemplateE' LBS.unpack++instance Replace (S.Seq Char) where+ lengthE = S.length+ packE = S.fromList+ unpackE = F.toList+ linesE = map packE . lines . unpackE+ unlinesE = packE . unlines . map unpackE+ parseTemplateE = parseTemplateE' F.toList++instance Replace T.Text where+ lengthE = T.length+ packE = T.pack+ unpackE = T.unpack+ textifyE = id+ detextifyE = id+ linesE = T.lines+ unlinesE = T.unlines+ appendNewlineE = (<>"\n")+ parseTemplateE = parseTemplateE' T.unpack++instance Replace LT.Text where+ lengthE = fromEnum . LT.length+ packE = LT.pack+ unpackE = LT.unpack+ textifyE = LT.toStrict+ detextifyE = LT.fromStrict+ linesE = LT.lines+ unlinesE = LT.unlines+ appendNewlineE = (<>"\n")+ parseTemplateE = parseTemplateE' LT.unpack+\end{code}++\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 x_src hm s =+ case HM.null hm of+ True -> s+ False -> expandMacros' (fmap x_src . flip HM.lookup hm) s+\end{code}++\begin{code}+-- | expand the @{..} macos in the argument string using the given+-- function+expandMacros' :: (MacroID->Maybe String) -> String -> String+expandMacros' lu = fixpoint e_m+ where+ e_m re_s = replaceAllCaptures TOP phi $ re_s $=~ [here|@(@|\{([^{}]+)\})|]+ where+ phi mtch _ cap = case txt == "@@" of+ True -> Just "@"+ False -> Just $ fromMaybe txt $ lu ide+ where+ txt = capturedText cap+ ide = MacroID $ capturedText $ capture c2 mtch+ c2 = IsCaptureOrdinal $ CaptureOrdinal 2+\end{code}++\begin{code}+lift_phi :: Monad m+ => (Match a->Location->Capture a->Maybe a)+ -> (Match a->Location->Capture a->m (Maybe a))+lift_phi phi_ = phi+ where+ phi caps' loc' cap' = return $ phi_ caps' loc' cap'+\end{code}++\begin{code}+parseTemplateE' :: ( Replace a+ , RegexContext Regex a (Matches a)+ , RegexMaker Regex CompOption ExecOption String+ )+ => (a->String)+ -> a+ -> Match a+ -> Location+ -> Capture a+ -> Maybe a+parseTemplateE' unpack tpl mtch _ _ =+ Just $ replaceAllCaptures TOP phi $+ tpl $=~ [here|\$(\$|[0-9]|\{([^{}]+)\})|]+ where+ phi t_mtch _ _ = case t_mtch !$? c2 of+ Just cap -> case readMaybe stg of+ Nothing -> this $ IsCaptureName $ CaptureName $ T.pack stg+ Just cn -> this $ IsCaptureOrdinal $ CaptureOrdinal cn+ where+ stg = unpack $ capturedText cap+ Nothing -> case s == "$" of+ True -> Just t+ False -> this $ IsCaptureOrdinal $ CaptureOrdinal $ read s+ where+ s = unpack t+ t = capturedText $ capture c1 t_mtch++ this cid = capturedText <$> mtch !$? cid++ c1 = IsCaptureOrdinal $ CaptureOrdinal 1+ c2 = IsCaptureOrdinal $ CaptureOrdinal 2+\end{code}++\begin{code}+fixpoint :: (Eq a) => (a->a) -> a -> a+fixpoint f = chk . iterate f+ where+ chk (x:x':_) | x==x' = x+ chk xs = chk $ tail xs+\end{code}++\begin{code}+($=~) :: ( RegexContext Regex source target+ , RegexMaker Regex CompOption ExecOption String+ )+ => source -> String -> target+($=~) = (=~)++\end{code}
changelog view
@@ -1,5 +1,12 @@ -*-change-log-*- +0.7.0.0 Chris Dornan <chris.dornan@irisconnect.co.uk> 2017-03-15+ * Fix and extend Replace class (#74)+ * Better package organisation (#73)+ * Generalise sed' in progress (#72)+ * compileRegex to take just a string (#68)+ * Fix comment reference in Text.RE.PCRE in progress (#66)+ 0.6.0.1 Chris Dornan <chris.dornan@irisconnect.co.uk> 2017-03-13 * Fix .travis.yml release-stack script (#67)
regex.cabal view
@@ -1,5 +1,5 @@ Name: regex-Version: 0.6.0.1+Version: 0.7.0.0 Synopsis: Toolkit for regex-base Description: A Regular Expression Toolkit for regex-base with Compile-time checking of RE syntax, data types for@@ -31,7 +31,7 @@ Source-Repository this Type: git Location: https://github.com/iconnect/regex.git- Tag: 0.6.0.1+ Tag: 0.7.0.0 @@ -40,19 +40,13 @@ Hs-Source-Dirs: . Exposed-Modules: Text.RE- Text.RE.Capture- Text.RE.CaptureID- Text.RE.Edit Text.RE.Internal.AddCaptureNames Text.RE.Internal.EscapeREString Text.RE.Internal.NamedCaptures Text.RE.Internal.PreludeMacros Text.RE.Internal.QQ- Text.RE.IsRegex- Text.RE.LineNo- Text.RE.Options- Text.RE.Parsers- Text.RE.Replace+ Text.RE.Types.IsRegex+ Text.RE.Types.Replace Text.RE.TDFA Text.RE.TDFA.ByteString Text.RE.TDFA.ByteString.Lazy@@ -62,9 +56,17 @@ Text.RE.TDFA.Text Text.RE.TDFA.Text.Lazy Text.RE.TestBench+ Text.RE.TestBench.Parsers+ Text.RE.Tools.Edit Text.RE.Tools.Grep Text.RE.Tools.Lex Text.RE.Tools.Sed+ Text.RE.Types.Capture+ Text.RE.Types.CaptureID+ Text.RE.Types.LineNo+ Text.RE.Types.Match+ Text.RE.Types.Matches+ Text.RE.Types.Options Default-Language: Haskell2010 GHC-Options: