1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
-- | A module that exports a simple regex interface. This code is mostly copied
-- from the regex-compat package at hackage. I decided to write this module
-- because I want to abstract the regex package used.
module Text.Hakyll.Regex
( splitRegex
, substituteRegex
, matchesRegex
) where
import Text.Regex.TDFA
-- | Match a regular expression against a string, returning more information
-- about the match.
matchRegexAll :: Regex -> String -> Maybe (String, String, String, [String])
matchRegexAll = matchM
-- | Replaces every occurance of the given regexp with the replacement string.
subRegex :: Regex -- ^ Search pattern
-> String -- ^ Input string
-> String -- ^ Replacement text
-> String -- ^ Output string
subRegex _ "" _ = ""
subRegex regexp inp replacement =
let -- bre matches a backslash then capture either a backslash or some digits
bre = makeRegex "\\\\(\\\\|[0-9]+)"
lookup' _ [] _ = []
lookup' [] _ _ = []
lookup' match' repl groups =
case matchRegexAll bre repl of
Nothing -> repl
Just (lead, _, trail, bgroups) ->
let newval =
if head bgroups == "\\"
then "\\"
else let index :: Int
index = read (head bgroups) - 1
in if index == -1
then match'
else groups !! index
in lead ++ newval ++ lookup' match' trail groups
in case matchRegexAll regexp inp of
Nothing -> inp
Just (lead, match', trail, groups) ->
lead ++ lookup' match' replacement groups
++ subRegex regexp trail replacement
-- | Splits a string based on a regular expression. The regular expression
-- should identify one delimiter.
splitRegex' :: Regex -> String -> [String]
splitRegex' _ [] = []
splitRegex' delim strIn = loop strIn where
loop str = case matchOnceText delim str of
Nothing -> [str]
Just (firstline, _, remainder) ->
if null remainder
then [firstline,""]
else firstline : loop remainder
-- | Split a list at a certain element.
splitRegex :: String -> String -> [String]
splitRegex pattern = filter (not . null)
. splitRegex' (makeRegex pattern)
-- | Substitute a regex. Simplified interface. This function performs a global
-- substitution.
substituteRegex :: String -- ^ Pattern to replace (regex).
-> String -- ^ Replacement string.
-> String -- ^ Input string.
-> String -- ^ Result.
substituteRegex pattern replacement string =
subRegex (makeRegex pattern) string replacement
-- | Simple regex matching.
matchesRegex :: String -- ^ Input string.
-> String -- ^ Pattern to match.
-> Bool
matchesRegex = (=~)
|