{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE NamedFieldPuns #-} module Main (main) where import Data.Aeson (Value, eitherDecode) 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 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