{-# LANGUAGE OverloadedStrings #-}
module Bricoleur.Config
( Config(..)
, Source(..)
, Expose(..)
, getConfig
, example
) where
import Control.Applicative ((<|>))
import qualified Data.Adnot as A
import qualified Data.ByteString as B
import qualified Data.Map.Strict as M
import qualified Data.Text as T
import qualified Data.Vector as V
data Config = Config
{ confDocument :: FilePath
, confSources :: [Source]
} deriving (Eq, Show)
instance A.FromAdnot Config where
parseAdnot = A.withSumNamed "config file" "document" go
where
go payload
| Just file <- payload V.!? 0
= Config <$> A.parseAdnot file
<*> mapM A.parseAdnot (V.toList (V.tail payload))
| otherwise = Left "expected source file in config"
data Source = Source
{ sourceName :: T.Text
, sourceDir :: FilePath
, sourceCommands :: [String]
, sourceExpose :: Expose
} deriving (Eq, Show)
instance A.FromAdnot Source where
parseAdnot = A.withProduct "source" $ \p -> do
name <- p A..: "name"
dir <- p A..: "dir"
cmds <- p A..: "cmd"
expose <- p A..: "expose"
return (Source name dir cmds expose)
data Expose
= ExposeFile FilePath
| ExposeSections FilePath
| NamedMap (M.Map T.Text Expose)
deriving (Eq, Show)
instance A.FromAdnot Expose where
parseAdnot v = file v <|> sections v <|> namedMap v
where
file = A.withSumNamed "exposed fragments" "file" $ \ ps ->
case V.toList ps of
[] -> Left "Expected name for file"
[f] -> ExposeFile <$> A.parseAdnot f
_ -> Left "Too many arguments to file"
sections = A.withSumNamed "exposed fragments" "sections" $ \ ps ->
case V.toList ps of
[] -> Left "Expected name for sections"
[f] -> ExposeSections <$> A.parseAdnot f
_ -> Left "Too many arguments to sections"
namedMap = A.withProduct "exposed fragments" $ \ p ->
NamedMap <$> mapM A.parseAdnot p
parseConfig :: B.ByteString -> Either String Config
parseConfig = A.decode
getConfig :: FilePath -> IO (Either String Config)
getConfig loc = do
conf <- B.readFile loc
return (parseConfig conf)
example :: Config
example = Config
{ confDocument = "main.md"
, confSources =
[ Source
{ sourceName = "rust-sample"
, sourceDir = "s1"
, sourceCommands = ["cargo clean", "cargo build"]
, sourceExpose = ExposeFile "src/main.rs"
}
, Source
{ sourceName = "haskell-sample"
, sourceDir = "s2"
, sourceCommands = ["cabal new-build"]
, sourceExpose = ExposeSections "Main.hs"
}
]
}