packages feed

lingo 0.3.2.0 → 0.4.0.0

raw patch · 6 files changed

+133/−155 lines, 6 filesdep +aesondep +template-haskelldep ~textsetup-changednew-uploaderPVP ok

version bump matches the API change (PVP)

Dependencies added: aeson, template-haskell

Dependency ranges changed: text

API changes (from Hackage documentation)

- Data.Languages: [languageID] :: Language -> Integer
- Data.Languages: [languageName] :: Language -> Text
+ Data.Languages: [languageId] :: Language -> Integer
+ Data.Languages: [languageKey] :: Language -> LanguageKey
+ Data.Languages: languageName :: Language -> Text
+ Data.Languages.Templates: Language :: Integer -> LanguageKey -> [String] -> [String] -> Language
+ Data.Languages.Templates: [languageExtensions] :: Language -> [String]
+ Data.Languages.Templates: [languageFileNames] :: Language -> [String]
+ Data.Languages.Templates: [languageId] :: Language -> Integer
+ Data.Languages.Templates: [languageKey] :: Language -> LanguageKey
+ Data.Languages.Templates: data Language
+ Data.Languages.Templates: generateLanguageMap :: DecsQ
+ Data.Languages.Templates: instance Data.Aeson.Types.FromJSON.FromJSON Data.Languages.Templates.Language
+ Data.Languages.Templates: instance GHC.Classes.Eq Data.Languages.Templates.Language
+ Data.Languages.Templates: instance GHC.Show.Show Data.Languages.Templates.Language
+ Data.Languages.Templates: instance Language.Haskell.TH.Syntax.Lift Data.Languages.Templates.Language
+ Data.Languages.Templates: languageName :: Language -> Text
+ Data.Languages.Templates: type LanguageKey = String
- Data.Languages: Language :: Integer -> Text -> [Text] -> [Text] -> Language
+ Data.Languages: Language :: Integer -> LanguageKey -> [String] -> [String] -> Language
- Data.Languages: [languageExtensions] :: Language -> [Text]
+ Data.Languages: [languageExtensions] :: Language -> [String]
- Data.Languages: [languageFileNames] :: Language -> [Text]
+ Data.Languages: [languageFileNames] :: Language -> [String]
- Data.Languages: languagesByExtension :: Map Text [LanguageKey]
+ Data.Languages: languagesByExtension :: Map String [LanguageKey]
- Data.Languages: languagesByFileName :: Map Text [LanguageKey]
+ Data.Languages: languagesByFileName :: Map String [LanguageKey]
- Data.Languages: type LanguageKey = Text
+ Data.Languages: type LanguageKey = String

Files

