53 lines
1.4 KiB
Haskell
53 lines
1.4 KiB
Haskell
|
module YAML (module YAML) where
|
||
|
|
||
|
import Data.YAML as YAML
|
||
|
import Data.YAML.Event as YAML (untagged)
|
||
|
import Data.Text (Text)
|
||
|
import qualified Data.Text as Text
|
||
|
import Misc
|
||
|
import Data.ByteString (ByteString)
|
||
|
import qualified Data.ByteString as BS
|
||
|
import qualified Data.ByteString.Lazy as LazyBS
|
||
|
import qualified System.IO as IO
|
||
|
|
||
|
|
||
|
str' :: String -> Node ()
|
||
|
str' = str . Text.pack
|
||
|
|
||
|
str :: Text -> Node ()
|
||
|
str = Scalar () . SStr
|
||
|
|
||
|
obj :: Mapping () -> Node ()
|
||
|
obj = Mapping () untagged
|
||
|
|
||
|
(##=) :: (ToYAML b) => Text -> b -> (Node (), Node ())
|
||
|
(##=) = (#=)
|
||
|
|
||
|
(#=) :: (ToYAML a, ToYAML b) => a -> b -> (Node (), Node ())
|
||
|
k #= v = (toYAML k, toYAML v)
|
||
|
|
||
|
list :: ToYAML a => [a] -> Node ()
|
||
|
list = Sequence () untagged . map toYAML
|
||
|
|
||
|
|
||
|
-- | read a chunk from the beginning of the file between a
|
||
|
-- @---@ and a @...@. throw an exception if there isn't one
|
||
|
readHeader :: FilePath -> IO (YAML.Node YAML.Pos)
|
||
|
readHeader file = IO.withFile file IO.ReadMode \h -> do
|
||
|
ln <- BS.hGetLine h
|
||
|
if (ln /= "---") then
|
||
|
fail $ file <> ": no header"
|
||
|
else
|
||
|
unwrap file . YAML.decode1 =<< linesUntil "..." h
|
||
|
|
||
|
-- | read all the lines from a handle until the given terminator. return the
|
||
|
-- lines read, excluding the terminator
|
||
|
linesUntil :: ByteString -> IO.Handle -> IO LazyBS.ByteString
|
||
|
linesUntil end h = go [] where
|
||
|
go acc = do
|
||
|
l <- BS.hGetLine h
|
||
|
if l == end then
|
||
|
return $ LazyBS.fromChunks $ reverse acc
|
||
|
else
|
||
|
go (l <> "\n" : acc)
|