packages feed

marvin-0.0.2: initializer/Main.hs

{-# LANGUAGE RecordWildCards #-}
module Main where

import           Control.Arrow         (second)
import           Control.Monad
import           Data.Containers
import           Data.Foldable         (for_)
import           Data.Sequences
import qualified Data.Text.IO          as T
import           Options.Applicative
import           Paths_marvin
import           Prelude               hiding (lookup)
import           System.Directory
import           System.FilePath
import           Text.Mustache.Compile
import           Text.Mustache.Render
import           Text.Mustache.Types


data Opts = Opts
    { botname :: String
    , adapter :: String
    }


fromEither :: Show a => Either a b -> b
fromEither (Left e)  = error $ "Was left: " <> show e
fromEither (Right v) = v


wantDirectories :: [FilePath]
wantDirectories =
    [ "bot" ]


wantFiles :: [(FilePath, Template)]
wantFiles = map (second $ fromEither . compileTemplate "")
    [ ("Main.hs.mustache", "bot/Main.hs")
    , ("MyScript.hs.mustache", "bot/MyScript.hs")
    , ("config.cfg.mustache", "config.cfg")
    , ("bot.cabal.mustache", "{{name}}.cabal")
    ]


adType :: [(String, String)]
adType =
    [ ("slack-rtm", "SlackRTMAdapter") ]


main :: IO ()
main = do
    Opts{..} <- execParser infoParser
    d <- (</> "initializer") <$> getDataDir
    unless (adapter `member` adType) $ putStrLn "Unrecognized adapter"

    let subsData = object [ "name" ~> botname
                          , "scriptsig" ~> maybe "IsAdapter a => ScriptInit a" ("ScriptInit " <>) (lookup adapter adType)
                          , "adapter" ~> adapter
                          ]

    for_ wantDirectories $ \dir -> do
        exists <- doesDirectoryExist dir
        unless exists (createDirectory dir)

    for_ wantFiles $ \(source, target) -> do
        let targetName = unpack $ substituteValue target subsData
        if ".mustache" == takeExtension source
            then do
                tpl <- fromEither <$> automaticCompile [d] source
                T.writeFile targetName $ substituteValue tpl subsData
            else copyFile source targetName

    return ()
  where
    infoParser = info
        (helper <*> optsParser)
        (fullDesc <> header "marvin-init ~ make a new marvin project")
    optsParser = Opts
        <$> argument str (metavar "BOTNAME")
        <*> strOption
            (  long "adapter"
            <> short 'a'
            <> metavar "ID"
            <> value "slack-rtm"
            <> help "id of the adapter to use" )