elm-init 1.0.1.0 → 1.0.1.1
raw patch · 7 files changed
+258/−211 lines, 7 filesdep +base-unicode-symbolsdep +processdep ~basedep ~directory
Dependencies added: base-unicode-symbols, process
Dependency ranges changed: base, directory
Files
- elm-init.cabal +9/−5
- resources/.gitignore +2/−0
- resources/Main.elm +2/−2
- src/ElmInit/Interact.hs +36/−33
- src/ElmInit/Types.hs +52/−43
- src/ElmInit/Util.hs +20/−13
- src/Main.hs +137/−115
elm-init.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: elm-init-version: 1.0.1.0+version: 1.0.1.1 synopsis: Set up basic structure for an elm project description: Initialize a new empty elm project with some basic scaffolding according to 'https://github.com/evancz/elm-architecture-tutorial'.@@ -14,6 +14,7 @@ category: Development build-type: Simple cabal-version: >=1.10+tested-with: GHC >= 7.6 Data-dir: resources @@ -27,6 +28,7 @@ licenses/LGPL3 licenses/MIT index.html+ .gitignore Extra-source-files: README.md@@ -41,16 +43,18 @@ ElmInit.Util -- other-extensions: build-depends:- base >=4.8 && <5.0,+ base >=4.6 && <5.0, filepath >= 1.4,- directory >= 1.2,+ directory >= 1.2.3, file-embed >= 0.0.8, bytestring >= 0.10, aeson >= 0.8, aeson-pretty >= 0.7, text >= 1.2, containers >= 0.5,- time+ time,+ base-unicode-symbols,+ process hs-source-dirs: src default-language: Haskell2010 ghc-options:@@ -64,4 +68,4 @@ type: git branch: master location: git://github.com/JustusAdam/elm-init.git- tag: 1.0.1.0+ tag: 1.0.1.1
+ resources/.gitignore view
@@ -0,0 +1,2 @@+elm-stuff/+app.js
resources/Main.elm view
@@ -9,7 +9,7 @@ type Action = Reset -update : Action -> Model -> Model+update : Action → Model → Model update action model = case action of- Reset -> model+ Reset → model
src/ElmInit/Interact.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE UnicodeSyntax #-} module ElmInit.Interact ( askChoicesWithOther@@ -6,24 +7,26 @@ ) where -import Control.Applicative ((<$>), (<*>))-import qualified Control.Arrow as Arrow (first)-import Data.Bool (bool)-import Data.Text (append)-import Data.Text as Text (Text, intercalate, pack)-import Data.Text.IO as TextIO (getLine, putStrLn)-import ElmInit.Util (enumerate, getOr)-import Prelude hiding (getLine, putStrLn)+import Control.Applicative ((<$>), (<*>))+import Control.Applicative.Unicode+import qualified Control.Arrow as Arrow (first)+import Control.Monad.Unicode+import Data.Text (append)+import Data.Text as Text (Text, intercalate, pack)+import Data.Text.IO as TextIO (getLine, putStrLn)+import ElmInit.Util (enumerate, getOr, bool)+import Prelude hiding (getLine, putStrLn)+import Prelude.Unicode -askChoices :: Text -> Int -> [Text] -> IO Text+askChoices ∷ Text → Int → [Text] → IO Text askChoices =- ((fmap <$> (!!) <*>) .) . askChoices'+ ((fmap <$> (!!) ⊛) ∘) ∘ askChoices' -askChoices' :: Text -> Int -> [Text] -> IO Int+askChoices' ∷ Text → Int → [Text] → IO Int askChoices' message selected choices =- putStrLn message >>+ putStrLn message ≫ ask out where@@ -32,40 +35,40 @@ intercalate "\n" (normFormat 1 l1- ++ (selectedFormat selected selectedElem : normFormat (selected + 1) l2tail))+ ⧺ (selectedFormat selected selectedElem : normFormat (selected + 1) l2tail)) - enumF = flip append " ) " . pack . show- enumFn = append " " . enumF- enumFs = append " * " . enumF- normFormat = (map (uncurry append . Arrow.first enumFn) .) . enumerate- selectedFormat x y = (flip append y . enumFs) x+ enumF = flip append " ) " ∘ pack ∘ show+ enumFn = append " " ∘ enumF+ enumFs = append " * " ∘ enumF+ normFormat = (map (uncurry append ∘ Arrow.first enumFn) ∘) ∘ enumerate+ selectedFormat x y = (flip append y ∘ enumFs) x ask a =- putStrLn a >>- getOr selected >>=+ putStrLn a ≫+ getOr selected ≫= (bool- (putStrLn "invalid choice, please choose again" >>+ (putStrLn "invalid choice, please choose again" ≫ ask a) <$> return- <*> (<= length choices))+ ⊛ (≤ length choices)) -askChoicesWithOther :: Text -> Int -> (Text -> Either Text a) -> [Text] -> IO a+askChoicesWithOther ∷ Text → Int → (Text → Either Text a) → [Text] → IO a askChoicesWithOther m s trans l =- askChoices' m s (l ++ ["other (specify)"])- >>= (flip bool getAlternative- <$> either (const $ error "No parse") return . trans . (l !!)- <*> (== length l))+ askChoices' m s (l ⧺ ["other (specify)"])+ ≫= (flip bool getAlternative+ <$> either (const $ error "No parse") return ∘ trans ∘ (l !!)+ ⊛ (≡ length l)) where getAlternative =- putStrLn "please enter an alternative" >>- getLine >>=+ putStrLn "please enter an alternative" ≫+ getLine ≫= (either- (\message ->- putStrLn "Invalid input:" >>- putStrLn message >>+ (\message →+ putStrLn "Invalid input:" ≫+ putStrLn message ≫ getAlternative ) return- . trans)+ ∘ trans)
src/ElmInit/Types.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE UnicodeSyntax #-} module ElmInit.Types ( Result@@ -6,70 +7,78 @@ , UserDecisions(..) , ElmPackage(..) , readVersion+ , makeVersion+ , Version , makePackage , verifyElmVersion , readOneVersion ) where -import Control.Applicative ((<$>), (<*>))+import Control.Applicative+import Control.Applicative.Unicode import Control.Monad ((<=<)) import Data.Aeson as Aeson (ToJSON, Value, object, toJSON, (.=)) import Data.Text (Text, pack)-import Data.Version (Version (Version), makeVersion,- parseVersion, showVersion)+import Data.Traversable (sequenceA)+import Data.Version (Version (Version), parseVersion,+ showVersion)+import Prelude.Unicode import Text.ParserCombinators.ReadP (readP_to_S) - type Result = Either Text () -data CmdArgs = CmdArgs { workingDirectory :: FilePath }+data CmdArgs = CmdArgs { workingDirectory ∷ FilePath } -data UserDecisions = Default { projectName :: Text- , sourceFolder :: FilePath- , version :: Version- , summary :: Text- , repository :: Text- , license :: Text- , elmVersion :: Text- , mainFileName :: String- , addIndex :: Bool+data UserDecisions = Default { projectName ∷ Text+ , sourceFolder ∷ FilePath+ , version ∷ Version+ , summary ∷ Text+ , repository ∷ Text+ , license ∷ Text+ , elmVersion ∷ Text+ , mainFileName ∷ String+ , addIndex ∷ Bool } -data ElmPackage = ElmPackage { pkgVersion :: Version- , pkgSummary :: Text- , pkgRepository :: Text- , pkgLicense :: Text- , pkgDependencies :: Aeson.Value- , pkgExposedModules :: [Text]- , pkgElmVersion :: Text- , pkgSourceDirs :: [Text]+data ElmPackage = ElmPackage { pkgVersion ∷ Version+ , pkgSummary ∷ Text+ , pkgRepository ∷ Text+ , pkgLicense ∷ Text+ , pkgDependencies ∷ Aeson.Value+ , pkgExposedModules ∷ [Text]+ , pkgElmVersion ∷ Text+ , pkgSourceDirs ∷ [Text] } -readVersion :: String -> [(Version, String)]+readVersion ∷ String → [(Version, String)] readVersion = readP_to_S parseVersion +makeVersion :: [Int] -> Version+makeVersion = flip Version []++ instance Aeson.ToJSON ElmPackage where toJSON = object . sequenceA- [ ("version" .=) . showVersion . pkgVersion- , ("summary" .=) . pkgSummary- , ("repository" .=) . pkgRepository- , ("license" .=) . pkgLicense- , ("dependencies" .=) . pkgDependencies- , ("exposed-modules" .=) . pkgExposedModules- , ("elm-version" .=) . pkgElmVersion- , ("source-directories".=). pkgSourceDirs+ [ ("version" .=) ∘ showVersion ∘ pkgVersion+ , ("summary" .=) ∘ pkgSummary+ , ("repository" .=) ∘ pkgRepository+ , ("license" .=) ∘ pkgLicense+ , ("dependencies" .=) ∘ pkgDependencies+ , ("exposed-modules" .=) ∘ pkgExposedModules+ , ("elm-version" .=) ∘ pkgElmVersion+ , ("source-directories".=)∘ pkgSourceDirs ] -emptyDecisions :: UserDecisions+emptyDecisions ∷ UserDecisions emptyDecisions = Default { summary = "" , repository = ""@@ -83,27 +92,27 @@ } -makePackage :: UserDecisions -> ElmPackage+makePackage ∷ UserDecisions → ElmPackage makePackage = ElmPackage <$> version- <*> summary- <*> repository- <*> license- <*> const (object [("elm-lang/core", "2.0.0 <= v < 3.0.0")])- <*> const []- <*> elmVersion- <*> (:[]) . pack . sourceFolder+ ⊛ summary+ ⊛ repository+ ⊛ license+ ⊛ const (object [("elm-lang/core", "2.0.0 <= v < 3.0.0")])+ ⊛ const []+ ⊛ elmVersion+ ⊛ (:[]) . pack . sourceFolder -readOneVersion :: String -> Either Text Version-readOneVersion = verif . readVersion+readOneVersion ∷ String → Either Text Version+readOneVersion = verif ∘ readVersion where verif ((v, []):_) = return v verif [] = Left "Version must have this structure: 1.2.3" verif (_:xs) = verif xs -verifyElmVersion :: String -> Either Text Version+verifyElmVersion ∷ String → Either Text Version verifyElmVersion = hasElmStructure <=< readOneVersion where hasElmStructure v@(Version [ _, _, _ ] []) = Right v
src/ElmInit/Util.hs view
@@ -1,33 +1,40 @@+{-# LANGUAGE UnicodeSyntax #-} module ElmInit.Util ( exists , getOr , enumerate+ , bool ) where -import Control.Applicative ((<$>), (<*>))-import Control.Exception (IOException, catch)-import Data.Bool (bool)-import Data.Maybe (fromMaybe)-import System.Directory (doesDirectoryExist, doesFileExist)+import Control.Applicative ((<$>))+import Control.Applicative.Unicode+import Control.Exception (IOException, catch)+import Prelude.Unicode+import System.Directory (doesDirectoryExist, doesFileExist) -exists :: FilePath -> IO Bool+bool :: a -> a -> Bool -> a+bool a _ False = a+bool _ a True = a+++exists ∷ FilePath → IO Bool exists = (>>=) <$> doesFileExist- <*> (flip bool+ ⊛ (flip bool (return True)- . doesDirectoryExist)+ ∘ doesDirectoryExist) -getOr :: Read a => a -> IO a+getOr ∷ Read a ⇒ a → IO a getOr =- catch readLn . handler+ catch readLn ∘ handler where- handler :: a -> IOException -> IO a- handler = const . return+ handler ∷ a → IOException → IO a+ handler = const ∘ return -enumerate :: Int -> [a] -> [(Int,a)]+enumerate ∷ Int → [a] → [(Int,a)] enumerate from l = zip [from..(length l)] l
src/Main.hs view
@@ -1,58 +1,68 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE UnicodeSyntax #-} module Main (main) where -import Control.Applicative ((<$>), (<*>))-import Control.Arrow as Arrow (first)-import Control.Monad (join)-import Data.Aeson.Encode.Pretty (encodePretty)-import Data.Bool (bool)-import qualified Data.ByteString as ByteString (ByteString, hPut)-import qualified Data.ByteString.Char8 as CBS (pack, unpack)-import qualified Data.ByteString.Lazy as LBS (hPut)-import Data.Char (isUpper)-import Data.FileEmbed (embedFile)-import Data.Text as Text (Text, append, pack, unpack)-import qualified Data.Text.IO as TextIO (getLine, putStrLn)+import Control.Applicative ((<$>), (<*>))+import Control.Applicative.Unicode+import Control.Arrow as Arrow (first)+import Control.Monad (join, void, when)+import Control.Monad.Unicode+import Data.Aeson.Encode.Pretty (encodePretty)+import qualified Data.ByteString as ByteString (ByteString, hPut,+ writeFile)+import qualified Data.ByteString.Char8 as CBS (pack, unpack)+import qualified Data.ByteString.Lazy as LBS (hPut)+import Data.Char (isUpper)+import Data.FileEmbed (embedFile)+import Data.Monoid.Unicode+import Data.Text as Text (Text, pack, unpack)+import qualified Data.Text.IO as TextIO (getLine, putStrLn) import Data.Time-import Data.Version (Version (..), makeVersion,- showVersion)-import ElmInit (CmdArgs (..), Result,- UserDecisions (..), askChoices,- askChoicesWithOther, exists,- makePackage, verifyElmVersion)-import Prelude hiding (putStrLn)-import System.Directory (createDirectoryIfMissing,- doesDirectoryExist, doesFileExist,- getCurrentDirectory, makeAbsolute)-import System.Environment (getArgs)-import System.FilePath (isValid, takeBaseName, takeExtension,- (</>))-import System.IO (IOMode (WriteMode), withFile)-import Text.Printf (printf)+import ElmInit.Types (makeVersion, Version)+import ElmInit (CmdArgs (..), Result,+ UserDecisions (..), askChoices,+ askChoicesWithOther, exists,+ makePackage, verifyElmVersion)+import ElmInit.Util (bool)+import Prelude hiding (putStrLn)+import Prelude.Unicode+import System.Directory (createDirectoryIfMissing,+ doesDirectoryExist, doesFileExist,+ getCurrentDirectory, makeAbsolute,+ withCurrentDirectory)+import System.Environment (getArgs)+import System.FilePath (isValid, takeBaseName,+ takeExtension, (</>))+import System.IO (IOMode (WriteMode), withFile)+import System.Process (callProcess)+import Text.Printf (printf) -standardDirectories :: [FilePath]+standardDirectories ∷ [FilePath] standardDirectories = [ "elm-stuff" ] -standardSourceFolders :: [FilePath]+standardSourceFolders ∷ [FilePath] standardSourceFolders = [ "src" ] -standardFiles :: [(FilePath, Maybe ByteString.ByteString)]+standardFiles ∷ [(FilePath, Maybe ByteString.ByteString)] standardFiles = [ ("README.md", Nothing) ] -standardSourceFiles :: [(FilePath, Maybe ByteString.ByteString)]+standardSourceFiles ∷ [(FilePath, Maybe ByteString.ByteString)] standardSourceFiles = [] -mainFile :: String -> ByteString.ByteString-mainFile = CBS.pack . printf (CBS.unpack $(embedFile "resources/Main.elm"))+mainFile ∷ String → ByteString.ByteString+mainFile = CBS.pack ∘ printf (CBS.unpack $(embedFile "resources/Main.elm")) -indexHtml :: String -> ByteString.ByteString-indexHtml = CBS.pack . printf (CBS.unpack $(embedFile "resources/index.html"))+indexHtml ∷ String → ByteString.ByteString+indexHtml = CBS.pack ∘ printf (CBS.unpack $(embedFile "resources/index.html")) -standardLicenses :: [(Text, Maybe ByteString.ByteString)]+gitignore ∷ ByteString.ByteString+gitignore = $(embedFile "resources/.gitignore")++standardLicenses ∷ [(Text, Maybe ByteString.ByteString)] standardLicenses = [ ("None" , Nothing ) , ("BSD3" , Just $(embedFile "resources/licenses/BSD3" ))@@ -64,177 +74,189 @@ , ("GPLv3" , Just $(embedFile "resources/licenses/GPLv3" )) ] -defaultProjectVersion :: Version+defaultProjectVersion ∷ Version defaultProjectVersion = makeVersion [1, 0, 0] -defaultElmVersion :: Text+defaultElmVersion ∷ Text defaultElmVersion = "0.15.0 <= v < 0.16.0" -availableLicenses :: [Text]+availableLicenses ∷ [Text] availableLicenses = fst $ unzip standardLicenses -elmConfigName :: FilePath+elmConfigName ∷ FilePath elmConfigName = "elm-package.json" -getCmdArgs :: IO CmdArgs-getCmdArgs =- fmap CmdArgs- (getArgs >>=- (\args ->- case args of- [] -> getCurrentDirectory- [x] -> makeAbsolute x- _ -> error "Too many arguments")) -- I'm so sorry+getCmdArgs ∷ IO CmdArgs+getCmdArgs = CmdArgs <$> (getArgs ≫= handleDir)+ where+ handleDir [] = getCurrentDirectory+ handleDir [x] = makeAbsolute x+ handleDir _ = error "Too many arguments" -- I'm so sorry -verifyWD :: FilePath -> IO FilePath+verifyWD ∷ FilePath → IO FilePath verifyWD wd =- doesFileExist wd >>=+ doesFileExist wd ≫= bool- (doesDirectoryExist wd >>=+ (doesDirectoryExist wd ≫= bool- (TextIO.putStrLn "the chosen directory does not exist yet, shall I create it? [y/N]"- >> getResp >>=+ (TextIO.putStrLn "the chosen directory does not exist yet, shall I create it? [y/N]" >>+ getResp ≫= bool (error "Project directory does not exist") -- I'm so sorry- makeDirs- >> return wd)- (return wd))+ makeDirs ≫+ return wd)+ (return wd)) (error "The chosen directory is a file, you'll have to choose a different name") -- I'm so sorry where- getResp :: IO Bool- getResp = flip elem ["y", "yes"] <$> TextIO.getLine+ getResp ∷ IO Bool+ getResp = (∈ ["y", "yes"]) <$> TextIO.getLine makeDirs = createDirectoryIfMissing True wd -getUserDecisions :: FilePath -> IO UserDecisions+getUserDecisions ∷ FilePath → IO UserDecisions getUserDecisions wd = Default <$> askChoicesWithOther "project name?" 0 return [pack $ takeBaseName wd]- <*> askChoicesWithOther+ ⊛ askChoicesWithOther "choose a source folder name" 0- ((bool (Left "The filepath must be valid") <$> return <*> isValid) . unpack) -- filepath path verifier+ ((bool (Left "The filepath must be valid") <$> return ⊛ isValid) ∘ unpack) -- filepath path verifier (map pack standardSourceFolders)- <*> askChoicesWithOther+ ⊛ askChoicesWithOther "initial project version?" 0- (verifyElmVersion . unpack)- [pack $ showVersion defaultProjectVersion]- <*> (TextIO.putStrLn "a quick summary" >> TextIO.getLine)- <*> (TextIO.putStrLn "project repository url" >> TextIO.getLine)- <*> askChoicesWithOther+ (verifyElmVersion ∘ unpack)+ [pack $ show defaultProjectVersion]+ ⊛ (TextIO.putStrLn "a quick summary" ≫ TextIO.getLine)+ ⊛ (TextIO.putStrLn "project repository url" ≫ TextIO.getLine)+ ⊛ askChoicesWithOther "choose a license" 0 return availableLicenses- <*> askChoicesWithOther+ ⊛ askChoicesWithOther "select the elm-version" 0 return [defaultElmVersion]- <*> askChoicesWithOther+ ⊛ askChoicesWithOther "What sould be the Main file?" 0 (isValidMainFile . unpack) ["Main.elm"]- <*> ((== "Yes") <$> askChoices+ ⊛ ((≡ "Yes") <$> askChoices "Should I create an index.html file?" 0 ["Yes", "No"] ) -isValidMainFile :: String -> Either Text String+isValidMainFile ∷ String → Either Text String isValidMainFile file | null file = Left "Filename cannot be 𝜖"- | not $ isUpper (head file) = Left "Module names (and their files) have to start with uppercase"- | ".elm" /= takeExtension file = Left "Elm modules (such as this main file) have to end with the fileending \".elm\""+ | not $ isUpper (head file) =+ Left "Module names (and their files) have to start with uppercase"+ | ".elm" ≢ takeExtension file =+ Left "Elm modules (such as this main file) have to end with the fileending \".elm\"" | otherwise = return file -mkFiles :: [(FilePath, Maybe ByteString.ByteString)] -> IO [Result]+mkFiles ∷ [(FilePath, Maybe ByteString.ByteString)] → IO [Result] mkFiles = mapM (uncurry mkFile) -mkFile :: FilePath -> Maybe ByteString.ByteString -> IO Result-mkFile name defaultFile = exists name >>=+mkFile ∷ FilePath → Maybe ByteString.ByteString → IO Result+mkFile name defaultFile = exists name ≫= bool (withFile name WriteMode- (flip (maybe (return ())) defaultFile . ByteString.hPut)- >> return (Right ()))- (return $ Left $ "file " `append` pack name `append` " already exists")+ (flip (maybe (return ())) defaultFile ∘ ByteString.hPut) ≫+ return (Right ()))+ (return $ Left $ "file " ⊕ pack name ⊕ " already exists") -mkSourceFiles :: FilePath -> UserDecisions -> IO [Result]-mkSourceFiles wd (Default { mainFileName = mfn, sourceFolder = sourceF, addIndex = makeIndex }) = do+mkSourceFiles ∷ UserDecisions → IO [Result]+mkSourceFiles (Default { mainFileName = mfn, sourceFolder = sourceF, addIndex = makeIndex }) = do let mainModule = takeBaseName mfn- mainFileRes <- mkFile (wd </> sourceF </> mfn) $ Just $ mainFile mainModule- indexFileRes <- if makeIndex- then mkFile (wd </> "index.html") $ Just $ indexHtml mainModule+ mainFileRes ← mkFile (sourceF </> mfn) $ Just $ mainFile mainModule+ indexFileRes ← if makeIndex+ then mkFile "index.html" $ Just $ indexHtml mainModule else return $ return ()- others <- mkFiles $ flip map standardSourceFiles $ Arrow.first ((wd </> sourceF) </>)+ others ← mkFiles standardSourceFiles return $ mainFileRes:indexFileRes:others -mkDirs :: FilePath -> [FilePath] -> IO ()-mkDirs = mapM_ . (createDirectoryIfMissing True .) . (</>)+mkDirs ∷ [FilePath] → IO ()+mkDirs = mapM_ (createDirectoryIfMissing True) -writeConf :: FilePath -> UserDecisions -> IO ()-writeConf wd =+writeConf ∷ UserDecisions → IO ()+writeConf = withFile- (wd </> elmConfigName)+ elmConfigName WriteMode- . flip LBS.hPut . encodePretty . makePackage+ ∘ flip LBS.hPut ∘ encodePretty ∘ makePackage -putLicense :: FilePath -> Text -> IO ()-putLicense wd name =+putLicense ∷ Text → IO ()+putLicense name = case join $ lookup name standardLicenses of- Nothing -> return ()- Just contents -> do+ Nothing → return ()+ Just contents → do TextIO.putStrLn "The project owner(s): (for the license)"- authors <- getLine- (year, _, _) <- toGregorian . utctDay <$> getCurrentTime- writeFile (wd </> "LICENSE") $+ authors ← getLine+ (year, _, _) ← toGregorian ∘ utctDay <$> getCurrentTime+ writeFile "LICENSE" $ printf (CBS.unpack contents) year $ if null authors then "[project owners]" else authors -main :: IO ()+initGit ∷ IO ()+initGit = do+ TextIO.putStrLn "Shall I initialize a git repository? [Y/n]"+ answ ← getLine+ when (answ `elem` ["y", "Y", ""]) $ do+ ByteString.writeFile ".gitignore" gitignore+ void $ callProcess "git" ["init"]+++main ∷ IO () main = do -- get either the working directory or the directory the user entered- wd <- getCmdArgs >>= (verifyWD . workingDirectory)+ wd ← getCmdArgs ≫= (verifyWD ∘ workingDirectory) - -- ask all important input first- decisions <- getUserDecisions wd+ withCurrentDirectory wd $ do - -- create necessary directories- mkDirs wd (sourceFolder decisions : standardDirectories)+ -- ask all important input first+ decisions ← getUserDecisions wd - -- create non-dynamic files, collect errors- resStatic <- mkFiles $ map (Arrow.first (wd </>)) standardFiles+ -- create necessary directories+ mkDirs (sourceFolder decisions : standardDirectories) - -- create Elm source files, collect errors- resSource <- mkSourceFiles wd decisions+ -- create non-dynamic files, collect errors+ resStatic ← mkFiles standardFiles - -- write the package config based on the user decisions- writeConf wd decisions+ -- create Elm source files, collect errors+ resSource ← mkSourceFiles decisions - -- write the choosen license- _ <- putLicense wd (license decisions)+ -- write the package config based on the user decisions+ writeConf decisions - -- report all errors- mapM_ (either TextIO.putStrLn return) (resStatic ++ resSource)+ -- write the choosen license+ _ ← putLicense (license decisions)++ initGit++ -- report all errors+ mapM_ (either TextIO.putStrLn return) (resStatic ⧺ resSource)