diff options
author | Ben Sima <ben@bsima.me> | 2021-07-23 14:28:35 -0400 |
---|---|---|
committer | Ben Sima <ben@bsima.me> | 2021-11-26 13:47:37 -0500 |
commit | 0264f4a5dc37b16f872e6fa92bd8f1fc1e2b1826 (patch) | |
tree | db66845496f21afe845abaa23546b82be9c8adf0 /Biz/Namespace.hs | |
parent | 7f311fd420e92b6d90007fdd3b2d843e6e1752c3 (diff) |
Automatically detect Haskell dependencies
This parses the files contents for imports, then uses ghc-pkg to lookup the
package that provides the module. Now I can do that analysis in Haskell instead
of nix, which is much easier to code with.
Diffstat (limited to 'Biz/Namespace.hs')
-rw-r--r-- | Biz/Namespace.hs | 75 |
1 files changed, 49 insertions, 26 deletions
diff --git a/Biz/Namespace.hs b/Biz/Namespace.hs index 316896a..c3252fd 100644 --- a/Biz/Namespace.hs +++ b/Biz/Namespace.hs @@ -1,58 +1,58 @@ +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE NoImplicitPrelude #-} --- : dep regex-applicative module Biz.Namespace ( Namespace (..), Ext (..), fromPath, + fromContent, + fromHaskellModule, toPath, toHaskellModule, toSchemeModule, - match, ) where import Alpha +import qualified Data.Aeson as Aeson import qualified Data.Char as Char import qualified Data.List as List +import qualified Data.List.Split as List import qualified Text.Regex.Applicative as Regex data Ext = Hs | Scm | Nix | Md | Css | Py | Sh | Keys | Json | None - deriving (Eq, Show) + deriving (Eq, Show, Generic, Aeson.ToJSON) -data Namespace = Namespace [String] Ext - deriving (Eq, Show) - -match :: String -> Maybe Namespace -match = Regex.match <| Namespace </ path <* Regex.sym '.' <*> ext - where - name = - Regex.many (Regex.psym Char.isUpper) - <> Regex.many (Regex.psym Char.isAlphaNum) - path = Regex.many (name <* Regex.string "/" <|> name) - ext = - Nix <$ Regex.string "nix" - <|> Hs <$ Regex.string "hs" - <|> Scm <$ Regex.string "scm" - <|> Md <$ Regex.string "md" - <|> Css <$ Regex.string "css" - <|> Py <$ Regex.string "py" - <|> Sh <$ Regex.string "sh" - <|> Keys <$ Regex.string "pub" - <|> Json <$ Regex.string "json" +data Namespace = Namespace {path :: [String], ext :: Ext} + deriving (Eq, Show, Generic, Aeson.ToJSON) fromPath :: String -> String -> Maybe Namespace fromPath bizRoot absPath = List.stripPrefix bizRoot absPath +> List.stripPrefix "/" - +> match + +> Regex.match (Namespace </ rePath <* dot <*> reExt) + +fromContent :: String -> Maybe Namespace +fromContent c = case Regex.findFirstInfix haskellModule c of + Nothing -> Nothing + Just (_, Namespace {..}, _) -> Just <| Namespace (filter (/= ".") path) ext + where + haskellModule = + Namespace + </ (Regex.string "\nmodule " *> Regex.many (name <|> dot)) + <*> pure Hs toHaskellModule :: Namespace -> String toHaskellModule (Namespace parts Hs) = joinWith "." parts -toHaskellModule (Namespace _ ext) = +toHaskellModule (Namespace {..}) = panic <| "can't convert " <> show ext <> " to a Haskell module" +fromHaskellModule :: String -> Namespace +fromHaskellModule s = Namespace (List.splitOn "." s) Hs + toPath :: Namespace -> FilePath toPath (Namespace parts ext) = joinWith "/" parts @@ -61,5 +61,28 @@ toPath (Namespace parts ext) = toSchemeModule :: Namespace -> String toSchemeModule (Namespace parts Scm) = "(" ++ joinWith " " parts ++ ")" -toSchemeModule (Namespace _ ext) = +toSchemeModule (Namespace {..}) = panic <| "can't convert " <> show ext <> " to a Scheme module" + +dot :: Regex.RE Char String +dot = Regex.some <| Regex.sym '.' + +name :: Regex.RE Char String +name = + Regex.many (Regex.psym Char.isUpper) + <> Regex.many (Regex.psym Char.isAlphaNum) + +rePath :: Regex.RE Char [String] +rePath = Regex.many (name <* Regex.string "/" <|> name) + +reExt :: Regex.RE Char Ext +reExt = + Nix <$ Regex.string "nix" + <|> Hs <$ Regex.string "hs" + <|> Scm <$ Regex.string "scm" + <|> Md <$ Regex.string "md" + <|> Css <$ Regex.string "css" + <|> Py <$ Regex.string "py" + <|> Sh <$ Regex.string "sh" + <|> Keys <$ Regex.string "pub" + <|> Json <$ Regex.string "json" |