summaryrefslogtreecommitdiff
path: root/Biz/Namespace.hs
diff options
context:
space:
mode:
authorBen Sima <ben@bsima.me>2021-07-23 14:28:35 -0400
committerBen Sima <ben@bsima.me>2021-11-26 13:47:37 -0500
commit0264f4a5dc37b16f872e6fa92bd8f1fc1e2b1826 (patch)
treedb66845496f21afe845abaa23546b82be9c8adf0 /Biz/Namespace.hs
parent7f311fd420e92b6d90007fdd3b2d843e6e1752c3 (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.hs75
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"