@@ -37,13 +37,13 @@ module Hakyll.Core.Identifier.Pattern
37 , fromList
37 , fromList
38 , fromRegex
38 , fromRegex
39 , fromVersion
39 , fromVersion
41− -- * Manipulating patterns
43+ -- * Composing patterns
44 , complement
46 , complement
48 -- * Applying patterns
48 -- * Applying patterns
@@ -105,7 +105,6 @@ data Pattern
105 = Everything
105 = Everything
106 | Complement Pattern
106 | Complement Pattern
107 | And Pattern Pattern
107 | And Pattern Pattern
108− | Or Pattern Pattern
109 | Glob [GlobComponent]
108 | Glob [GlobComponent]
110 | List (Set Identifier)
109 | List (Set Identifier)
111 | Regex String
110 | Regex String
@@ -118,20 +117,18 @@ instance Binary Pattern where
118 put Everything = putWord8 0
117 put Everything = putWord8 0
119 put (Complement p) = putWord8 1 >> put p
118 put (Complement p) = putWord8 1 >> put p
120 put (And x y) = putWord8 2 >> put x >> put y
119 put (And x y) = putWord8 2 >> put x >> put y
121− put (Or x y) = putWord8 3 >> put x >> put y
120+ put (Glob g) = putWord8 3 >> put g
122− put (Glob g) = putWord8 4 >> put g
123− put (List is) = putWord8 5 >> put is
121+ put (List is) = putWord8 4 >> put is
124− put (Regex r) = putWord8 6 >> put r
122+ put (Regex r) = putWord8 5 >> put r
125− put (Version v) = putWord8 7 >> put v
123+ put (Version v) = putWord8 6 >> put v
127 get = getWord8 >>= \t -> case t of
125 get = getWord8 >>= \t -> case t of
128 0 -> pure Everything
126 0 -> pure Everything
129 1 -> Complement <$> get
127 1 -> Complement <$> get
130 2 -> And <$> get <*> get
128 2 -> And <$> get <*> get
131− 3 -> Or <$> get <*> get
132− 4 -> Glob <$> get
129+ 3 -> Glob <$> get
133− 5 -> List <$> get
130+ 4 -> List <$> get
134− 6 -> Regex <$> get
131+ 5 -> Regex <$> get
135 _ -> Version <$> get
132 _ -> Version <$> get
@@ -146,19 +143,6 @@ instance Monoid Pattern where
146 mappend = (.&&.)
143 mappend = (.&&.)
149−--------------------------------------------------------------------------------
150−-- | This is necessary for good 'isLiteral' results
151−optimize :: Pattern -> Pattern
152−optimize (Complement x) = Complement (optimize x)
153−optimize (And x Everything) = x
154−optimize (And Everything y) = y
155−optimize (And x y) = And (optimize x) (optimize y)
156−optimize (Or _ Everything) = Everything
157−optimize (Or Everything _) = Everything
158−optimize (Or x y) = Or (optimize x) (optimize y)
162--------------------------------------------------------------------------------
146--------------------------------------------------------------------------------
163-- | Parse a pattern from a string
147-- | Parse a pattern from a string
164fromGlob :: String -> Pattern
148fromGlob :: String -> Pattern
@@ -174,7 +158,24 @@ fromGlob = Glob . parse'
176--------------------------------------------------------------------------------
160--------------------------------------------------------------------------------
177−-- | Create a 'Pattern' from a list of 'Identifier's it should match
161+-- | Create a 'Pattern' from a list of 'Identifier's it should match.
163+-- /Warning/: use this carefully with 'hasNoVersion' and 'hasVersion'. The
164+-- 'Identifier's in the list /already/ have versions assigned, and the pattern
165+-- will then only match the intersection of both versions.
167+-- A more concrete example,
169+-- > fromList ["foo.markdown"] .&&. hasVersion "pdf"
171+-- will not match anything! The @"foo.markdown"@ 'Identifier' has no version
172+-- assigned, so the LHS of '.&&.' will only match this 'Identifier' with no
173+-- version. The RHS only matches 'Identifier's with version set to @"pdf"@ --
174+-- hence, this pattern matches nothing.
176+-- The correct way to use this is:
178+-- > fromList (map (setVersion "pdf") ["foo.markdown"])
178fromList :: [Identifier] -> Pattern
179fromList :: [Identifier] -> Pattern
179fromList = List . S.fromList
180fromList = List . S.fromList
@@ -195,17 +196,33 @@ fromVersion :: Maybe String -> Pattern
195fromVersion = Version
196fromVersion = Version
199+--------------------------------------------------------------------------------
200+-- | Specify a version, e.g.
202+-- > "foo/*.markdown" .&&. hasVersion "pdf"
203+hasVersion :: String -> Pattern
204+hasVersion = fromVersion . Just
207+--------------------------------------------------------------------------------
208+-- | Match only if the identifier has no version set, e.g.
210+-- > "foo/*.markdown" .&&. hasNoVersion
211+hasNoVersion :: Pattern
212+hasNoVersion = fromVersion Nothing
198--------------------------------------------------------------------------------
215--------------------------------------------------------------------------------
199-- | '&&' for patterns: the given identifier must match both subterms
216-- | '&&' for patterns: the given identifier must match both subterms
200(.&&.) :: Pattern -> Pattern -> Pattern
217(.&&.) :: Pattern -> Pattern -> Pattern
201−x .&&. y = optimize (And x y)
218+x .&&. y = And x y
202infixr 3 .&&.
219infixr 3 .&&.
205--------------------------------------------------------------------------------
222--------------------------------------------------------------------------------
206-- | '||' for patterns: the given identifier must match any subterm
223-- | '||' for patterns: the given identifier must match any subterm
207(.||.) :: Pattern -> Pattern -> Pattern
224(.||.) :: Pattern -> Pattern -> Pattern
208−x .||. y = optimize (Or x y)
225+x .||. y = complement (complement x `And` complement y) -- De Morgan's law
209infixr 2 .||.
226infixr 2 .||.
@@ -219,27 +236,12 @@ complement :: Pattern -> Pattern
219complement = Complement
236complement = Complement
222−--------------------------------------------------------------------------------
223−-- | Specify a version, e.g.
225−-- > "foo/*.markdown" `withVersion` "pdf"
226−withVersion :: Pattern -> String -> Pattern
227−withVersion p v = optimize $ And p $ fromVersion $ Just v
230−--------------------------------------------------------------------------------
231−-- | Match only if the identifier has no version set
232−noVersion :: Pattern -> Pattern
233−noVersion p = optimize $ And p $ fromVersion Nothing
236--------------------------------------------------------------------------------
239--------------------------------------------------------------------------------
237-- | Check if an identifier matches a pattern
240-- | Check if an identifier matches a pattern
238matches :: Pattern -> Identifier -> Bool
241matches :: Pattern -> Identifier -> Bool
239matches Everything _ = True
242matches Everything _ = True
240matches (Complement p) i = not $ matches p i
243matches (Complement p) i = not $ matches p i
241matches (And x y) i = matches x i && matches y i
244matches (And x y) i = matches x i && matches y i
242−matches (Or x y) i = matches x i || matches y i
243matches (Glob p) i = isJust $ capture (Glob p) i
245matches (Glob p) i = isJust $ capture (Glob p) i
244matches (List l) i = i `S.member` l
246matches (List l) i = i `S.member` l
245matches (Regex r) i = toFilePath i =~ r
247matches (Regex r) i = toFilePath i =~ r