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
  , module Skylighting.Format.ANSI
  , module Skylighting.Format.HTML
  , module Skylighting.Format.LaTeX
  ) 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.Format.ANSI
import Skylighting.Format.HTML
import Skylighting.Format.LaTeX
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
  | Bool
otherwise =
    SyntaxMap -> Text -> Maybe Syntax
syntaxByName SyntaxMap
syntaxmap Text
lang Maybe Syntax -> Maybe Syntax -> Maybe Syntax
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 (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