summoner 1.0.4 → 1.0.5
raw patch · 10 files changed
+234/−67 lines, 10 files
Files
- CHANGELOG.md +14/−0
- README.md +9/−3
- src/Summoner/CLI.hs +14/−0
- src/Summoner/Config.hs +9/−1
- src/Summoner/Default.hs +2/−2
- src/Summoner/Project.hs +29/−5
- src/Summoner/ProjectData.hs +8/−1
- src/Summoner/Question.hs +9/−4
- src/Summoner/Template.hs +139/−50
- summoner.cabal +1/−1
CHANGELOG.md view
@@ -1,5 +1,19 @@ # Summoner +1.0.5+=====++* [#100](https://github.com/kowainik/summoner/issues/100):+ Bump up to `ghc-8.4.3`. Add support for `Ghc843` in code+ and make it default.+* Make CI badges in README be shown depending on the chosen options.+* [#99](https://github.com/kowainik/summoner/issues/99):+ UseTravis-specific env variable `TRAVIS_BUILD_DIR` in created travis file.+* [#97](https://github.com/kowainik/summoner/issues/97):+ Add cabal to created travis file.+* [#96](https://github.com/kowainik/summoner/issues/96):+ Add option to choose `cabal`, `stack` or both.+ 1.0.4 ===== * Bump up `tomland` to version `0.3`.
README.md view
@@ -1,7 +1,6 @@ # 🔮 Summoner [](http://travis-ci.org/kowainik/summoner)-[](https://ci.appveyor.com/project/kowainik/summoner) [](https://github.com/kowainik/summoner/blob/master/LICENSE) [](https://hackage.haskell.org/package/summoner) [](http://stackage.org/lts/package/summoner)@@ -31,7 +30,7 @@ or - $ stack install summoner --resolver nightly-2018-06-14+ $ stack install summoner You can turn on the bash auto-completion by running the following command: @@ -65,6 +64,10 @@ ###### Global keys +* `cabal` – `true` if you want to build you project with `cabal`,+ `false` if you don't. If not specified it would be asked during each run of the `summoner`.+* `stack` – `true` if you want to build your project with `stack`,+ `false` if you don't. If not specified it would be asked during each run of the `summoner`. * `owner` – `GitHub` login. * `fullName` – full name. * `email` – e-mail address.@@ -115,13 +118,16 @@ See the basic usage syntax below (you can check it out with `summon --help` command): ```-summon PROJECT_NAME [with [OPTIONS]] [without [OPTIONS]]+summon PROJECT_NAME [--cabal] [--stack]+ [with [OPTIONS]] [without [OPTIONS]] [-f|--file FILENAME] [--prelude-package PACKAGE_NAME] [--prelude-module MODULE_NAME] Available global options: -h, --help Show this help text -v, --version Show summoner's version+ --cabal Cabal support for the project+ --stack Stack support for the project -f, --file FILENAME Path to the toml file with configurations. If not specified '~/.summoner.toml' will be used if present --prelude-package PACKAGE_NAME
src/Summoner/CLI.hs view
@@ -187,9 +187,21 @@ <> metavar "MODULE_NAME" <> help "Name for the module of the custom prelude to use in the project" +cabalP :: Parser Decision+cabalP = flag Idk Yes+ $ long "cabal"+ <> help "Cabal support for the project"++stackP :: Parser Decision+stackP = flag Idk Yes+ $ long "stack"+ <> help "Stack support for the project"+ optsP :: Parser InitOpts optsP = do projectName <- strArgument (metavar "PROJECT_NAME")+ cabal <- cabalP+ stack <- stackP with <- optional withP without <- optional withoutP file <- optional fileP@@ -199,6 +211,8 @@ pure $ InitOpts projectName file $ (maybeToMonoid $ with <> without) { cPrelude = Last $ Prelude <$> preludePack <*> preludeMod+ , cCabal = cabal+ , cStack = stack } versionP :: Parser (a -> a)
src/Summoner/Config.hs view
@@ -49,6 +49,8 @@ , cEmail :: p :- Text , cLicense :: p :- License , cGhcVer :: p :- [GhcVer]+ , cCabal :: Decision+ , cStack :: Decision , cGitHub :: Decision , cTravis :: Decision , cAppVey :: Decision@@ -91,6 +93,8 @@ , cEmail = Last (Just "xrom.xkov@gmail.com") , cLicense = Last (Just $ License "MIT") , cGhcVer = Last (Just [])+ , cCabal = Idk+ , cStack = Idk , cGitHub = Idk , cTravis = Idk , cAppVey = Idk@@ -112,6 +116,8 @@ <*> lastT Toml.text "email" .= cEmail <*> lastT license "license" .= cLicense <*> lastT ghcVerArr "ghcVersions" .= cGhcVer+ <*> decision "cabal" .= cCabal+ <*> decision "stack" .= cStack <*> decision "github" .= cGitHub <*> decision "travis" .= cTravis <*> decision "appveyor" .= cAppVey@@ -169,7 +175,9 @@ <*> fin "fullName" cFullName <*> fin "email" cEmail <*> fin "license" cLicense- <*> fin "ghcersions" cGhcVer+ <*> fin "ghcVersions" cGhcVer+ <*> pure cCabal+ <*> pure cStack <*> pure cGitHub <*> pure cTravis <*> pure cAppVey
src/Summoner/Default.hs view
@@ -14,14 +14,14 @@ import System.Directory (getHomeDirectory) import System.FilePath ((</>)) -import Summoner.ProjectData (GhcVer (Ghc822))+import Summoner.ProjectData (GhcVer (Ghc843)) ---------------------------------------------------------------------------- -- Default Settings ---------------------------------------------------------------------------- defaultGHC :: GhcVer-defaultGHC = Ghc822+defaultGHC = Ghc843 defaultTomlFile :: String defaultTomlFile = ".summoner.toml"
src/Summoner/Project.hs view
@@ -14,7 +14,7 @@ import System.Info (os) import System.Process (readProcess) -import Summoner.Ansi (infoMessage, successMessage)+import Summoner.Ansi (errorMessage, infoMessage, successMessage) import Summoner.Config (Config, ConfigP (..)) import Summoner.Default (currentYear, defaultGHC) import Summoner.License (License (..), customizeLicense, githubLicenseQueryNames, licenseNames)@@ -22,7 +22,8 @@ import Summoner.ProjectData (CustomPrelude (..), Decision (..), ProjectData (..), parseGhcVer, showGhcVer, supportedGhcVers) import Summoner.Question (checkUniqueName, choose, chooseYesNo, chooseYesNoBool, falseMessage,- query, queryDef, queryManyRepeatOnFail, trueMessage)+ query, queryDef, queryManyRepeatOnFail, targetMessageWithText,+ trueMessage) import Summoner.Template (createStackTemplate) import Summoner.Text (intercalateMap, packageToModule) import Summoner.Tree (showTree, traverseTree)@@ -39,6 +40,9 @@ generateProject :: Text -> Config -> IO () generateProject projectName Config{..} = do repo <- checkUniqueName projectName+ -- decide cabal stack or both+ (cabal, stack) <- getCabalStack (cCabal, cStack)+ owner <- queryDef "Repository owner: " cOwner description <- query "Short project description: " nm <- queryDef "Author: " cFullName@@ -67,7 +71,7 @@ -- Library/Executable/Tests/Benchmarks flags github <- decisionToBool cGitHub "GitHub integration" travis <- ifGithub github "Travis CI integration" cTravis- appVey <- ifGithub github "AppVeyor CI integration" cAppVey+ appVey <- ifGithub (stack && github) "AppVeyor CI integration" cAppVey privat <- ifGithub github "private repository" cPrivate script <- decisionToBool cScript "build script" isLib <- decisionToBool cLib "library target"@@ -85,7 +89,7 @@ let extensions = cExtensions putTextLn $ "The project will be created with the latest resolver for default GHC-" <> showGhcVer defaultGHC- testedVersions <- (sortNub . (defaultGHC :)) <$> case cGhcVer of+ testedVersions <- sortNub . (defaultGHC :) <$> case cGhcVer of [] -> do putTextLn "Additionally you can specify versions of GHC to test with (space-separated): " infoMessage $ "Supported by 'summoner' GHCs: " <> intercalateMap " " showGhcVer supportedGhcVers@@ -163,5 +167,25 @@ pure $ Just $ Prelude p m noDo = pure Nothing chooseYesNo "custom prelude" yesDo noDo- Last prelude@(Just (Prelude p _)) -> do+ Last prelude@(Just (Prelude p _)) -> prelude <$ successMessage ("Custom prelude " <> p <> " will be used in the project")++ -- get what build tool to use in the project+ -- If user chose only one during CLI, we assume to use only that one.+ getCabalStack :: (Decision, Decision) -> IO (Bool, Bool)+ getCabalStack = \case+ (Idk, Idk) -> decisionToBool cCabal "cabal" >>= \c ->+ if c then decisionToBool cStack "stack" >>= \s -> pure (c, s)+ else stackMsg True >> pure (False, True)+ (Nop, Nop) -> errorMessage "Neither cabal nor stack was chosen" >> exitFailure+ (Yes, Yes) -> output (True, True)+ (Yes, _) -> output (True, False)+ (_, Yes) -> output (False, True)+ (Nop, Idk) -> output (False, True)+ (Idk, Nop) -> output (True, False)+ where+ output :: (Bool, Bool) -> IO (Bool, Bool)+ output x@(c, s) = cabalMsg c >> stackMsg s >> pure x++ cabalMsg c = targetMessageWithText c "Cabal" "used in this project"+ stackMsg c = targetMessageWithText c "Stack" "used in this project"
src/Summoner/ProjectData.hs view
@@ -46,6 +46,8 @@ , base :: Text -- ^ Base library to use , prelude :: Maybe CustomPrelude -- ^ custom prelude to be used , extensions :: [Text] -- ^ default extensions+ , cabal :: Bool+ , stack :: Bool } deriving (Show) -- | Used for detecting the user decision during CLI input.@@ -74,6 +76,7 @@ | Ghc801 | Ghc802 | Ghc822+ | Ghc843 deriving (Eq, Ord, Show, Enum, Bounded) -- | Supported by @summoner@ GHC versions for project templates.@@ -86,6 +89,7 @@ showGhcVer Ghc801 = "8.0.1" showGhcVer Ghc802 = "8.0.2" showGhcVer Ghc822 = "8.2.2"+showGhcVer Ghc843 = "8.4.3" -- | Converts numeric dot-separated GHC version into 'GhcVer'. parseGhcVer :: Text -> Maybe GhcVer@@ -93,6 +97,7 @@ parseGhcVer "8.0.1" = Just Ghc801 parseGhcVer "8.0.2" = Just Ghc802 parseGhcVer "8.2.2" = Just Ghc822+parseGhcVer "8.4.3" = Just Ghc843 parseGhcVer _ = Nothing -- | Returns latest known LTS resolver for all GHC versions except default one.@@ -100,13 +105,15 @@ latestLts Ghc7103 = "6.35" latestLts Ghc801 = "7.24" latestLts Ghc802 = "9.21"-latestLts Ghc822 = "11.10"+latestLts Ghc822 = "11.17"+latestLts Ghc843 = "12.0" baseNopreludeVer :: GhcVer -> Text baseNopreludeVer Ghc7103 = "4.8.0.2" baseNopreludeVer Ghc801 = "4.9.0.0" baseNopreludeVer Ghc802 = "4.9.1.0" baseNopreludeVer Ghc822 = "4.10.1.0"+baseNopreludeVer Ghc843 = "4.11.1.0" data CustomPrelude = Prelude { cpPackage :: Text
src/Summoner/Question.hs view
@@ -13,6 +13,8 @@ , queryManyRepeatOnFail , checkUniqueName + , targetMessageWithText+ , trueMessage , falseMessage ) where@@ -71,10 +73,13 @@ chooseYesNoBool target = chooseYesNo target (pure True) (pure False) targetMessage :: Bool -> Text -> IO Bool-targetMessage result target = do- let (color, actionResult) = case result of- False -> (Cyan, " won't be added to the project")- True -> (Green, " will be added to the project")+targetMessage result target = targetMessageWithText result target "added to the project"++targetMessageWithText :: Bool -> Text -> Text -> IO Bool+targetMessageWithText result target text = do+ let (color, actionResult) = if result+ then (Green, " will be " <> text)+ else (Cyan, " won't be" <> text) beautyPrint [italic, bold, setColor color] $ " " <> headToUpper target beautyPrint [setColor color] actionResult
src/Summoner/Template.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ViewPatterns #-} -- | This module contains functions for stack template creation. @@ -24,14 +25,15 @@ -- Stack File Creation ---------------------------------------------------------------------------- -emptyIfNot :: Bool -> Text -> Text-emptyIfNot p txt = if p then txt else ""+emptyIfNot :: Monoid m => Bool -> m -> m+emptyIfNot p val = if p then val else mempty -- | Creating template file to use in `stack new` command createStackTemplate :: ProjectData -> TreeFs createStackTemplate ProjectData{..} = Dir (toString repo) $ [ File (toString repo <> ".cabal") ( createCabalTop+ <> emptyIfNot github createCabalGit <> emptyIfNot isLib createCabalLib <> emptyIfNot isExe ( createCabalExe@@ -40,14 +42,13 @@ <> emptyIfNot bench ( createCabalBenchmark $ emptyIfNot isLib $ ", " <> repo )- <> emptyIfNot github createCabalGit ) , File "README.md" readme , File "CHANGELOG.md" changelog , File "LICENSE" licenseText ] ++ createCabalFiles- ++ createStackYamls testedVersions+ ++ emptyIfNot stack (createStackYamls testedVersions) ++ [File ".gitignore" gitignore | github] ++ [File ".travis.yml" travisYml | travis] ++ [File "appveyor.yml" appVeyorYml | appVey]@@ -99,6 +100,15 @@ [] -> "" xs -> "default-extensions: " <> T.intercalate "\n " xs + createCabalGit :: Text+ createCabalGit =+ [text|+ source-repository head+ type: git+ location: https://github.com/${owner}/${repo}.git+ $endLine+ |]+ createCabalLib :: Text createCabalLib = [text|@@ -162,21 +172,12 @@ $endLine |] - createCabalGit :: Text- createCabalGit =- [text|- source-repository head- type: git- location: https://github.com/${owner}/${repo}.git- $endLine- |]- createCabalFiles :: [TreeFs] createCabalFiles =- [ Dir "app" [exeFile] | isExe ]- ++ [ Dir "test" [testFile] | test ]- ++ [ Dir "benchmark" [benchmarkFile] | bench ]- ++ [ Dir "src" $ [libFile] ++ preludeFile | isLib ]+ [ Dir "app" [exeFile] | isExe ]+ ++ [ Dir "test" [testFile] | test ]+ ++ [ Dir "benchmark" [benchmarkFile] | bench ]+ ++ [ Dir "src" $ libFile : preludeFile | isLib ] testFile :: TreeFs testFile = File "Spec.hs"@@ -255,9 +256,9 @@ # $repo []($hackageLink)- [](${travisLink})- [](${appVeyorLink}) [](${licenseLink})+ $travisBadge+ $appVeyorBadge $description $endLine@@ -267,14 +268,21 @@ "https://img.shields.io/hackage/v/" <> repo <> ".svg" hackageLink :: Text = "https://hackage.haskell.org/package/" <> repo+ travisShield :: Text = "https://secure.travis-ci.org/" <> owner <> "/" <> repo <> ".svg" travisLink :: Text = "https://travis-ci.org/" <> owner <> "/" <> repo+ travisBadge :: Text = emptyIfNot travis+ [text|[](${travisLink})|]+ appVeyorShield :: Text = "https://ci.appveyor.com/api/projects/status/github/" <> owner <> "/" <> repo <> "?branch=master&svg=true" appVeyorLink :: Text = "https://ci.appveyor.com/project/" <> owner <> "/" <> repo+ appVeyorBadge :: Text = emptyIfNot appVey+ [text|[](${appVeyorLink})|]+ licenseShield :: Text = "https://img.shields.io/badge/license-" <> T.replace "-" "--" license <> "-blue.svg" licenseLink :: Text =@@ -362,8 +370,18 @@ -- create travis.yml template travisYml :: Text travisYml =- let travisMtr = T.concat (map (travisMatrixItem . showGhcVer) (delete defaultGHC testedVersions))- defGhc = showGhcVer defaultGHC in+ let travisStackMtr = emptyIfNot stack $+ T.concat (map travisStackMatrixItem $ delete defaultGHC testedVersions)+ <> travisStackMatrixDefaultItem+ travisCabalMtr = emptyIfNot cabal $+ T.concat $ map travisCabalMatrixItem testedVersions+ installAndScript =+ if cabal+ then if stack+ then installScriptBoth+ else installScriptCabal+ else installScriptStack+ in [text| sudo: true language: haskell@@ -374,50 +392,121 @@ cache: directories: - "$$HOME/.stack"- - "$$HOME/build/${owner}/${repo}/.stack-work"+ - "$$TRAVIS_BUILD_DIR/.stack-work" matrix: include: - $travisMtr+ $travisCabalMtr+ $travisStackMtr - - ghc: $defGhc- env: GHCVER='${defGhc}' STACK_YAML="$$HOME/build/${owner}/${repo}/stack.yaml"+ $installAndScript - addons:- apt:- sources:- - sourceline: 'ppa:hvr/ghc'- packages:- - libgmp-dev+ notifications:+ email: false+ $endLine+ |] - before_install:- - mkdir -p ~/.local/bin- - export PATH="$$HOME/.local/bin:$$PATH"- - travis_retry curl -L 'https://www.stackage.org/stack/linux-x86_64' | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'- - stack --version+ cabalTest :: Text+ cabalTest = if test then "cabal new-test" else "echo 'No tests'" + travisCabalMatrixItem :: GhcVer -> Text+ travisCabalMatrixItem (showGhcVer -> ghcV) =+ [text|+ - ghc: ${ghcV}+ env: GHCVER='${ghcV}' CABALVER='head'+ os: linux+ addons:+ apt:+ sources:+ - hvr-ghc+ packages:+ - ghc-${ghcV}+ - cabal-install-head+ $endLine+ |] - install:- - travis_wait 30 stack setup --no-terminal- - stack ghc -- --version+ travisStackMatrixItem :: GhcVer -> Text+ travisStackMatrixItem (showGhcVer -> ghcV) =+ [text|+ - ghc: ${ghcV}+ env: GHCVER='${ghcV}' STACK_YAML="$$TRAVIS_BUILD_DIR/stack-$$GHCVER.yaml"+ os: linux+ addons:+ apt:+ packages:+ - libgmp-dev+ $endLine+ |] - - travis_wait 40 stack build --only-dependencies --no-terminal- - travis_wait 40 stack build --test --bench --haddock --no-run-tests --no-run-benchmarks --no-haddock-deps --no-terminal+ travisStackMatrixDefaultItem :: Text+ travisStackMatrixDefaultItem = let defGhc = showGhcVer defaultGHC in+ [text|+ - ghc: ${defGhc}+ env: GHCVER='${defGhc}' STACK_YAML="$$TRAVIS_BUILD_DIR/stack.yaml"+ os: linux+ addons:+ apt:+ packages:+ - libgmp-dev+ $endLine+ |] + installScriptBoth :: Text+ installScriptBoth =+ [text|+ install:+ - |+ if [ -z "$$STACK_YAML" ]; then+ export PATH="/opt/ghc/$$GHCVER/bin:/opt/cabal/$$CABALVER/bin:$$PATH"+ echo $$PATH+ cabal new-update+ cabal new-build --enable-tests --enable-benchmarks+ else+ mkdir -p ~/.local/bin+ export PATH="$$HOME/.local/bin:$$PATH"+ travis_retry curl -L 'https://www.stackage.org/stack/linux-x86_64' | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'+ stack --version+ stack setup --no-terminal --install-cabal 2.0.1.0+ stack ghc -- --version+ stack build --only-dependencies --no-terminal+ fi script:- - travis_wait 40 stack build --test --no-terminal+ - |+ if [ -z "$$STACK_YAML" ]; then+ ${cabalTest}+ else+ stack build --test --bench --no-run-benchmarks --no-terminal+ fi+ $endLine+ |] - notifications:- email: false+ installScriptCabal :: Text+ installScriptCabal =+ [text|+ install:+ - export PATH="/opt/ghc/$$GHCVER/bin:/opt/cabal/$$CABALVER/bin:$$PATH"+ - echo $$PATH+ - cabal new-update+ - cabal new-build --enable-tests --enable-benchmarks+ script:+ - ${cabalTest} $endLine |] - travisMatrixItem :: Text -> Text- travisMatrixItem ghcV =+ installScriptStack :: Text+ installScriptStack = [text|- - ghc: ${ghcV}- env: GHCVER='${ghcV}' STACK_YAML="$$HOME/build/${owner}/${repo}/stack-$$GHCVER.yaml"+ install:+ - mkdir -p ~/.local/bin+ - export PATH="$$HOME/.local/bin:$$PATH"+ - travis_retry curl -L 'https://www.stackage.org/stack/linux-x86_64' | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'+ - stack --version+ - stack setup --no-terminal --install-cabal 2.0.1.0+ - stack ghc -- --version+ - stack build --only-dependencies --no-terminal+ script:+ - stack build --test --bench --no-run-benchmarks --no-terminal $endLine |] @@ -427,7 +516,7 @@ where createStackYaml :: GhcVer -> TreeFs createStackYaml ghcV = let ver = case ghcV of- Ghc822 -> ""+ Ghc843 -> "" _ -> "-" <> showGhcVer ghcV in stackYaml ver (latestLts ghcV) (baseNopreludeVer ghcV) where@@ -452,7 +541,7 @@ else [text| ghc-options:- "$$locals": -fhide-sourcepaths+ "$$locals": -fhide-source-paths |]
summoner.cabal view
@@ -1,5 +1,5 @@ name: summoner-version: 1.0.4+version: 1.0.5 synopsis: Tool for creating completely configured production Haskell projects. description: Tool for creating completely configured production Haskell projects. See README.md for details.