packages feed

tmpl-0.0.0.1: tmpl.hs

{-# LANGUAGE OverloadedStrings #-}
module Main where
import System.Environment (getArgs)
import Control.Monad (when)
import qualified Data.ByteString.Lazy as S
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import qualified Data.Text.Lazy.Encoding as E
import System.Directory (doesFileExist)
import System.Exit (exitSuccess)

import Data.Text.Template

usage :: String
usage = unlines [
   "tmpl -- simple string-template-interpolation"
  ,"\n"
  ,"Usage:"
  ,"\ttmpl var1=uno:var2=dos < myfile.tmpl > myfile.txt"
  ,"\ttmpl myfile.tmpl < vars.conf > myfile.txt"
  ,"\ttmpl myfile.tmpl vars.conf > myfile.txt"
  ,"\n"
  ,"Example:"
  ,"\techo 'The quick $color fox jumps over the $adj dog.' \\"
  ,"\t\t| tmpl color=brown:adj=lazy"
  ,"\n"
  ,"Author: Michel Kuhlmann 2013"
  ]

main :: IO ()
main = do
  args <- getArgs
  (tmpl,cntx) <-
      case length args of
        1 -> do
          let f = head args
          when (f == "-h" || f == "--help") (sequence_ [putStrLn usage, exitSuccess])
          isFile <- doesFileExist f
          if isFile
             then do
               cntx <- fmap (context . splitStr) TIO.getContents
               tmpl <- TIO.readFile f
               return (tmpl,cntx)
             else do
               let cntx = context . splitStr . T.pack $ f
               tmpl <- TIO.getContents
               return (tmpl,cntx)

        2 -> do
          let tmplF:cntxF:[] = args
          existTmplF <- doesFileExist tmplF
          existCntxF <- doesFileExist cntxF
          when (not  existTmplF || not existCntxF) (fail usage)
          tmpl <- TIO.readFile tmplF
          cntx <- fmap (context . splitStr) $ TIO.readFile cntxF
          return (tmpl,cntx)

        _ -> error usage

  S.putStr $ E.encodeUtf8 $ substitute tmpl cntx


-- | Create 'Context' from association list.
context :: [(T.Text, T.Text)] -> Context
context assocs x = maybe err id . lookup x $ assocs
  where err = error $ "Could not find key: " ++ T.unpack x

-- | First split Text on ':' or newline; second split on '='
splitStr :: T.Text -> [(T.Text, T.Text)]
splitStr s = map splitEq (T.split (\c -> c `elem` [':','\n'] ) s)
  where
    splitEq s = (k,v)
      where
        k:v:[] = T.split (== '=') s
        --k:v:[] = map chomp $ T.split (== '=') s
    --chomp = T.replace " " ""