on de41665 help sign in
typeable/yaml/Data/Yaml/Include.hs
62 lines 2.0 kB history raw
1{-# LANGUAGE RankNTypes #-}
2module Data.Yaml.Include (decodeFile, decodeFileEither) where
4import Control.Exception (throwIO)
5import Control.Monad (when)
6import Control.Monad.IO.Class (liftIO)
7import Control.Monad.Trans.Resource (MonadResource)
8import Data.Aeson (FromJSON)
9import Data.Conduit
10import qualified Data.Conduit.List as CL
11import Data.Text (unpack)
12import Data.Text.Encoding (decodeUtf8)
13import System.Directory
14import System.FilePath
16import Data.Yaml.Internal (ParseException(..), decodeHelper_, decodeHelper)
17import Text.Libyaml hiding (decodeFile)
18import qualified Text.Libyaml as Y
20eventsFromFile
21 :: MonadResource m
22 => FilePath
23 -> Producer m Event
24eventsFromFile = go []
25 where
26 go :: MonadResource m => [FilePath] -> FilePath -> Producer m Event
27 go seen fp = do
28 cfp <- liftIO $ canonicalizePath fp
29 when (cfp `elem` seen) $ do
30 liftIO $ throwIO CyclicIncludes
31 Y.decodeFile cfp $= do
32 awaitForever $ \event -> case event of
33 EventScalar f (UriTag "!include") _ _ -> do
34 let includeFile = takeDirectory cfp </> unpack (decodeUtf8 f)
35 go (cfp : seen) includeFile $= CL.filter (`notElem` irrelevantEvents)
36 _ -> yield event
38 irrelevantEvents = [EventStreamStart, EventDocumentStart, EventDocumentEnd, EventStreamEnd]
40-- | Like `Data.Yaml.decodeFile` but with support for relative and absolute
41-- includes.
42--
43-- The syntax for includes follows the form:
44--
45-- > somekey: !include ./somefile.yaml
46decodeFile
47 :: FromJSON a
48 => FilePath
49 -> IO (Maybe a)
50decodeFile fp = decodeHelper (eventsFromFile fp) >>= either throwIO (return . either (const Nothing) id)
52-- | Like `Data.Yaml.decodeFileEither` but with support for relative and
53-- absolute includes.
54--
55-- The syntax for includes follows the form:
56--
57-- > somekey: !include ./somefile.yaml
58decodeFileEither
59 :: FromJSON a
60 => FilePath
61 -> IO (Either ParseException a)
62decodeFileEither = decodeHelper_ . eventsFromFile