module Ormolu.Utils.Glob ( Glob, mkGlob, matchesGlob, ) where import Data.List (elemIndex, stripPrefix) import Data.Maybe (fromMaybe) newtype Glob = Glob [GlobPart] deriving (Glob -> Glob -> Bool (Glob -> Glob -> Bool) -> (Glob -> Glob -> Bool) -> Eq Glob forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a $c== :: Glob -> Glob -> Bool == :: Glob -> Glob -> Bool $c/= :: Glob -> Glob -> Bool /= :: Glob -> Glob -> Bool Eq, Int -> Glob -> ShowS [Glob] -> ShowS Glob -> String (Int -> Glob -> ShowS) -> (Glob -> String) -> ([Glob] -> ShowS) -> Show Glob forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a $cshowsPrec :: Int -> Glob -> ShowS showsPrec :: Int -> Glob -> ShowS $cshow :: Glob -> String show :: Glob -> String $cshowList :: [Glob] -> ShowS showList :: [Glob] -> ShowS Show) data GlobPart = MatchExactly !String | SingleWildcard | DoubleWildcard deriving (GlobPart -> GlobPart -> Bool (GlobPart -> GlobPart -> Bool) -> (GlobPart -> GlobPart -> Bool) -> Eq GlobPart forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a $c== :: GlobPart -> GlobPart -> Bool == :: GlobPart -> GlobPart -> Bool $c/= :: GlobPart -> GlobPart -> Bool /= :: GlobPart -> GlobPart -> Bool Eq, Int -> GlobPart -> ShowS [GlobPart] -> ShowS GlobPart -> String (Int -> GlobPart -> ShowS) -> (GlobPart -> String) -> ([GlobPart] -> ShowS) -> Show GlobPart forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a $cshowsPrec :: Int -> GlobPart -> ShowS showsPrec :: Int -> GlobPart -> ShowS $cshow :: GlobPart -> String show :: GlobPart -> String $cshowList :: [GlobPart] -> ShowS showList :: [GlobPart] -> ShowS Show) mkGlob :: String -> Glob mkGlob :: String -> Glob mkGlob = [GlobPart] -> Glob Glob ([GlobPart] -> Glob) -> (String -> [GlobPart]) -> String -> Glob forall b c a. (b -> c) -> (a -> b) -> a -> c . String -> [GlobPart] parsePart where parsePart :: String -> [GlobPart] parsePart :: String -> [GlobPart] parsePart String s = case String s of [] -> [] Char '*' : Char '*' : String t -> GlobPart DoubleWildcard GlobPart -> [GlobPart] -> [GlobPart] forall a. a -> [a] -> [a] : String -> [GlobPart] parsePart String t Char '*' : String t -> GlobPart SingleWildcard GlobPart -> [GlobPart] -> [GlobPart] forall a. a -> [a] -> [a] : String -> [GlobPart] parsePart String t String t -> let (String m, String t') = (Char -> Bool) -> String -> (String, String) forall a. (a -> Bool) -> [a] -> ([a], [a]) break (Char -> Char -> Bool forall a. Eq a => a -> a -> Bool == Char '*') String t in String -> GlobPart MatchExactly String m GlobPart -> [GlobPart] -> [GlobPart] forall a. a -> [a] -> [a] : String -> [GlobPart] parsePart String t' matchesGlob :: String -> Glob -> Bool matchesGlob :: String -> Glob -> Bool matchesGlob String s (Glob [GlobPart] ps) = String s String -> [GlobPart] -> Bool `matchesGlobParts` [GlobPart] ps matchesGlobParts :: String -> [GlobPart] -> Bool matchesGlobParts :: String -> [GlobPart] -> Bool matchesGlobParts String s [GlobPart] g = case [GlobPart] g of [] -> String -> Bool forall a. [a] -> Bool forall (t :: * -> *) a. Foldable t => t a -> Bool null String s MatchExactly String p : [GlobPart] g' -> case String -> String -> Maybe String forall a. Eq a => [a] -> [a] -> Maybe [a] stripPrefix String p String s of Maybe String Nothing -> Bool False Just String s' -> String s' String -> [GlobPart] -> Bool `matchesGlobParts` [GlobPart] g' GlobPart SingleWildcard : [GlobPart] g' -> let l :: Int l = Int -> Maybe Int -> Int forall a. a -> Maybe a -> a fromMaybe (String -> Int forall a. [a] -> Int forall (t :: * -> *) a. Foldable t => t a -> Int length String s) (Char -> String -> Maybe Int forall a. Eq a => a -> [a] -> Maybe Int elemIndex Char '.' String s) in [Bool] -> Bool forall (t :: * -> *). Foldable t => t Bool -> Bool or [String s' String -> [GlobPart] -> Bool `matchesGlobParts` [GlobPart] g' | Int i <- [Int 0 .. Int l], let s' :: String s' = Int -> ShowS forall a. Int -> [a] -> [a] drop Int i String s] GlobPart DoubleWildcard : [GlobPart] g' -> [Bool] -> Bool forall (t :: * -> *). Foldable t => t Bool -> Bool or [String s' String -> [GlobPart] -> Bool `matchesGlobParts` [GlobPart] g' | Int i <- [Int 0 .. String -> Int forall a. [a] -> Int forall (t :: * -> *) a. Foldable t => t a -> Int length String s], let s' :: String s' = Int -> ShowS forall a. Int -> [a] -> [a] drop Int i String s]