{-# LANGUAGE OverloadedStrings #-} module Main (main) where import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as BC import Debug.Trace import System.Directory import System.FilePath (()) import qualified Data.Map.Strict as Map import Data.Text (Text) import Data.Text.Encoding (encodeUtf8) import qualified Data.Yaml as Y import Data.Yaml (FromJSON (..), (.!=), (.:), (.:?)) main :: IO () main = do dir <- getCurrentDirectory let yamlFile = dir "languages.yml" yaml <- B.readFile yamlFile B.writeFile (dir "src" "Gen_Languages.hs") (contents yaml) pure () contents :: B.ByteString -> B.ByteString contents yaml = "module Gen_Languages where\n\ \\n\ \import Data.ByteString (ByteString)\n\ \import Data.Text (Text)\n\ \import qualified Data.Map.Strict as Map\n\ \\n\ \-- | Type synonym for linguist's language name key.\n\ \type LanguageKey = Text\n\ \\n\ \-- | Identifies a programming language.\n\ \data Language\n\ \ = Language\n\ \ { languageID :: Integer\n\ \ , languageName :: Text\n\ \ , languageExtensions :: [Text]\n\ \ , languageFileNames :: [Text]\n\ \ } deriving (Eq, Show)\n\ \\n\ \-- | Complete map of programming languages known to linguist.\n\ \languages :: Map.Map LanguageKey Language\n\ \languages = Map.fromList\ \ [\n " <> either (BC.pack . show) (B.intercalate ",\n ") langs <> " ]\n\ \\n\ \-- | Map of languages by file extension.\n\ \languagesByExtension :: Map.Map Text [LanguageKey]\n\ \languagesByExtension = Map.fromList\ \ [\n " <> either (BC.pack . show) (B.intercalate ",\n ") langsByExt <> " ]\n\ \\n\ \-- | Map of languages by filename.\n\ \languagesByFileName :: Map.Map Text [LanguageKey]\n\ \languagesByFileName = Map.fromList\ \ [\n " <> either (BC.pack . show) (B.intercalate ",\n ") langsByFileName <> " ]\n\ \" where langs = Map.foldrWithKey (\k v xs -> "(\"" <> encodeUtf8 k <> "\", " <> BC.pack (show v { languageName = k }) <> ")" : xs) mempty <$> languages langsByExt = Map.foldrWithKey (\k vs xs -> "(\"" <> encodeUtf8 k <> "\", [" <> showLanguages vs <> "])" : xs) mempty <$> languagesByExtension langsByFileName = Map.foldrWithKey (\k vs xs -> "(\"" <> encodeUtf8 k <> "\", [" <> showLanguages vs <> "])" : xs) mempty <$> languagesByFileName showLanguages = BC.intercalate ", " . fmap (wrap . encodeUtf8 . languageName) wrap x = "\"" <> x <> "\"" languages :: Either Y.ParseException (Map.Map Text Language) languages = Y.decodeEither' yaml languagesByExtension :: Either Y.ParseException (Map.Map Text [Language]) languagesByExtension = Map.foldrWithKey (buildMap languageExtensions) mempty <$> languages languagesByFileName :: Either Y.ParseException (Map.Map Text [Language]) languagesByFileName = Map.foldrWithKey (buildMap languageFileNames) mempty <$> languages buildMap :: (Language -> [Text]) -> Text -> Language -> Map.Map Text [Language] -> Map.Map Text [Language] buildMap f k l m = foldr (\ext b -> Map.insertWith (<>) ext (pure lang) b) m (f lang) where lang = l { languageName = k } data Language = Language { languageID :: Integer , languageName :: Text , languageExtensions :: [Text] , languageFileNames :: [Text] } deriving (Eq, Show) instance FromJSON Language where parseJSON (Y.Object v) = Language <$> v .: "language_id" <*> v .:? "language_name" .!= mempty <*> v .:? "extensions" .!= mempty <*> v .:? "filenames" .!= mempty parseJSON _ = fail "Expected Object for Language value"