module Hi ( run , process ) where import Hi.Directory (inDirectory) import Hi.FilePath (rewritePath) import qualified Hi.Git as Git import Hi.Template (readTemplates) import Hi.Types import Hi.Utils import Control.Applicative import Control.Monad import qualified Data.ByteString as BS (writeFile, concat) import qualified Data.ByteString.Lazy as LBS (toChunks) import Data.Maybe (fromJust) import qualified Data.Text as T (pack, unpack) import Data.Text.Encoding (decodeUtf8) import Data.Text.Lazy.Encoding (encodeUtf8) import Data.Text.Template (Context, substitute) import System.Directory (createDirectoryIfMissing) import System.FilePath (dropFileName) import System.Process (system) -- | Run 'hi'. run :: [Option] -> IO () run options = do putStrLn $ "Creating new project from repository: " ++ Git.expandUrl repository writeFiles =<< showFileList =<< process options <$> readTemplates repository postProcess options where repository = fromJust $ lookupArg "repository" options -- |Write given 'Files' to filesystem. writeFiles :: Files -> IO () writeFiles = mapM_ write write :: File -> IO () write f = let path = getFilePath f contents = getFileContents f in createDirectoryIfMissing True (dropFileName path) >> BS.writeFile path contents -- | Show 'Files' to stdout. showFileList :: Files -> IO Files showFileList files = do mapM_ (showFile . getFilePath) files return files where showFile :: FilePath -> IO () showFile path = putStrLn $ " " ++ green "create" ++ " " ++ path green :: String -> String green x = "\x1b[32m" ++ x ++ "\x1b[0m" -- |Process given 'Files' and return result. it does -- -- 1. rewrite path -- -- 2. substitute arguments process :: [Option] -> Files -> Files process options = map go where go (TemplateFile path content) = TemplateFile (rewritePath' path) (substitute' content) go (RegularFile path content) = RegularFile (rewritePath' path) content rewritePath' = rewritePath options substitute' text = BS.concat . LBS.toChunks . encodeUtf8 $ substitute (decodeUtf8 text) (context options) -- | Return 'Context' obtained by given 'Options' context :: [Option] -> Context context options x = T.pack (fromJust $ lookup (T.unpack x) [(k,v) | (Arg k v) <- options]) postProcess :: [Option] -> IO () postProcess options = do when (InitializeGitRepository `elem` options) $ -- TODO This wont' work unless template has `package-name` as root dir. inDirectory (fromJust $ lookupArg "packageName" options) $ void $ system "git init && git add . && git commit -m \"Initial commit\"" return ()