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
|