@@ -33,6 +33,7 @@
34module Hakyll.Core.Identifier.Pattern
34module Hakyll.Core.Identifier.Pattern
36 , parseGlob
37 , parseGlob
37 , predicate
38 , predicate
@@ -64,21 +65,27 @@ data GlobComponent = Capture
65-- | Type that allows matching on identifiers
66-- | Type that allows matching on identifiers
67−data Pattern = Glob [GlobComponent]
68+data Pattern a = Glob [GlobComponent]
68− | Predicate (Identifier -> Bool)
69+ | Predicate (Identifier -> Bool)
70−instance IsString Pattern where
72+instance IsString (Pattern a) where
71 fromString = parseGlob
73 fromString = parseGlob
73−instance Monoid Pattern where
75+instance Monoid (Pattern a) where
74 mempty = Predicate (const True)
76 mempty = Predicate (const True)
75− g@(Glob _) `mappend` x = Predicate (matches g) `mappend` x
77+ p1 `mappend` p2 = Predicate $ \i -> matches p1 i && matches p2 i
76− x `mappend` g@(Glob _) = x `mappend` Predicate (matches g)
78+
77− Predicate f `mappend` Predicate g = Predicate $ \i -> f i && g i
79+-- | Discard the phantom type parameter
81+castPattern :: Pattern a -> Pattern b
82+castPattern (Glob g) = Glob g
83+castPattern (Predicate p) = Predicate p
84+castPattern (List l) = List l
79-- | Parse a pattern from a string
86-- | Parse a pattern from a string
81−parseGlob :: String -> Pattern
88+parseGlob :: String -> Pattern a
82parseGlob = Glob . parse'
89parseGlob = Glob . parse'
84 parse' str =
91 parse' str =
@@ -95,7 +102,7 @@ parseGlob = Glob . parse'
96-- > predicate (\i -> matches "foo/*" i && not (matches "foo/bar" i))
103-- > predicate (\i -> matches "foo/*" i && not (matches "foo/bar" i))
98−predicate :: (Identifier -> Bool) -> Pattern
105+predicate :: (Identifier -> Bool) -> Pattern a
99predicate = Predicate
106predicate = Predicate
101-- | Create a 'Pattern' from a regex
108-- | Create a 'Pattern' from a regex
@@ -104,24 +111,25 @@ predicate = Predicate
105-- > regex "^foo/[^x]*$
112-- > regex "^foo/[^x]*$
107−regex :: String -> Pattern
114+regex :: String -> Pattern a
108regex str = predicate $ fromMaybe False . (=~~ str) . toFilePath
115regex str = predicate $ fromMaybe False . (=~~ str) . toFilePath
110-- | Create a 'Pattern' which matches if the identifier is in a certain group
117-- | Create a 'Pattern' which matches if the identifier is in a certain group
111-- (or in no group)
118-- (or in no group)
113−inGroup :: Maybe String -> Pattern
120+inGroup :: Maybe String -> Pattern a
114inGroup group = predicate $ (== group) . identifierGroup
121inGroup group = predicate $ (== group) . identifierGroup
116-- | Check if an identifier matches a pattern
123-- | Check if an identifier matches a pattern
118−matches :: Pattern -> Identifier -> Bool
125+matches :: Pattern a -> Identifier -> Bool
119matches (Glob p) = isJust . capture (Glob p)
126matches (Glob p) = isJust . capture (Glob p)
120matches (Predicate p) = (p $)
127matches (Predicate p) = (p $)
128+matches (List l) = (`elem` l)
122-- | Given a list of identifiers, retain only those who match the given pattern
130-- | Given a list of identifiers, retain only those who match the given pattern
124−filterMatches :: Pattern -> [Identifier] -> [Identifier]
132+filterMatches :: Pattern a -> [Identifier] -> [Identifier]
125filterMatches = filter . matches
133filterMatches = filter . matches
127-- | Split a list at every possible point, generate a list of (init, tail)
135-- | Split a list at every possible point, generate a list of (init, tail)
@@ -132,9 +140,9 @@ splits = inits &&& tails >>> uncurry zip >>> reverse
133-- | Match a glob against a pattern, generating a list of captures
141-- | Match a glob against a pattern, generating a list of captures
135−capture :: Pattern -> Identifier -> Maybe [String]
143+capture :: Pattern a -> Identifier -> Maybe [String]
136capture (Glob p) (Identifier _ i) = capture' p i
144capture (Glob p) (Identifier _ i) = capture' p i
137−capture (Predicate _) _ = Nothing
145+capture _ _ = Nothing
139-- | Internal verion of 'capture'
147-- | Internal verion of 'capture'
@@ -164,17 +172,17 @@ capture' (CaptureMany : ms) str =
165-- > "tags/foo"
173-- > "tags/foo"
167−fromCapture :: Pattern -> String -> Identifier
175+fromCapture :: Pattern a -> String -> Identifier
168fromCapture pattern = fromCaptures pattern . repeat
176fromCapture pattern = fromCaptures pattern . repeat
170-- | Create an identifier from a pattern by filling in the captures with the
178-- | Create an identifier from a pattern by filling in the captures with the
171-- given list of strings
179-- given list of strings
173−fromCaptures :: Pattern -> [String] -> Identifier
181+fromCaptures :: Pattern a -> [String] -> Identifier
174−fromCaptures (Glob p) = Identifier Nothing . fromCaptures' p
182+fromCaptures (Glob p) = Identifier Nothing . fromCaptures' p
175−fromCaptures (Predicate _) = error $
183+fromCaptures _ = error $
176− "Hakyll.Core.Identifier.Pattern.fromCaptures: fromCaptures called on a " ++
184+ "Hakyll.Core.Identifier.Pattern.fromCaptures: fromCaptures only works " ++
177− "predicate instead of a glob"
185+ "on simple globs!"
179-- | Internally used version of 'fromCaptures'
187-- | Internally used version of 'fromCaptures'