packages feed

madlang-1.1.2.0: src/Text/Madlibs/Exec/Main.hs

{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}

-- | Provides `madlang` runMadlangutable
module Text.Madlibs.Exec.Main where

import Control.Monad
import Text.Madlibs.Cata.Run
import Text.Madlibs.Ana.Parse
import Text.Madlibs.Internal.Types
import Text.Madlibs.Internal.Utils
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import Text.Megaparsec
import Options.Generic
import Development.GitRev

-- | datatype for the program
data Program = Program { input :: FilePath <?> "filepath to template"
                       , debug :: Bool <?> "whether to display parsed RandTok" 
                       , rep :: Maybe Int <?> "How many times to repeat"
                       , v :: [String] <?> "Extra input to the template" --fix soon?
                       , version :: Bool <?> "Display version information for debugging"
                       } deriving (Generic)

data Subcommand = Debug { file :: FilePath } 
                | Run { file :: FilePath , rep' :: Maybe Int , input' :: [String] } 

-- | Generated automatically by optparse-generic.
instance ParseRecord Program where

-- | Main program action
runMadlang :: IO ()
runMadlang = do
    x <- getRecord "Text.Madlibs templating DSL"
    if unHelpful . version $ x then putStrLn build else pure ()
    case unHelpful . rep $ x of
        (Just n) -> replicateM_ n $ template x
        Nothing -> template x

-- | given a parsed record perform the appropriate IO action
template :: Program -> IO ()
template rec = do
    let filepath = unHelpful . input $ rec
    let ins = map T.pack $ (unHelpful . v $ rec)
    parsed <- parseFile ins filepath
    runFile ins filepath >>= TIO.putStrLn
    if unHelpful . debug $ rec then
        print parsed
    else
        pure ()

-- | Generate randomized text from a template
templateGen :: [T.Text] -> T.Text -> Either (ParseError Char Dec) (IO T.Text)
templateGen ins txt = run <$> parseTok ins txt

-- | Generate randomized text from a file conatining a template
runFile :: [T.Text] -> FilePath -> IO T.Text
runFile ins filepath = do
    txt <- readFile' filepath
    either (pure . parseErrorPretty') (>>= (pure . show')) (templateGen ins txt)

-- | Parse a template file into the `RandTok` data type
parseFile :: [T.Text] -> FilePath -> IO (Either (ParseError Char Dec) RandTok)
parseFile ins filepath = do
    txt <- readFile' filepath
    let val = parseTok ins txt
    pure val

-- | String with git commit string
build :: String
build = concat [ "[version: ", $(gitBranch), "@", $(gitHash)
               , " (", $(gitCommitDate), ")"
               , " (", $(gitCommitCount), " commits in HEAD)"
               , dirty, "] "] 
    where
        dirty | $(gitDirty) = " (uncommitted files present)" 
              | otherwise   = ""