module ExcludeApi ( parseFilterFile, matcher ) where import Data.Char (isSpace) import Data.Maybe (catMaybes, isJust) import Data.List (isPrefixOf, intersperse) import Text.Regex (mkRegex, matchRegex) data FilterSpec = Exclude String | NotExclude String -- override Exclude but not AlwaysExclude | AlwaysExclude String parseFilterFile :: String -> [FilterSpec] parseFilterFile = catMaybes . map parseLine . lines where parseLine [] = Nothing parseLine ('#':_) = Nothing parseLine line | "exclude " `isPrefixOf` line = Just $ Exclude $ trim $ drop 8 line | "do not exclude " `isPrefixOf` line = Just $ NotExclude $ trim $ drop 15 line | "always exclude " `isPrefixOf` line = Just $ AlwaysExclude $ trim $ drop 15 line parseLine line = error $ "cannot parse line: " ++ line trim = takeWhile (not . isSpace) . dropWhile isSpace matcher :: [FilterSpec] -> (String -> Bool) matcher spec line = not $ (matchExclude && (not matchNotExclude)) || matchAlwaysExclude where excludeRegexFragments = [ regex | Exclude regex <- spec ] noExcludeRegexFragments = [ regex | NotExclude regex <- spec ] alwaysExcludeRegexFragments = [ regex | AlwaysExclude regex <- spec ] excludeRegex = mkRegex $ concat $ intersperse "|" excludeRegexFragments noExcludeRegex = mkRegex $ concat $ intersperse "|" noExcludeRegexFragments alwaysExcludeRegex = mkRegex $ concat $ intersperse "|" alwaysExcludeRegexFragments matchExclude = isJust (matchRegex excludeRegex line) && not (null excludeRegexFragments) matchNotExclude = isJust (matchRegex noExcludeRegex line) && not (null noExcludeRegexFragments) matchAlwaysExclude = isJust (matchRegex alwaysExcludeRegex line) && not (null alwaysExcludeRegexFragments)