blog/blog-meta/lib/YAML.hs

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)