Config.hs 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. {-# LANGUAGE OverloadedStrings #-}
  2. module Collage.Config
  3. ( Config(..)
  4. , Source(..)
  5. , Expose(..)
  6. , getConfig
  7. , example
  8. ) where
  9. import Control.Applicative ((<|>))
  10. import qualified Data.Adnot as A
  11. import qualified Data.ByteString as B
  12. import qualified Data.Map.Strict as M
  13. import qualified Data.Text as T
  14. import qualified Data.Vector as V
  15. data Config = Config
  16. { confDocument :: T.Text
  17. , confSources :: [Source]
  18. } deriving (Eq, Show)
  19. instance A.FromAdnot Config where
  20. parseAdnot = A.withSumNamed "config file" "document" go
  21. where
  22. go payload
  23. | Just file <- payload V.!? 0
  24. = Config <$> A.withString "file name" pure file
  25. <*> mapM A.parseAdnot (V.toList (V.tail payload))
  26. | otherwise = Left "expected source file in config"
  27. data Source = Source
  28. { sourceName :: T.Text
  29. , sourceDir :: FilePath
  30. , sourceCommands :: [String]
  31. , sourceExpose :: [Expose]
  32. } deriving (Eq, Show)
  33. instance A.FromAdnot Source where
  34. parseAdnot = A.withProduct "source" $ \p -> do
  35. name <- p A..: "name"
  36. dir <- p A..: "dir"
  37. cmds <- p A..: "cmd"
  38. expose <- p A..: "expose" <|> (fmap pure (p A..: "expose"))
  39. return (Source name dir cmds expose)
  40. data Expose
  41. = ExposeFile FilePath
  42. | ExposeSections FilePath
  43. | NamedMap (M.Map T.Text Expose)
  44. deriving (Eq, Show)
  45. instance A.FromAdnot Expose where
  46. parseAdnot v = file v <|> sections v <|> namedMap v
  47. where
  48. file = A.withSumNamed "exposed fragments" "file" $ \ ps ->
  49. case V.toList ps of
  50. [] -> Left "Expected name for file"
  51. [f] -> ExposeFile <$> A.parseAdnot f
  52. _ -> Left "Too many arguments to file"
  53. sections = A.withSumNamed "exposed fragments" "sections" $ \ ps ->
  54. case V.toList ps of
  55. [] -> Left "Expected name for sections"
  56. [f] -> ExposeFile <$> A.parseAdnot f
  57. _ -> Left "Too many arguments to sections"
  58. namedMap = A.withProduct "exposed fragments" $ \ p ->
  59. NamedMap <$> mapM A.parseAdnot p
  60. parseConfig :: B.ByteString -> Either String Config
  61. parseConfig = A.decode
  62. getConfig :: FilePath -> IO (Either String Config)
  63. getConfig loc = do
  64. loc <- B.readFile loc
  65. return (parseConfig loc)
  66. example :: Config
  67. example = Config
  68. { confDocument = "main.md"
  69. , confSources =
  70. [ Source
  71. { sourceName = "rust-sample"
  72. , sourceDir = "s1"
  73. , sourceCommands = ["cargo clean", "cargo build"]
  74. , sourceExpose = [ExposeFile "src/main.rs"]
  75. }
  76. , Source
  77. { sourceName = "haskell-sample"
  78. , sourceDir = "s2"
  79. , sourceCommands = ["cabal new-build"]
  80. , sourceExpose = [ExposeSections "Main.hs"]
  81. }
  82. ]
  83. }