1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE NamedFieldPuns #-}
module Main (main) where
import Data.Aeson (Value, eitherDecode)
import Data.Bifunctor (first)
import qualified Data.ByteString as B (readFile)
import qualified Data.ByteString.Lazy as BS (readFile)
import Data.Foldable (for_)
import qualified Data.Text.IO as TIO (putStrLn)
import Data.Yaml (decodeEither')
import System.Console.CmdArgs.Implicit (Data, Typeable, argPos, args,
cmdArgs, def, help, summary,
typ, (&=))
import System.FilePath (takeExtension)
import Text.Mustache (automaticCompile, substitute,
toMustache)
data Arguments = Arguments
{ template :: FilePath
, templateDirs :: [FilePath]
, dataFiles :: [FilePath]
} deriving (Show, Data, Typeable)
commandArgs :: Arguments
commandArgs = Arguments
{ template = def
&= argPos 0
&= typ "TEMPLATE"
, dataFiles = def
&= args
&= typ "DATA-FILES"
, templateDirs = ["."]
&= help "The directories in which to search for the templates"
&= typ "DIRECTORIES"
} &= summary "Simple mustache template subtitution"
readJSON :: FilePath -> IO (Either String Value)
readJSON = fmap eitherDecode . BS.readFile
readYAML :: FilePath -> IO (Either String Value)
readYAML = fmap (first show . decodeEither') . B.readFile
main :: IO ()
main = do
(Arguments { template, templateDirs, dataFiles }) <- cmdArgs commandArgs
eitherTemplate <- automaticCompile templateDirs template
case eitherTemplate of
Left err -> print err
Right compiledTemplate ->
for_ dataFiles $ \file -> do
let decoder =
case takeExtension file of
".yml" -> readYAML
".yaml" -> readYAML
_ -> readJSON
decoded <- decoder file
either
putStrLn
(TIO.putStrLn . substitute compiledTemplate . toMustache)
decoded
|