    module Skylighting.Core (
        lookupSyntax
      , syntaxByName
      , syntaxByShortName
      , syntaxesByExtension
      , syntaxesByFilename
      , module Skylighting.Types
      , module Skylighting.Tokenizer
      , module Skylighting.Parser
      , module Skylighting.Regex
      , module Skylighting.Styles
      , module Skylighting.Loader
      ) where
    import Control.Monad
    import Data.List (tails)
    import qualified Data.Map as Map
    import Data.Maybe (listToMaybe)
    import Data.Text (Text)
    import qualified Data.Text as Text
    import Skylighting.Loader
    import Skylighting.Parser
    import Skylighting.Regex
    import Skylighting.Styles
    import Skylighting.Tokenizer
    import Skylighting.Types

    -- | Returns a list of syntaxes appropriate for the given file extension.
    syntaxesByExtension :: SyntaxMap -> String -> [Syntax]
    syntaxesByExtension :: SyntaxMap -> String -> [Syntax]
    syntaxesByExtension SyntaxMap
    syntaxmap (Char
    '.':String
    ext) =
      SyntaxMap -> String -> [Syntax]
    syntaxesByFilename SyntaxMap
    syntaxmap (String
    "*." String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    ext)
    syntaxesByExtension SyntaxMap
    syntaxmap String
    ext =
      SyntaxMap -> String -> [Syntax]
    syntaxesByFilename SyntaxMap
    syntaxmap (String
    "*." String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    ext)

    -- | Returns a list of syntaxes appropriate for the given filename.
    syntaxesByFilename :: SyntaxMap -> String -> [Syntax]
    syntaxesByFilename :: SyntaxMap -> String -> [Syntax]
    syntaxesByFilename SyntaxMap
    syntaxmap String
    fn = [Syntax
    s | Syntax
    s <- SyntaxMap -> [Syntax]
    forall k a. Map k a -> [a]
    Map.elems SyntaxMap
    syntaxmap
                                    , String -> [String] -> Bool
    matchGlobs String
    fn (Syntax -> [String]
    sExtensions Syntax
    s)]

    -- | Lookup a syntax by full name (case insensitive).
    syntaxByName :: SyntaxMap -> Text -> Maybe Syntax
    syntaxByName :: SyntaxMap -> Text -> Maybe Syntax
    syntaxByName SyntaxMap
    syntaxmap Text
    name =
      Text -> SyntaxMap -> Maybe Syntax
    forall k a. Ord k => k -> Map k a -> Maybe a
    Map.lookup (Text -> Text
    Text.toLower Text
    name) ((Text -> Text) -> SyntaxMap -> SyntaxMap
    forall k2 k1 a. Ord k2 => (k1 -> k2) -> Map k1 a -> Map k2 a
    Map.mapKeys Text -> Text
    Text.toLower SyntaxMap
    syntaxmap)

    -- | Lookup a syntax by short name (case insensitive).
    syntaxByShortName :: SyntaxMap -> Text -> Maybe Syntax
    syntaxByShortName :: SyntaxMap -> Text -> Maybe Syntax
    syntaxByShortName SyntaxMap
    syntaxmap Text
    name = [Syntax] -> Maybe Syntax
    forall a. [a] -> Maybe a
    listToMaybe
      [Syntax
    s | Syntax
    s <- SyntaxMap -> [Syntax]
    forall k a. Map k a -> [a]
    Map.elems SyntaxMap
    syntaxmap
         , Text -> Text
    Text.toLower (Syntax -> Text
    sShortname Syntax
    s) Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text -> Text
    Text.toLower Text
    name ]

    -- | Lookup syntax by (in order) full name (case insensitive),
    -- short name (case insensitive), extension.
    lookupSyntax :: Text -> SyntaxMap -> Maybe Syntax
    lookupSyntax :: Text -> SyntaxMap -> Maybe Syntax
    lookupSyntax Text
    lang SyntaxMap
    syntaxmap
      -- special cases:
      | Text
    lang Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == String -> Text
    Text.pack String
    "csharp" = Text -> SyntaxMap -> Maybe Syntax
    lookupSyntax (String -> Text
    Text.pack String
    "cs") SyntaxMap
    syntaxmap
      | Text
    lang Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == String -> Text
    Text.pack String
    "fortran" = Text -> SyntaxMap -> Maybe Syntax
    lookupSyntax (String -> Text
    Text.pack String
    "for")
                  SyntaxMap
    syntaxmap
      | Bool
    otherwise =
        SyntaxMap -> Text -> Maybe Syntax
    syntaxByName SyntaxMap
    syntaxmap Text
    lang Maybe Syntax -> Maybe Syntax -> Maybe Syntax
    forall a. Maybe a -> Maybe a -> Maybe a
    forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
    `mplus`
        SyntaxMap -> Text -> Maybe Syntax
    syntaxByShortName SyntaxMap
    syntaxmap Text
    lang Maybe Syntax -> Maybe Syntax -> Maybe Syntax
    forall a. Maybe a -> Maybe a -> Maybe a
    forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
    `mplus`
        [Syntax] -> Maybe Syntax
    forall a. [a] -> Maybe a
    listToMaybe (SyntaxMap -> String -> [Syntax]
    syntaxesByExtension SyntaxMap
    syntaxmap (Text -> String
    Text.unpack Text
    lang))

    -- | Match filename against a list of globs contained in a semicolon-separated
    -- string.
    matchGlobs :: String -> [String] -> Bool
    matchGlobs :: String -> [String] -> Bool
    matchGlobs String
    fn [String]
    globs = (String -> Bool) -> [String] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any ((String -> String -> Bool) -> String -> String -> Bool
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip String -> String -> Bool
    matchGlob String
    fn) [String]
    globs

    -- | Match filename against a glob pattern with asterisks.
    matchGlob :: String -> String -> Bool
    matchGlob :: String -> String -> Bool
    matchGlob (Char
    '*':String
    xs) String
    fn   = (String -> Bool) -> [String] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any (String -> String -> Bool
    matchGlob String
    xs) (String -> [String]
    forall a. [a] -> [[a]]
    tails String
    fn)
    matchGlob (Char
    x:String
    xs) (Char
    y:String
    ys) = Char
    x Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    y Bool -> Bool -> Bool
    && String -> String -> Bool
    matchGlob String
    xs String
    ys
    matchGlob String
    "" String
    ""         = Bool
    True
    matchGlob String
    _ String
    _           = Bool
    False