-- | Module providing pattern matching and capturing on 'Identifier's.---- A very simple pattern could be, for example, @foo\/bar@. This pattern will-- only match the exact @foo\/bar@ identifier.---- To match more than one identifier, there are different captures that one can-- use:---- * @*@: matches exactly one element of an identifier;---- * @**@: matches one or more elements of an identifier.---- Some examples:---- * @foo\/*@ will match @foo\/bar@ and @foo\/foo@, but not @foo\/bar\/qux@ nor-- @foo@;---- * @**@ will match any non-empty identifier;---- * @foo\/**@ will match @foo\/bar@ and @foo\/bar\/qux@, but not @bar\/foo@ nor-- @foo@;---- A small warning: patterns are not globs. Using @foo\/*.markdown@ will not do-- what you probably intended, as it will only match the file which is literally-- called @foo\/*.markdown@. Remember that these captures only work on elements-- of identifiers as a whole; not on parts of these elements.---- Furthermore, the 'match' function allows the user to get access to the-- elements captured by the capture elements in the pattern.--moduleHakyll.Core.Identifier.Pattern(Pattern,parsePattern,match,doesMatch,matches,fromCapture,fromCaptureString,fromCaptures)whereimportData.List(intercalate)importControl.Monad(msum)importData.Maybe(isJust)importData.Monoid(mempty,mappend)importGHC.Exts(IsString,fromString)importHakyll.Core.Identifier-- | One base element of a pattern--dataPatternComponent=CaptureOne|CaptureMany|LiteralStringderiving(Eq)instanceShowPatternComponentwhereshowCaptureOne="*"showCaptureMany="**"show(Literals)=s-- | Type that allows matching on identifiers--newtypePattern=Pattern{unPattern::[PatternComponent]}deriving(Eq)instanceShowPatternwhereshow=intercalate"/".mapshow.unPatterninstanceIsStringPatternwherefromString=parsePattern-- | Parse a pattern from a string--parsePattern::String->PatternparsePattern=Pattern.maptoPattern.unIdentifier.parseIdentifierwheretoPatternx|x=="*"=CaptureOne|x=="**"=CaptureMany|otherwise=Literalx-- | Match an identifier against a pattern, generating a list of captures--match::Pattern->Identifier->Maybe[Identifier]match(Patternp)(Identifieri)=fmap(mapIdentifier)$match'pi-- | Check if an identifier matches a pattern--doesMatch::Pattern->Identifier->BooldoesMatchp=isJust.matchp-- | Given a list of identifiers, retain only those who match the given pattern--matches::Pattern->[Identifier]->[Identifier]matchesp=filter(doesMatchp)-- | Split a list at every possible point, generate a list of (init, tail) cases--splits::[a]->[([a],[a])]splitsls=reverse$splits'[]lswheresplits'lxly=(lx,ly):caselyof[]->[](y:ys)->splits'(lx++[y])ys-- | Internal verion of 'match'--match'::[PatternComponent]->[String]->Maybe[[String]]match'[][]=Just[]-- An empty matchmatch'[]_=Nothing-- No matchmatch'_[]=Nothing-- No matchmatch'(m:ms)(s:ss)=casemof-- Take one string and one literal, fail on mismatchLiterall->ifs==lthenmatch'mssselseNothing-- Take one string and one captureCaptureOne->fmap([s]:)$match'msss-- Take one string, and one or many capturesCaptureMany->lettake'(i,t)=fmap(i:)$match'mstinmsum$maptake'$splits(s:ss)-- | Create an identifier from a pattern by filling in the captures with a given-- string---- Example:---- > fromCapture (parsePattern "tags/*") (parseIdentifier "foo")---- Result:---- > "tags/foo"--fromCapture::Pattern->Identifier->IdentifierfromCapturepattern=fromCapturespattern.repeat-- | Simplified version of 'fromCapture' which takes a 'String' instead of an-- 'Identifier'---- > fromCaptureString (parsePattern "tags/*") "foo"---- Result:---- > "tags/foo"--fromCaptureString::Pattern->String->IdentifierfromCaptureStringpattern=fromCapturepattern.parseIdentifier-- | Create an identifier from a pattern by filling in the captures with the-- given list of strings--fromCaptures::Pattern->[Identifier]->IdentifierfromCaptures(Pattern[])_=memptyfromCaptures(Pattern(m:ms))[]=casemofLiterall->Identifier[l]`mappend`fromCaptures(Patternms)[]_->error$"Hakyll.Core.Identifier.Pattern.fromCaptures: "++"identifier list exhausted"fromCaptures(Pattern(m:ms))ids@(i:is)=casemofLiterall->Identifier[l]`mappend`fromCaptures(Patternms)ids_->i`mappend`fromCaptures(Patternms)is