ChangeLog.md view
@@ -1,3 +1,9 @@+# 0.4.0.0++Rewrite to use Template Haskell splices instead of a custom Setup.hs.++Add support for the Bazel build system.+ # 0.3.0.0  `languageForPath` is now `languagesForPath`, which returns multiple results in cases of ambiguity.
README.md view
@@ -5,7 +5,13 @@ ## Development  ```-cabal new-update-cabal new-configure-cabal new-build+cabal v2-update+cabal v2-configure+cabal v2-build+```++You can also use the [Bazel](https://haskell.build) build system:++```+bazel build //... ```
Setup.hs view
@@ -1,116 +1,2 @@-{-# LANGUAGE OverloadedStrings #-}--import qualified Data.ByteString as B-import qualified Data.ByteString.Char8 as BC-import           Debug.Trace-import           Distribution.PackageDescription-import           Distribution.Simple hiding (Language)-import           Distribution.Simple.BuildPaths-import           Distribution.Simple.LocalBuildInfo-import           Distribution.Simple.Setup-import           System.Directory-import           System.FilePath.Posix ((</>))-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 = defaultMainWithHooks simpleUserHooks { postConf = conf }--conf :: Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ()-conf _ _ _ info = do-  let autogenDir = autogenPackageModulesDir info-  createDirectoryIfMissing True autogenDir-  traceM $ "Writing Gen_Languages.hs to autogenDir: " <> autogenDir-  dir <- getCurrentDirectory-  let yamlFile = dir </> "languages.yml"-  yaml <- B.readFile yamlFile-  B.writeFile (autogenDir </> "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"+import Distribution.Simple+main = defaultMain
lingo.cabal view
@@ -1,7 +1,7 @@ cabal-version:       2.4-build-type:          Custom+build-type:          Simple name:                lingo-version:             0.3.2.0+version:             0.4.0.0 synopsis:            File extension based programming language detection description:         Lingo uses github/linguist's language registry to enable fast detection of a file path's programming langauge based on extension or filename. homepage:            https://github.com/tclem/lingo-haskell@@ -11,32 +11,26 @@ maintainer:          timothy.clem@gmail.com category:            Data extra-source-files:  README.md-                   , languages.yml                    , ChangeLog.md--tested-with:         GHC == 8.6.5-                     GHC == 8.8.1+data-files:          languages.yml -custom-setup-  setup-depends:       Cabal-                     , base-                     , bytestring-                     , containers-                     , directory-                     , filepath-                     , text-                     , yaml+tested-with:  GHC == 8.6.5+            , GHC == 8.8.1+            , GHC == 8.10.1  library-  exposed-modules: Data.Languages-  other-modules: Gen_Languages-  autogen-modules: Gen_Languages+  exposed-modules:     Data.Languages+                     , Data.Languages.Templates+  autogen-modules:     Paths_lingo+  other-modules:       Paths_lingo   build-depends:       base >= 4.12 && < 5+                     , aeson >= 1.4 && <2                      , bytestring ^>= 0.10.8.2                      , containers ^>= 0.6.0.1                      , filepath ^>= 1.4.2.1                      , raw-strings-qq ^>= 1.1-                     , text ^>= 1.2.3.1+                     , text ^>= 1.2.3.2+                     , template-haskell >= 2.14.0.0 && < 2.17.0.0                      , yaml ^>= 0.11.1.2   hs-source-dirs:      src   default-language:    Haskell2010
src/Data/Languages.hs view
@@ -1,23 +1,29 @@+{-# LANGUAGE TemplateHaskell #-}+ -- | Primary interface for looking up the programming language of a file or -- interacting with languages known to linguist -- (https://github.com/github/linguist). module Data.Languages-  ( languagesForPath-  , languages-  , languagesByExtension-  , languagesByFileName-  , LanguageKey-  , Language(..)-  ) where+  ( languagesForPath,+    languages,+    languagesByExtension,+    languagesByFileName,+    LanguageKey,+    Language (..),+    languageName+  )+where -import           Control.Applicative+import Control.Applicative+import Data.Languages.Templates import qualified Data.Map.Strict as Map-import           Data.Maybe-import           Data.Text (Text)+import Data.Maybe+import Data.Text (Text) import qualified Data.Text as Text-import           Gen_Languages-import           System.FilePath.Posix+import System.FilePath.Posix +$(generateLanguageMap)+ -- | Find the set of possible languages for a given file path. -- -- Multiple results will be returned for ambiguous files; for example, @.md@ files can be Markdown or GCC machine descriptions, and @.php@ files can be PHP or Hack source files.@@ -26,8 +32,8 @@   where     languageForFileName = languageFor (takeFileName path) languagesByFileName     languageForExtension = languageFor (takeExtension path) languagesByExtension-    languageFor :: String -> Map.Map Text [LanguageKey] -> [Language]-    languageFor k-      = foldMap (maybeToList . flip Map.lookup languages)-      . fromMaybe []-      . Map.lookup (Text.pack k)+    languageFor :: String -> Map.Map String [LanguageKey] -> [Language]+    languageFor k =+      foldMap (maybeToList . flip Map.lookup languages)+        . fromMaybe []+        . Map.lookup k
+ src/Data/Languages/Templates.hs view
@@ -0,0 +1,80 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveLift #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}++module Data.Languages.Templates+  ( Language (..),+    LanguageKey,+    generateLanguageMap,+    languageName,+  )+where++import Data.Aeson+import Data.ByteString (ByteString)+import qualified Data.Map.Strict as Map+import Data.Text (Text)+import qualified Data.Text as Text+import Data.Yaml+import GHC.Generics (Generic)+import Language.Haskell.TH+import Language.Haskell.TH.Syntax+#ifndef LANGUAGES_YAML_PATH+import Paths_lingo+#endif++-- | Type synonym for linguist's language name key.+type LanguageKey = String++-- | Identifies a programming language.+data Language = Language+  { languageId :: Integer,+    languageKey :: LanguageKey,+    languageExtensions :: [String],+    languageFileNames :: [String]+  }+  deriving (Eq, Show, Lift)++languageName :: Language -> Text+languageName = Text.pack . languageKey++instance FromJSON Language where+  parseJSON = withObject "Language" $ \l ->+    Language+      <$> l .: "language_id"+      <*> pure "unspecified" -- this is set later in map iteration+      <*> l .:? "extensions" .!= []+      <*> l .:? "filenames" .!= []++languagesYamlPath :: IO String+#ifdef LANGUAGES_YAML_PATH+languagesYamlPath = pure LANGUAGES_YAML_PATH+#else+languagesYamlPath = getDataFileName "languages.yml"+#endif++generateLanguageMap :: DecsQ+generateLanguageMap = do+  langYaml <- runIO languagesYamlPath+  langs <- runIO (decodeFileThrow @IO @(Map.Map LanguageKey Language) langYaml)+  let normalizedLangs = Map.mapWithKey (\name lang -> lang {languageKey = name}) langs++      byExtension = Map.foldr (process languageExtensions) mempty normalizedLangs+      byFileName = Map.foldr (process languageFileNames) mempty normalizedLangs++      process :: (Language -> [String]) -> Language -> Map.Map String [LanguageKey] -> Map.Map String [LanguageKey]+      process selector lang acc = foldr (\ext -> Map.insertWith mappend ext [languageKey lang]) acc (selector lang)++  [d|+    languages :: Map.Map LanguageKey Language+    languages = Map.fromDistinctAscList $(lift (Map.toAscList normalizedLangs))++    languagesByExtension :: Map.Map String [LanguageKey]+    languagesByExtension = Map.fromDistinctAscList $(lift (Map.toAscList byExtension))++    languagesByFileName :: Map.Map String [LanguageKey]+    languagesByFileName = Map.fromDistinctAscList $(lift (Map.toAscList byFileName))+    |]