packages feed

project-forge-0.1.0.0: src/ProjectForge/Actions.hs

{-|
Functions for creating project initialization applications
-}

{-# LANGUAGE OverloadedStrings #-}
module ProjectForge.Actions (
    createProjectTemplateAction
  , defaultTemplateActionOpts
) where

import           Blammo.Logging.Simple
import           Control.Monad.IO.Class
import           Data.Aeson
import           Data.Text.Lazy         as TL
import qualified Data.Text.Lazy.IO      as TL
import           ProjectForge.Get
import           ProjectForge.Render
import           System.Directory
import           System.FilePath

{-|
Options for compiling, rendering and writing a a @'ProjectTemplate'@.
-}
newtype TemplateActionOpts = MkTemplateActionOpts {
    -- | The @'RenderTemplateOpts'@ for the action
    renderOpts :: RenderTemplateOpts
  }

-- | Default options
defaultTemplateActionOpts :: TemplateActionOpts
defaultTemplateActionOpts = MkTemplateActionOpts { renderOpts = defaultRenderTemplateOpts}

{-|
Create an @IO@ action that compiles, renders, and writes a @'ProjectTemplate'@.
-}
createProjectTemplateAction :: (MonadLogger m, MonadIO m, ToJSON a) =>
     TemplateActionOpts
  -> FilePath -- ^ name of directory containing project template
  -> a -- ^ type which when converted via @'Data.Aeson.toJSON'@ contains values
      --    to interpolate into the @'ProjectTemplate'@.
  -> m ()
createProjectTemplateAction opts d settings = do
  let template = getProjectTemplateFromDir d
      values = toJSON settings

  results <- (\x -> renderProjectTemplate (renderOpts opts) x values) =<< template

  writeTemplateResult results

{-
Utility for writing the results for @'renderProjectTemplate'@ to files.
-}
writeTemplateResult :: (MonadLogger m, MonadIO m) => [(FilePath, TL.Text)] -> m ()
writeTemplateResult =
    mapM_ (\(fn, cnts) -> do
      liftIO $ createDirectoryIfMissing True (takeDirectory fn)

      logDebug $ "Writing template result to file" :# [ "path" .= fn ]
      liftIO $ TL.writeFile fn cnts
    )