1-- | Module providing pattern matching and capturing on 'Identifier's.
5module Hakyll.Core.Identifier.Pattern
13import Data.List (intercalate)
14import Control.Monad (msum)
15import Data.Maybe (isJust)
17import GHC.Exts (IsString, fromString)
19import Hakyll.Core.Identifier
21-- | One base element of a pattern
23data PatternComponent = CaptureOne
28instance Show PatternComponent where
30 show CaptureMany = "**"
33-- | Type that allows matching on identifiers
35newtype Pattern = Pattern {unPattern :: [PatternComponent]}
38instance Show Pattern where
39 show = intercalate "/" . map show . unPattern
41instance IsString Pattern where
42 fromString = parsePattern
44-- | Parse a pattern from a string
46parsePattern :: String -> Pattern
47parsePattern = Pattern . map toPattern . unIdentifier . parseIdentifier
49 toPattern x | x == "*" = CaptureOne
50 | x == "**" = CaptureMany
51 | otherwise = Literal x
53-- | Match an identifier against a pattern, generating a list of captures
55match :: Pattern -> Identifier -> Maybe [[String]]
56match (Pattern p) (Identifier i) = match' p i
58-- | Check if an identifier matches a pattern
60doesMatch :: Pattern -> Identifier -> Bool
61doesMatch p = isJust . match p
63-- | Given a list of identifiers, retain only those who match the given pattern
65matches :: Pattern -> [Identifier] -> [Identifier]
66matches p = filter (doesMatch p)
68-- | Split a list at every possible point, generate a list of (init, tail) cases
70splits :: [a] -> [([a], [a])]
71splits ls = reverse $ splits' [] ls
73 splits' lx ly = (lx, ly) : case ly of
75 (y : ys) -> splits' (lx ++ [y]) ys
77-- | Internal verion of 'match'
79match' :: [PatternComponent] -> [String] -> Maybe [[String]]
80match' [] [] = Just [] -- An empty match
81match' [] _ = Nothing -- No match
82match' _ [] = Nothing -- No match
83match' (m : ms) (s : ss) = case m of
84 -- Take one string and one literal, fail on mismatch
85 Literal l -> if s == l then match' ms ss else Nothing
86 -- Take one string and one capture
87 CaptureOne -> fmap ([s] :) $ match' ms ss
88 -- Take one string, and one or many captures
90 let take' (i, t) = fmap (i :) $ match' ms t
91 in msum $ map take' $ splits (s : ss)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list