packages feed

summoner 1.4.0.0 → 2.0.0.0

raw patch · 105 files changed

+2723/−1258 lines, 105 filesdep +colouristadep +generic-datadep +hspec-hedgehogdep −ansi-terminaldep −generic-derivingdep ~basedep ~containersPVP ok

version bump matches the API change (PVP)

Dependencies added: colourista, generic-data, hspec-hedgehog, validation-selective

Dependencies removed: ansi-terminal, generic-deriving

Dependency ranges changed: base, containers

API changes (from Hackage documentation)

- Summoner.Ansi: Black :: Color
- Summoner.Ansi: Blue :: Color
- Summoner.Ansi: Cyan :: Color
- Summoner.Ansi: Green :: Color
- Summoner.Ansi: Magenta :: Color
- Summoner.Ansi: Red :: Color
- Summoner.Ansi: White :: Color
- Summoner.Ansi: Yellow :: Color
- Summoner.Ansi: beautyPrint :: [IO ()] -> Text -> IO ()
- Summoner.Ansi: blueCode :: String
- Summoner.Ansi: bold :: IO ()
- Summoner.Ansi: boldCode :: String
- Summoner.Ansi: boldText :: Text -> IO ()
- Summoner.Ansi: data Color
- Summoner.Ansi: italic :: IO ()
- Summoner.Ansi: redCode :: String
- Summoner.Ansi: reset :: IO ()
- Summoner.Ansi: resetCode :: String
- Summoner.Ansi: setColor :: Color -> IO ()
- Summoner.CLI: [newOptsOffline] :: NewOpts -> Bool
- Summoner.Config: Config :: !p :- Text -> !p :- Text -> !p :- Text -> !p :- LicenseName -> !p :- [GhcVer] -> !Decision -> !Decision -> !Decision -> !Decision -> !Decision -> !Decision -> !Decision -> !Decision -> !Decision -> !Decision -> !Last CustomPrelude -> ![Text] -> ![Text] -> ![Text] -> !Last Source -> !Last Source -> !Any -> !Map FilePath Source -> ConfigP
- Summoner.Config: [cContributing] :: ConfigP -> !Last Source
- Summoner.Config: [cStylish] :: ConfigP -> !Last Source
- Summoner.Config: instance (Generics.Deriving.Monoid.Internal.GMonoid (p Summoner.Config.:- Data.Text.Internal.Text), Generics.Deriving.Monoid.Internal.GMonoid (p Summoner.Config.:- Summoner.License.LicenseName), Generics.Deriving.Monoid.Internal.GMonoid (p Summoner.Config.:- [Summoner.GhcVer.GhcVer])) => Generics.Deriving.Monoid.Internal.GMonoid (Summoner.Config.ConfigP p)
- Summoner.Config: instance (Generics.Deriving.Semigroup.Internal.GSemigroup (p Summoner.Config.:- Data.Text.Internal.Text), Generics.Deriving.Semigroup.Internal.GSemigroup (p Summoner.Config.:- Summoner.License.LicenseName), Generics.Deriving.Semigroup.Internal.GSemigroup (p Summoner.Config.:- [Summoner.GhcVer.GhcVer])) => Generics.Deriving.Semigroup.Internal.GSemigroup (Summoner.Config.ConfigP p)
- Summoner.Config: instance GHC.Classes.Ord k => Generics.Deriving.Monoid.Internal.GMonoid (Data.Map.Internal.Map k v)
- Summoner.Config: instance GHC.Classes.Ord k => Generics.Deriving.Semigroup.Internal.GSemigroup (Data.Map.Internal.Map k v)
- Summoner.Decision: instance Generics.Deriving.Monoid.Internal.GMonoid Summoner.Decision.Decision
- Summoner.Decision: instance Generics.Deriving.Semigroup.Internal.GSemigroup Summoner.Decision.Decision
- Summoner.GhcVer: Ghc881 :: GhcVer
- Summoner.License: None :: LicenseName
- Summoner.License: cabalLicense :: LicenseName -> Text
- Summoner.Project: fetchSources :: Bool -> Map FilePath Source -> IO [TreeFs]
- Summoner.Settings: [settingsBaseType] :: Settings -> !Text
- Summoner.Settings: [settingsContributing] :: Settings -> !Maybe Text
- Summoner.Settings: [settingsStylish] :: Settings -> !Maybe Text
- Summoner.Source: sourceT :: Key -> TomlCodec Source
+ Summoner.CLI: Config :: ConfigOpts -> Command
+ Summoner.CLI: [newOptsConnectMode] :: NewOpts -> !ConnectMode
+ Summoner.CLI: [newOptsInteractivity] :: NewOpts -> !Interactivity
+ Summoner.CLI: getCustomLicenseText :: LicenseName -> IO License
+ Summoner.CLI: runConfig :: ConfigOpts -> IO ()
+ Summoner.Config: ConfigP :: !p :- Text -> !p :- Text -> !p :- Text -> !p :- LicenseName -> !p :- [GhcVer] -> !Decision -> !Decision -> !Decision -> !Decision -> !Decision -> !Decision -> !Decision -> !Decision -> !Decision -> !Decision -> !Decision -> !Last CustomPrelude -> ![Text] -> ![Text] -> ![Text] -> !Any -> !Map FilePath Source -> ConfigP (p :: Phase)
+ Summoner.Config: [cGhActions] :: ConfigP (p :: Phase) -> !Decision
+ Summoner.Config: guessConfigFromGit :: IO PartialConfig
+ Summoner.Decision: decisionsToBools :: (Decision, Decision) -> (Bool, Bool)
+ Summoner.Decision: promptDecisionToBool :: Decision -> YesNoPrompt -> IO Bool
+ Summoner.Default: defaultConfigFileContent :: Text
+ Summoner.Default: defaultEmail :: Text
+ Summoner.Default: defaultFullName :: Text
+ Summoner.Default: defaultLicenseName :: LicenseName
+ Summoner.Default: defaultOwner :: Text
+ Summoner.GhcVer: Ghc883 :: GhcVer
+ Summoner.License: ISC :: LicenseName
+ Summoner.License: NONE :: LicenseName
+ Summoner.License: fetchLicenseCustom :: LicenseName -> Text -> Text -> IO License
+ Summoner.Mode: Interactive :: Interactivity
+ Summoner.Mode: NonInteractive :: Interactivity
+ Summoner.Mode: Offline :: ConnectMode
+ Summoner.Mode: Online :: ConnectMode
+ Summoner.Mode: data ConnectMode
+ Summoner.Mode: data Interactivity
+ Summoner.Mode: instance GHC.Classes.Eq Summoner.Mode.ConnectMode
+ Summoner.Mode: instance GHC.Classes.Eq Summoner.Mode.Interactivity
+ Summoner.Mode: instance GHC.Show.Show Summoner.Mode.ConnectMode
+ Summoner.Mode: instance GHC.Show.Show Summoner.Mode.Interactivity
+ Summoner.Mode: isNonInteractive :: Interactivity -> Bool
+ Summoner.Mode: isOffline :: ConnectMode -> Bool
+ Summoner.Project: generateProjectInteractive :: ConnectMode -> Text -> Config -> IO ()
+ Summoner.Project: generateProjectNonInteractive :: ConnectMode -> Text -> Config -> IO ()
+ Summoner.Question: doesExistProjectName :: Text -> IO Bool
+ Summoner.Settings: [settingsGhActions] :: Settings -> !Bool
+ Summoner.Source: fetchSources :: ConnectMode -> Map FilePath Source -> IO [TreeFs]
- Summoner.Ansi: boldDefault :: Text -> IO ()
+ Summoner.Ansi: boldDefault :: Text -> Text
- Summoner.CLI: NewOpts :: Text -> Bool -> Bool -> Maybe FilePath -> PartialConfig -> NewOpts
+ Summoner.CLI: NewOpts :: !Text -> !Bool -> !ConnectMode -> !Interactivity -> !Maybe FilePath -> !PartialConfig -> NewOpts
- Summoner.CLI: [newOptsCliConfig] :: NewOpts -> PartialConfig
+ Summoner.CLI: [newOptsCliConfig] :: NewOpts -> !PartialConfig
- Summoner.CLI: [newOptsConfigFile] :: NewOpts -> Maybe FilePath
+ Summoner.CLI: [newOptsConfigFile] :: NewOpts -> !Maybe FilePath
- Summoner.CLI: [newOptsIgnoreFile] :: NewOpts -> Bool
+ Summoner.CLI: [newOptsIgnoreFile] :: NewOpts -> !Bool
- Summoner.CLI: [newOptsProjectName] :: NewOpts -> Text
+ Summoner.CLI: [newOptsProjectName] :: NewOpts -> !Text
- Summoner.Config: [cAppVey] :: ConfigP -> !Decision
+ Summoner.Config: [cAppVey] :: ConfigP (p :: Phase) -> !Decision
- Summoner.Config: [cBench] :: ConfigP -> !Decision
+ Summoner.Config: [cBench] :: ConfigP (p :: Phase) -> !Decision
- Summoner.Config: [cCabal] :: ConfigP -> !Decision
+ Summoner.Config: [cCabal] :: ConfigP (p :: Phase) -> !Decision
- Summoner.Config: [cEmail] :: ConfigP -> !p :- Text
+ Summoner.Config: [cEmail] :: ConfigP (p :: Phase) -> !p :- Text
- Summoner.Config: [cExe] :: ConfigP -> !Decision
+ Summoner.Config: [cExe] :: ConfigP (p :: Phase) -> !Decision
- Summoner.Config: [cExtensions] :: ConfigP -> ![Text]
+ Summoner.Config: [cExtensions] :: ConfigP (p :: Phase) -> ![Text]
- Summoner.Config: [cFiles] :: ConfigP -> !Map FilePath Source
+ Summoner.Config: [cFiles] :: ConfigP (p :: Phase) -> !Map FilePath Source
- Summoner.Config: [cFullName] :: ConfigP -> !p :- Text
+ Summoner.Config: [cFullName] :: ConfigP (p :: Phase) -> !p :- Text
- Summoner.Config: [cGhcOptions] :: ConfigP -> ![Text]
+ Summoner.Config: [cGhcOptions] :: ConfigP (p :: Phase) -> ![Text]
- Summoner.Config: [cGhcVer] :: ConfigP -> !p :- [GhcVer]
+ Summoner.Config: [cGhcVer] :: ConfigP (p :: Phase) -> !p :- [GhcVer]
- Summoner.Config: [cGitHub] :: ConfigP -> !Decision
+ Summoner.Config: [cGitHub] :: ConfigP (p :: Phase) -> !Decision
- Summoner.Config: [cGitignore] :: ConfigP -> ![Text]
+ Summoner.Config: [cGitignore] :: ConfigP (p :: Phase) -> ![Text]
- Summoner.Config: [cLib] :: ConfigP -> !Decision
+ Summoner.Config: [cLib] :: ConfigP (p :: Phase) -> !Decision
- Summoner.Config: [cLicense] :: ConfigP -> !p :- LicenseName
+ Summoner.Config: [cLicense] :: ConfigP (p :: Phase) -> !p :- LicenseName
- Summoner.Config: [cNoUpload] :: ConfigP -> !Any
+ Summoner.Config: [cNoUpload] :: ConfigP (p :: Phase) -> !Any
- Summoner.Config: [cOwner] :: ConfigP -> !p :- Text
+ Summoner.Config: [cOwner] :: ConfigP (p :: Phase) -> !p :- Text
- Summoner.Config: [cPrelude] :: ConfigP -> !Last CustomPrelude
+ Summoner.Config: [cPrelude] :: ConfigP (p :: Phase) -> !Last CustomPrelude
- Summoner.Config: [cPrivate] :: ConfigP -> !Decision
+ Summoner.Config: [cPrivate] :: ConfigP (p :: Phase) -> !Decision
- Summoner.Config: [cStack] :: ConfigP -> !Decision
+ Summoner.Config: [cStack] :: ConfigP (p :: Phase) -> !Decision
- Summoner.Config: [cTest] :: ConfigP -> !Decision
+ Summoner.Config: [cTest] :: ConfigP (p :: Phase) -> !Decision
- Summoner.Config: [cTravis] :: ConfigP -> !Decision
+ Summoner.Config: [cTravis] :: ConfigP (p :: Phase) -> !Decision
- Summoner.Config: type Config = ConfigP 'Final
+ Summoner.Config: type Config = ConfigP 'Final
- Summoner.Config: type PartialConfig = ConfigP 'Partial
+ Summoner.Config: type PartialConfig = ConfigP 'Partial
- Summoner.Decision: decisionToBool :: Decision -> YesNoPrompt -> IO Bool
+ Summoner.Decision: decisionToBool :: Decision -> Bool
- Summoner.Project: generateProject :: Bool -> Text -> Config -> IO ()
+ Summoner.Project: generateProject :: Interactivity -> ConnectMode -> Text -> Config -> IO ()
- Summoner.Settings: Settings :: !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !LicenseName -> !License -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> ![GhcVer] -> !Text -> !Maybe CustomPrelude -> ![Text] -> ![Text] -> ![Text] -> !Bool -> !Bool -> !Maybe Text -> !Maybe Text -> !Bool -> ![TreeFs] -> Settings
+ Summoner.Settings: Settings :: !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !LicenseName -> !License -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> ![GhcVer] -> !Maybe CustomPrelude -> ![Text] -> ![Text] -> ![Text] -> !Bool -> !Bool -> !Bool -> ![TreeFs] -> Settings
- Summoner.Source: fetchSource :: Bool -> Source -> IO (Maybe Text)
+ Summoner.Source: fetchSource :: ConnectMode -> Source -> IO (Maybe Text)

Files

CHANGELOG.md view
@@ -3,6 +3,125 @@ `summoner` uses [PVP Versioning][1]. The changelog is available [on GitHub][2]. +## 2.0.0.0 – Mar 28, 2019++* [#246](https://github.com/kowainik/summoner/issues/246):+  Put common fields into the `common-options` [common stanza](https://vrom911.github.io/blog/common-stanzas).+  (by [@vrom911](https://github.com/vrom911))+* [#351](https://github.com/kowainik/summoner/issues/351),+  [#395](https://github.com/kowainik/summoner/issues/395),+  [#398](https://github.com/kowainik/summoner/issues/398):+  __#CLI__ __#TUI__+  Add GitHub Actions CI check as an option for the generated+  project.++  * Add `-a` or `--actions` CLI option for GitHub actions.+  * Add `GitHub Actions` entry into interactive CLI mode.+  * Add `GitHub Actions` button into TUI.+  * Add `githubActions` to the TOML configs.++  (by [@patrickt](https://github.com/patrickt), [@vrom911](https://github.com/vrom911), [@chshersh](https://github.com/chshersh))+* [#401](https://github.com/kowainik/summoner/issues/401),+  [#429](https://github.com/kowainik/summoner/issues/429):+  Support GHC-8.8.3 in the project.+  Make GHC-8.8.3 default for the generated projects.+  Upgrade Stack LTS to `15.5`.+  (by [@vrom911](https://github.com/vrom911))+* [#418](https://github.com/kowainik/summoner/issues/418):+  Bump default `cabal` version to `2.4` in the generated project.+  (by [@vrom911](https://github.com/vrom911))+* [#114](https://github.com/kowainik/summoner/issues/114):+  __#CLI__ __#TUI__+  Implement non-interactive mode with `-n | --non-interacive` command-line option.+  (by [@vrom911](https://github.com/vrom911))+* [#70](https://github.com/kowainik/summoner/issues/70):+  __#CLI__ __#TUI__+  Implement `summon config` command. This command will generate the+  default TOML configuration file with helpful comments.+  (by [@chshersh](https://github.com/chshersh))+* [#361](https://github.com/kowainik/summoner/issues/361):+  Always put all default warnings in `ghc-options` inside common+  stanza under cabal conditionals on the `GHC` version. Now they look+  like this:++  ```haskell+  if impl(ghc >= 8.4)+    ghc-options:       -Wmissing-export-lists+                       -Wpartial-fields+  if impl(ghc >= 8.8)+    ghc-options:       -Wmissing-deriving-strategies+  ```++  (by [@chshersh](https://github.com/chshersh))+* [#345](https://github.com/kowainik/summoner/issues/345):+  Apply `mixins` approach for using alternative preludes instead of+  the `base-noprelude` trick. Now it looks like this in the `.cabal`+  file:++  ```haskell+  mixins:              base hiding (Prelude)+                     , relude (Relude as Prelude)+  ```+  (by [@chshersh](https://github.com/chshersh))+* [#251](https://github.com/kowainik/summoner/issues/251):+  Update LICENSE names for `.cabal` files in generated projects.+  Add `ISC` to the list of the accepted licenses.+  (by [@vrom911](https://github.com/vrom911))+* __#CLI__ __#TUI__+  Customise outputted LICENSE text for `summon show license LICENSE_NAME` command+  (by [@vrom911](https://github.com/vrom911))+* [#399](https://github.com/kowainik/summoner/issues/399):+  Add Haddock header to library module.++  ```haskell+  {- |+  Copyright: (c) 2020 FULL_NAME+  SPDX-License-Identifier: LICENSE_NAME+  Maintainer: NAME <email@email.com>++  Project description+  -}+  ```+  (by [@vrom911](https://github.com/vrom911))+* Improve `maintainer` field in the generated `.cabal` file.+  (by [@vrom911](https://github.com/vrom911))+* [#430](https://github.com/kowainik/summoner/issues/430):+  Instead of not including old GHCs for Stack check at Travis,+  those versions are added to the `allow_failures` section of matrix.+  (by [@vrom911](https://github.com/vrom911))++  _Note:_ For the Stack failure reasons see [this issue](https://github.com/commercialhaskell/stack/issues/4488).+* [#394](https://github.com/kowainik/summoner/issues/394):+  Do not crush when `hub` is not installed. Instead, print descriptive warning+  message.+  (by [@vrom911](https://github.com/vrom911))+* [#34](https://github.com/kowainik/summoner/issues/34):+  Print helpful error message when `hub` fails (for example, if the+  password is incorrect).+  (by [@chshersh](https://github.com/chshersh))+* [#281](https://github.com/kowainik/summoner/issues/281):+  Add more example projects and golden tests for various scaffolding+  configurations.+  (by [@chshersh](https://github.com/chshersh))+* [#375](https://github.com/kowainik/summoner/issues/375):+  Remove deprecated `stylish` and `contributing` fields in the configurations.+  Use `files` instead.+  (by [@vrom911](https://github.com/vrom911))+* Use `--silent` and `--fail` options with `curl` commands.+  (by [@chshersh](https://github.com/chshersh))+* Upgrade GHC-8.6.5 LTS to `14.27`.+  (by [@vrom911](https://github.com/vrom911))+* __#TUI__ Allow `brick-0.52`.+  (by [@vrom911](https://github.com/vrom911))+* [#363](https://github.com/kowainik/summoner/issues/363):+  Move from `generic-deriving` to `generic-data`.+  (by [@chshersh](https://github.com/chshersh))+* [#434](https://github.com/kowainik/summoner/issues/434):+  Move to `validation-selective`.+  (by [@vrom911](https://github.com/vrom911))+* Use `colourista` for pretty terminal formatting.+  (by [@chshersh](https://github.com/chshersh))+ ## 1.4.0.0 – Dec 25, 2019 🎅  * [#339](https://github.com/kowainik/summoner/issues/339):
README.md view
@@ -1,6 +1,7 @@ # 🔮 Summoner  ![wizard](https://user-images.githubusercontent.com/8126674/44388234-320aac00-a55a-11e8-879d-5dca68512031.png)+[![GitHub CI](https://github.com/kowainik/summoner/workflows/CI/badge.svg)](https://github.com/kowainik/summoner/actions) [![Build](https://img.shields.io/travis/kowainik/summoner.svg?logo=travis)](http://travis-ci.org/kowainik/summoner) [![Windows build](https://ci.appveyor.com/api/projects/status/github/kowainik/summoner?branch=master&svg=true)](https://ci.appveyor.com/project/kowainik/summoner) [![Hackage](https://img.shields.io/hackage/v/summoner.svg?logo=haskell)](https://hackage.haskell.org/package/summoner)@@ -14,11 +15,11 @@ Summoner is a tool for scaffolding fully configured batteries-included production-level Haskell projects.  Do you want to create a library that is to be uploaded to Hackage/Stackage, that builds with both Cabal and Stack and supports the latest three major GHC versions?-Or are you building a production application which uses a custom prelude and has CI with Travis Linux and AppVeyors Windows checks?+Or are you building a production application which uses a custom prelude and has CI with  GitHub Actions or Travis Linux and AppVeyors Windows checks? Maybe do you want to play with your idea in a single module without introducing the whole complexity of the Haskell projects? Summoner can help you do all that with minimal effort from you - it can even upload the project to GitHub if you wish! -By the way, Summoner operates as either CLI or TUI application, so you can choose what you're more comfortable with and install only the required one.+By the way, Summoner operates as either CLI or TUI application, so you can choose what you are more comfortable with and install only the required one.  ## Structure @@ -32,10 +33,14 @@     + [Installation](#installation-)         + [Summon-TUI](#summon-tui-)           + [TUI: download binary](#tui-download-binary-)+          + [TUI: Homebrew](#tui-homebrew-)+          + [TUI: Ubuntu](#tui-ubuntu-)           + [TUI: from Hackage/Stackage](#tui-from-hackagestackage-)           + [TUI: from source](#tui-from-source-)         + [Summon-CLI](#summon-cli-)           + [CLI: download binary](#cli-download-binary-)+          + [CLI: Homebrew](#cli-homebrew-)+          + [CLI: Ubuntu](#cli-ubuntu-)           + [CLI: from Hackage/Stackage](#cli-from-hackagestackage-)           + [CLI: from source](#cli-from-source-)     + [Setup](#setup-)@@ -55,21 +60,31 @@  ### TUI demo [↑](#structure) -[![TUI demo](https://asciinema.org/a/214424.png)](https://asciinema.org/a/214424)+[![TUI demo](https://asciinema.org/a/314375.png)](https://asciinema.org/a/314375)  ### CLI demo [↑](#structure) -[![CLI demo](https://asciinema.org/a/214433.png)](https://asciinema.org/a/214433)+[![CLI demo](https://asciinema.org/a/314374.png)](https://asciinema.org/a/314374)  ### Examples  You can also see complete examples in the following folder: -* [`summon-cli/tests/golden`: Examples of scaffolded projects](https://github.com/kowainik/summoner/tree/master/summoner-cli/test/golden)+* [`summon-cli/examples/`: Examples of scaffolded projects](https://github.com/kowainik/summoner/tree/master/summoner-cli/examples/) -Directory `smallProject` contains an example of the straightforward package,-and `fullProject` shows a generated project with more advanced structure and more features.+The directory contains the following examples: +* [`cabal-minimal`](https://github.com/kowainik/summoner/tree/master/summoner-cli/examples/cabal-minimal):+  Minimal Haskell project with the Cabal-only support, default+  settings and all of the integrations disabled.+* [`cabal-full`](https://github.com/kowainik/summoner/tree/master/summoner-cli/examples/cabal-full):+   Cabal-only project with all integrations enabled.+* [`stack-full`](https://github.com/kowainik/summoner/tree/master/summoner-cli/examples/stack-full):+  Stack-only project with all integrations enabled.+* [`full-batteries`](https://github.com/kowainik/summoner/tree/master/summoner-cli/examples/full-batteries):+  All batteries-included project which supports both build tools and+  shows every Summoner feature.+ ## Features [↑](#structure)  Summoner is a tool that combines predefined configurations, command-line arguments and a chosen interface.@@ -84,30 +99,30 @@  + Support for Cabal and Stack build tools. + Ability to pick stanzas (library, executable, test-suite, benchmark).++ Usage of [common stanza](https://vrom911.github.io/blog/common-stanzas) to reduce `.cabal` file's boilerplate. + Option to include an alternative prelude, if desired. The project would then-  use [`base-noprelude` technique](http://hackage.haskell.org/package/Prelude),-  and the `Prelude` module would be added to the library target.+  use the [`mixins` technique](https://www.reddit.com/r/haskelltil/comments/9qa366/easy_way_to_replace_default_prelude_with_the/). + Whole Hackage-upload checklist support (exhaustive `.cabal` file, PVP versioning, GHC options, conventional meta files).-+ Support for multiple GHC versions, with thoughtful reflection on project meta, base versions (e.g. `base >= 4.9 && < 4.12`), etc.++ Support for multiple GHC versions, with thoughtful reflection on project meta, base versions (e.g. `base >= 4.9 && < 4.13`), etc. + Ability to create runnable Haskell scripts.-+ Different license support: MIT, BSD2, BSD3, GPL-2, GPL-3, LGPL-2.1, LGPL-3, AGPL-3, Apache-2.0, MPL-2.0, None (All Rights Reserved license without file).++ Different license support: MIT, BSD-2-Clause, BSD-3-Clause, GPL-2.0, GPL-3.0, LGPL-2.1, LGPL-3.0, AGPL-3.0, Apache-2.0, MPL-2.0, ISC, None (without file). + Creation of the `CHANGELOG.md` file with [PVP versioning policy](https://pvp.haskell.org).-+ Ability to include any custom files (including `.stylish-haskell.yaml`, `CONTRIBUTING.md`, `CODEOWNERS`, etc.).++ Ability to include any custom files (including `.stylish-haskell.yaml`, `CONTRIBUTING.md`, `CODEOWNERS`, `FUNDING.yml` etc.). + Usage of the `ghc-options` field with sensible defaults.    If `ghc-options` are not explicitly stated in the configuration file, then the following list of GHC flags is added to all stanzas:    ```   -Wall-  -Wincomplete-uni-patterns-  -Wincomplete-record-updates   -Wcompat   -Widentities-  -Wredundant-constraints       (GHC >= 8.0)-  -fhide-source-paths           (GHC >= 8.2.2)-  -Wmissing-export-lists        (GHC >= 8.4.1)-  -Wpartial-fields              (GHC >= 8.4.1)-  -Wmissing-deriving-strategies (GHC >= 8.8.1)+  -Wincomplete-uni-patterns+  -Wincomplete-record-updates+  -Wredundant-constraints       (GHC ⩾ 8.0)+  -fhide-source-paths           (GHC ⩾ 8.2)+  -Wmissing-export-lists        (GHC ⩾ 8.4)+  -Wpartial-fields              (GHC ⩾ 8.4)+  -Wmissing-deriving-strategies (GHC ⩾ 8.8)   ```    Besides, the following GHC options are added to the executable, tests and benchmark stanzas:@@ -134,16 +149,19 @@ + Generation of the `.travis.yml` file that runs build and tests on CI under Linux using   [Dead simple Haskell Travis Settings for Cabal and Stack](https://chshersh.github.io/posts/2019-02-25-haskell-travis). + Generation of the `appveyor.yaml` file which runs build and tests on CI under Windows.++ Generation of the `.github/workflows/ci.yml` file that runs build and tests on+  GitHub Actions CI under Linux using Cabal. + Configuration matrix on CI to build with multiple GHC versions and various build tools. + `-Werror` is enabled on CI not to miss any warnings. + Run HLint checks on CI.  ### Others [↑](#structure) ++ Carefully collected Haskell project best practices gathered in your projects' scaffold.++ Generate beginner-friendly default configuration using the `summon config` command. + Ability to create a project in the offline mode. + Ability to check GHC-specific versions of the corresponding `base` library   and Stackage snapshot resolver via `summon show ghc` command.-+ Carefully collected Haskell project best practices gathered in your projects' scaffold.  ### Project structure example [↑](#structure) @@ -187,8 +205,8 @@  We also have minimal version requirements for build tools: -* [Cabal >= 2.0](https://www.haskell.org/cabal/)-* [Stack >= 2.1](http://haskellstack.org)+* [Cabal ⩾ 2.4](https://www.haskell.org/cabal/)+* [Stack ⩾ 2.1.3](http://haskellstack.org)  However, it is always recommended to use the newest versions of build tools. @@ -216,13 +234,36 @@ mv summon-cli-linux ~/.local/bin/summon ``` +##### TUI: Homebrew [↑](#structure)++If you are on MacOS, you can get Summoner using Homebrew Kowainik's Tap.++You need to run the following commands for that:++```shell+$ brew tap kowainik/tap+$ brew install summoner-tui+```++##### TUI: Ubuntu [↑](#structure)++If you are on Ubuntu, you can get Summoner from Kowainik's PPA.++You need to run the following commands for that:++```shell+$ sudo add-apt-repository ppa:kowainik/summoner-tui+$ sudo apt update+$ sudo apt install summoner-tui+```+ ##### TUI: from Hackage/Stackage [↑](#structure)  Using `cabal`:  ```shell-cabal new-update-cabal new-install summoner-tui+cabal v2-update+cabal v2-install summoner-tui ```  Using `stack`:@@ -254,7 +295,7 @@ Build and install using `cabal`:  ```shell-cabal new-install summoner-tui:exe:summon-tui+cabal v2-install summoner-tui:exe:summon-tui ```  Build and install using `stack`:@@ -276,13 +317,36 @@ mv summon-cli-linux ~/.local/bin/summon ``` +##### CLI: Homebrew [↑](#structure)++If you are on MacOS, you can get Summoner using Homebrew Kowainik's Tap.++You need to run the following commands for that:++```shell+$ brew tap kowainik/tap+$ brew install summoner-cli+```++##### CLI: Ubuntu [↑](#structure)++If you are on Ubuntu, you can get Summoner from Kowainik's PPA.++You need to run the following commands for that:++```shell+$ sudo add-apt-repository ppa:kowainik/summoner-cli+$ sudo apt update+$ sudo apt install summoner-cli+```+ ##### CLI: from Hackage/Stackage [↑](#structure)  Using `cabal`:  ```shell-cabal new-update-cabal new-install summoner+cabal v2-update+cabal v2-install summoner ```  Using `stack`:@@ -314,7 +378,7 @@ Build and install using `cabal`:  ```shell-cabal new-install summoner-cli:exe:summon+cabal v2-install summoner-cli:exe:summon ```  Build and install using `stack`:@@ -358,11 +422,12 @@ | `fullName`       | Text    | Full name.                                                                                                                                                           | | `email`          | Text    | E-mail address.                                                                                                                                                      | | `license`        | License | One of: `MIT`, `BSD2`, `BSD3`, `GPL-2`, `GPL-3`, `LGPL-2.1`, `LGPL-3`, `AGPL-3`, `Apache-2.0`, `MPL-2.0`, `None`.                                                    |-| `ghcVersions`    | [GHC]   | `summoner` uses default `GHC-8.8.1`. However, additionally you can specify other versions. For each version `x.y.z` the `stack-x.y.z.yaml` will be created.          |+| `ghcVersions`    | [GHC]   | `summoner` uses default `GHC-8.8.3`. However, additionally you can specify other versions. For each version `x.y.z` the `stack-x.y.z.yaml` will be created.          | | `github`         | Bool    | Turn on `GitHub` integration by default?                                                                                                                             | | `gitignore`      | [Text]  | List of files you want added to the default `.gitignore`. (Ignored if `github = false`)                                                                              | | `noUpload`       | Bool    | Do not upload to GitHub, but create all GitHub related files if specified (Ignored if `github = false`)                                                              | | `private`        | Bool    | Create private repository by default? (Ignored if `github = false`)                                                                                                  |+| `githubActions`  | Bool    | Turn on `GitHub Actions` integration by default?  (Currently working with `Cabal` only. Ignored if `github = false`)                                                 | | `travis`         | Bool    | Turn on `Travis` integration by default?  (Ignored if `github = false`)                                                                                              | | `appveyor`       | Bool    | Turn on `AppVeyor` integration by default?  (Ignored if `github = false`)                                                                                            | | `lib`            | Bool    | Create `src` folder with simple `ProjectName.hs` file and library target?                                                                                            |@@ -371,15 +436,16 @@ | `bench`          | Bool    | Create `benchmark` folder with `Main.hs` file with [`gauge`](https://hackage.haskell.org/package/gauge) library usage example?                                       | | `extensions`     | [Text]  | List of the default extensions to add into `default-extensions` section in the `.cabal`.                                                                             | | `ghc-options`    | [Text]  | List of the default GHC options to add into `ghc-options` section in the `.cabal`.                                                                                   |-| `stylish.*`      | Text    | **DEPRECATED** `stylish.file` to provide the absolute file path OR `stylish.url` to download the `.stylish-haskell.yaml` file to use in the project.                                |-| `contributing.*` | Text    | **DEPRECATED** `contributing.file` to provide the absolute file path OR `contributing.url` download OR `contribuint.link` to link the `CONTRIBUTING.md` file to use in the project. | | `files`          | Map FilePath Source  | Custom mapping of files to their sources. Represented as a list of inline tables in TOML in a format like `files = [ { path = "foo", url = "https://..." }, ... ]`. Supported file types: `url`, `local`, `raw`. | |`[prelude]`       |         |                                                                                                                                                                      | | `package`        | Text    | The package name of the custom prelude you'd like to use in the project (doesn't work without `module` field).                                                       | | `module`         | Text    | The module name of the custom prelude you'd like to use in the project (doesn't work without `package` field).                                                       | -See the example of [the configuration for projects of the `Kowainik` organization](https://github.com/kowainik/org/blob/master/.summoner.toml).+You can create default configuration using the `summon config`+command. See [the default content here](summoner-cli/test/golden/summoner-default.toml). +For a real-life example of the configuration, see [the configuration for projects of the `Kowainik` organization](https://github.com/kowainik/org/blob/master/.summoner.toml).+ ### Command line arguments [↑](#structure)  Available commands:@@ -393,6 +459,7 @@   new                      Create a new Haskell project   script                   Create a new Haskell script   show                     Show available licenses or ghc versions+  config                   Create default TOML configuration for summoner  Available global options:   -h, --help               Show this help text@@ -421,7 +488,7 @@   --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+                           specified '~/.summoner.toml' will be used by default   --prelude-package PACKAGE_NAME                            Name for the package of the custom prelude to use in                            the project@@ -437,6 +504,7 @@   -h, --help               Show this help text   -g, --github             Github integration   -p, --private            Create private GitHub repository+  -a, --actions            GitHub Actions CI integration   -c, --travis             Travis CI integration   -w, --app-veyor          AppVeyor CI integration   -l, --library            Library target@@ -474,12 +542,41 @@   -h, --help               Show this help text ``` -For example, the following command preconfigures the project settings with the custom prelude `relude`, included library, executable, test stanzas (but without benchmarks), creates a private repository on GitHub with the Travis CI and AppVeyor CI integrated.+For example, the following command preconfigures the project settings with the+custom prelude `relude`, included library, executable, test stanzas (but without+benchmarks), creates a private repository on GitHub with the GitHub Actions CI,+Travis CI and AppVeyor CI integrated.  ```shell-summon new my-project with -letgcpw without -b --prelude-package relude --prelude-module Relude+summon new my-project with -letgcpwa without -b --prelude-package relude --prelude-module Relude ``` +#### **summon config** command: [↑](#structure)++```+Usage: summon config [-f|--file=FILENAME]+  Create a default TOML configuration file for summoner++Available options:+  -h,--help                Show this help text+  -f,--file=FILENAME       Path to the toml file with configurations. If not+                           specified '~/.summoner.toml' will be used by default+```++This command will generate a TOML configuration file with the default settings+that can be used to scaffold future Haskell packages. It contains all+options supported by Summoner with comments and examples. Though, all+options would be turned off by default and to use them one will need+to uncomment the correspoding lines.+See [the default content here](summoner-cli/test/golden/summoner-default.toml).++Possible command usages:++```shell+summon config+summon config --file ~/.summoner-demo.toml+```+ ### TUI [↑](#structure)  #### TUI new command [↑](#structure)@@ -553,7 +650,7 @@ ```haskell #!/usr/bin/env stack {- stack-  --resolver lts-14.18+  --resolver lts-15.5   script   --package base -}@@ -591,6 +688,21 @@    export HUB_PROTOCOL="https"    ``` +<hr>++> Why some of the Stack checks on my TravisCI matrix are marked as "This job is+> allowed to fail"?++Due to the Stack problem of working with older versions of Cabal, the build can+fail with Stack for some older GHCs. We are adding these checks into+`allow_failures` section, as this is a known issue, and there is no need for the+whole build to fail because of that.++For more information about the issue and some workarounds from Stack developers,+see the following ticket:++  * [commersialhaskell/stack issue](https://github.com/commercialhaskell/stack/issues/4488)+ ## For Developers [↑](#structure)  If you'd like to take part in the development processes, here are a few things to keep in mind:@@ -610,7 +722,7 @@ To build the project you can use the following commands:  ```shell=-cabal new-build all+cabal v2-build all ```  for Cabal and@@ -619,14 +731,7 @@ stack build ``` -for Stack and--```shell=-nix-build -A summoner     # To build the CLI only-nix-build -A summoner-tui # To build the TUI-```--for Nix.+for Stack.  ### Test [↑](#structure) @@ -635,42 +740,29 @@ To actually run tests you need to run:  ```shell-cabal new-test all+cabal v2-test all ``` -or, if using Stack,+or, if using Stack  ```shell stack test ``` -or, if using Nix,--```shell-nix-shell --run 'cabal new-test all'-```- ### Run [↑](#structure)  Building Summoner with the recommended method creates two executables: `summon` and `summon-tui`. To run the compiled executable you can use the following commands:  ```shell-cabal new-exec summon -- SOME_COMMAND-cabal new-exec summon-tui -- SOME_COMMAND+cabal v2-exec summon -- SOME_COMMAND+cabal v2-exec summon-tui -- SOME_COMMAND ``` -or, if using Stack,+or, if using Stack  ```shell stack exec summon -- SOME_COMMAND stack exec summon-tui -- SOME_COMMAND-```--or, if using Nix,--```shell-nix-shell --run 'cabal new-run summon -- SOME_COMMAND'-nix-shell --run 'cabal new-run summon-tui -- SOME_COMMAND' ```  ## Acknowledgments [↑](#structure)
app/Cli.hs view
@@ -1,4 +1,4 @@-module Main where+module Main (main) where  import System.IO (hSetEncoding, utf8) 
+ examples/cabal-full/.github/workflows/ci.yml view
@@ -0,0 +1,44 @@+name: CI++# Trigger the workflow on push or pull request, but only for the master branch+on:+  pull_request:+  push:+    branches: [master]++jobs:+  build:+    name: ghc ${{ matrix.ghc }}+    runs-on: ubuntu-16.04+    strategy:+      matrix:+        cabal: ["2.4"]+        ghc:+          - "8.4.4"+          - "8.6.5"+          - "8.8.3"++    steps:+    - uses: actions/checkout@v2+      if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/master'++    - uses: actions/setup-haskell@v1+      name: Setup Haskell+      with:+        ghc-version: ${{ matrix.ghc }}+        cabal-version: ${{ matrix.cabal }}++    - uses: actions/cache@v1+      name: Cache ~/.cabal/store+      with:+        path: ~/.cabal/store+        key: ${{ runner.os }}-${{ matrix.ghc }}-cabal++    - name: Build+      run: |+        cabal v2-update+        cabal v2-build --enable-tests --enable-benchmarks++    - name: Test+      run: |+        cabal v2-test --enable-tests
+ examples/cabal-full/.gitignore view
@@ -0,0 +1,54 @@+### Haskell+dist+dist-*+cabal-dev+*.o+*.hi+*.chi+*.chs.h+*.dyn_o+*.dyn_hi+*.prof+*.aux+*.hp+*.eventlog+.virtualenv+.hsenv+.hpc+.cabal-sandbox/+cabal.sandbox.config+cabal.config+cabal.project.local+.ghc.environment.*+.HTF/+# Stack+.stack-work/+stack.yaml.lock++### IDE/support+# Vim+[._]*.s[a-v][a-z]+[._]*.sw[a-p]+[._]s[a-v][a-z]+[._]sw[a-p]+*~+tags++# IntellijIDEA+.idea/+.ideaHaskellLib/+*.iml++# Atom+.haskell-ghc-mod.json++# VS+.vscode/++# Emacs+*#+.dir-locals.el+TAGS++# other+.DS_Store
+ examples/cabal-full/.travis.yml view
@@ -0,0 +1,33 @@+sudo: true+language: haskell++git:+  depth: 5++cabal: "2.4"++cache:+  directories:+  - "$HOME/.cabal/store"+  ++matrix:+  include:+  - ghc: 8.4.4+  - ghc: 8.6.5+  - ghc: 8.8.3+  +  ++install:+  # HLint check+  - curl -sSL https://raw.github.com/ndmitchell/neil/master/misc/travis.sh | sh -s -- hlint .++  - cabal v2-update+  - cabal v2-build --enable-tests --enable-benchmarks++script:+  - cabal v2-test --enable-tests++notifications:+  email: false
+ examples/cabal-full/CHANGELOG.md view
@@ -0,0 +1,11 @@+# Changelog++`cabal-full` uses [PVP Versioning][1].+The changelog is available [on GitHub][2].++## 0.0.0.0++* Initially created.++[1]: https://pvp.haskell.org+[2]: https://github.com/kowainik/cabal-full/releases
+ examples/cabal-full/LICENSE view
@@ -0,0 +1,29 @@+BSD 3-Clause License++Copyright (c) 2020, Kowainik+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice, this+   list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright notice,+   this list of conditions and the following disclaimer in the documentation+   and/or other materials provided with the distribution.++3. Neither the name of the copyright holder nor the names of its+   contributors may be used to endorse or promote products derived from+   this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ examples/cabal-full/README.md view
@@ -0,0 +1,9 @@+# cabal-full++[![GitHub CI](https://github.com/kowainik/cabal-full/workflows/CI/badge.svg)](https://github.com/kowainik/cabal-full/actions)+[![Build status](https://img.shields.io/travis/kowainik/cabal-full.svg?logo=travis)](https://travis-ci.org/kowainik/cabal-full)+[![Windows build status](https://ci.appveyor.com/api/projects/status/github/kowainik/cabal-full?branch=master&svg=true)](https://ci.appveyor.com/project/kowainik/cabal-full)+[![Hackage](https://img.shields.io/hackage/v/cabal-full.svg?logo=haskell)](https://hackage.haskell.org/package/cabal-full)+[![BSD-3-Clause license](https://img.shields.io/badge/license-BSD--3--Clause-blue.svg)](LICENSE)++Cabal-only example with all integrations
+ examples/cabal-full/app/Main.hs view
@@ -0,0 +1,7 @@+module Main (main) where++import CabalFull (someFunc)+++main :: IO ()+main = someFunc
+ examples/cabal-full/appveyor.yml view
@@ -0,0 +1,34 @@+clone_folder: "c:\\WORK"+clone_depth: 5++# Do not build feature branch with open Pull Requests+skip_branch_with_pr: true++platform:+  - x86_64++cache:+  - "C:\\SR"+  - dist-newstyle++environment:+  global:+    CABOPTS: --store-dir=C:\\SR++  matrix:+    - GHCVER: 8.8.3++install:+  - choco source add -n mistuke -s https://www.myget.org/F/mistuke/api/v2+  - choco install -y cabal --version 2.4.1.0+  - choco install -y ghc   --version 8.8.3+  - refreshenv++before_build:+  - cabal --version+  - ghc   --version+  - cabal %CABOPTS% v2-update++build_script:+  - cabal %CABOPTS% v2-build --enable-tests+  - cabal %CABOPTS% v2-test  --enable-tests
+ examples/cabal-full/benchmark/Main.hs view
@@ -0,0 +1,7 @@+module Main (main) where++import Gauge.Main+++main :: IO ()+main = defaultMain [bench "const" (whnf const ())]
+ examples/cabal-full/cabal-full.cabal view
@@ -0,0 +1,84 @@+cabal-version:       2.4+name:                cabal-full+version:             0.0.0.0+synopsis:            Cabal-only example with all integrations+description:         Cabal-only example with all integrations+homepage:            https://github.com/kowainik/cabal-full+bug-reports:         https://github.com/kowainik/cabal-full/issues+license:             BSD-3-Clause+license-file:        LICENSE+author:              Kowainik+maintainer:          Kowainik <xrom.xkov@gmail.com>+copyright:           2020 Kowainik+category:            Testing+build-type:          Simple+extra-doc-files:     README.md+                     CHANGELOG.md+tested-with:         GHC == 8.4.4+                     GHC == 8.6.5+                     GHC == 8.8.3++source-repository head+  type:                git+  location:            https://github.com/kowainik/cabal-full.git++common common-options+  build-depends:       base >= 4.11.1.0 && < 4.14+                     , relude+  +  mixins:              base hiding (Prelude)+                     , relude (Relude as Prelude)+  +  ghc-options:         -Wall+                       -Wcompat+                       -Widentities+                       -Wincomplete-uni-patterns+                       -Wincomplete-record-updates+  if impl(ghc >= 8.0)+    ghc-options:       -Wredundant-constraints+  if impl(ghc >= 8.2)+    ghc-options:       -fhide-source-paths+  if impl(ghc >= 8.4)+    ghc-options:       -Wmissing-export-lists+                       -Wpartial-fields+  if impl(ghc >= 8.8)+    ghc-options:       -Wmissing-deriving-strategies++  default-language:    Haskell2010+  default-extensions:  DeriveGeneric+                       TypeApplications++library+  import:              common-options+  hs-source-dirs:      src+  exposed-modules:     CabalFull++executable cabal-full+  import:              common-options+  hs-source-dirs:      app+  main-is:             Main.hs+  build-depends:       cabal-full+  ghc-options:         -threaded+                       -rtsopts+                       -with-rtsopts=-N++test-suite cabal-full-test+  import:              common-options+  type:                exitcode-stdio-1.0+  hs-source-dirs:      test+  main-is:             Spec.hs+  build-depends:       cabal-full+  ghc-options:         -threaded+                       -rtsopts+                       -with-rtsopts=-N++benchmark cabal-full-benchmark+  import:              common-options+  type:                exitcode-stdio-1.0+  hs-source-dirs:      benchmark+  main-is:             Main.hs+  build-depends:       gauge+                     , cabal-full+  ghc-options:         -threaded+                       -rtsopts+                       -with-rtsopts=-N
+ examples/cabal-full/src/CabalFull.hs view
@@ -0,0 +1,15 @@+{- |+Copyright: (c) 2020 Kowainik+SPDX-License-Identifier: BSD-3-Clause+Maintainer: Kowainik <xrom.xkov@gmail.com>++Cabal-only example with all integrations+-}++module CabalFull+       ( someFunc+       ) where+++someFunc :: IO ()+someFunc = putStrLn ("someFunc" :: String)
+ examples/cabal-full/test/Spec.hs view
@@ -0,0 +1,5 @@+module Main (main) where+++main :: IO ()+main = putStrLn ("Test suite is not implemented" :: String)
+ examples/cabal-minimal/CHANGELOG.md view
@@ -0,0 +1,9 @@+# Changelog++`cabal-minimal` uses [PVP Versioning][1].++## 0.0.0.0++* Initially created.++[1]: https://pvp.haskell.org
+ examples/cabal-minimal/README.md view
@@ -0,0 +1,5 @@+# cabal-minimal++[![Hackage](https://img.shields.io/hackage/v/cabal-minimal.svg?logo=haskell)](https://hackage.haskell.org/package/cabal-minimal)++Minimal cabal-only test project
+ examples/cabal-minimal/app/Main.hs view
@@ -0,0 +1,5 @@+module Main (main) where+++main :: IO ()+main = putStrLn ("Hello, world!" :: String)
+ examples/cabal-minimal/cabal-minimal.cabal view
@@ -0,0 +1,42 @@+cabal-version:       2.4+name:                cabal-minimal+version:             0.0.0.0+synopsis:            Minimal cabal-only test project+description:         Minimal cabal-only test project+license:             NONE+author:              Kowainik+maintainer:          Kowainik <xrom.xkov@gmail.com>+copyright:           2020 Kowainik+build-type:          Simple+extra-doc-files:     README.md+                     CHANGELOG.md+tested-with:         GHC == 8.8.3++common common-options+  build-depends:       base ^>= 4.13.0.0+  +  ghc-options:         -Wall+                       -Wcompat+                       -Widentities+                       -Wincomplete-uni-patterns+                       -Wincomplete-record-updates+  if impl(ghc >= 8.0)+    ghc-options:       -Wredundant-constraints+  if impl(ghc >= 8.2)+    ghc-options:       -fhide-source-paths+  if impl(ghc >= 8.4)+    ghc-options:       -Wmissing-export-lists+                       -Wpartial-fields+  if impl(ghc >= 8.8)+    ghc-options:       -Wmissing-deriving-strategies++  default-language:    Haskell2010++executable cabal-minimal+  import:              common-options+  hs-source-dirs:      app+  main-is:             Main.hs+  +  ghc-options:         -threaded+                       -rtsopts+                       -with-rtsopts=-N
+ examples/full-batteries/.github/CODEOWNERS view
@@ -0,0 +1,1 @@+*  @chshersh @vrom911
+ examples/full-batteries/.github/workflows/ci.yml view
@@ -0,0 +1,46 @@+name: CI++# Trigger the workflow on push or pull request, but only for the master branch+on:+  pull_request:+  push:+    branches: [master]++jobs:+  build:+    name: ghc ${{ matrix.ghc }}+    runs-on: ubuntu-16.04+    strategy:+      matrix:+        cabal: ["2.4"]+        ghc:+          - "8.0.2"+          - "8.2.2"+          - "8.4.4"+          - "8.6.5"+          - "8.8.3"++    steps:+    - uses: actions/checkout@v2+      if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/master'++    - uses: actions/setup-haskell@v1+      name: Setup Haskell+      with:+        ghc-version: ${{ matrix.ghc }}+        cabal-version: ${{ matrix.cabal }}++    - uses: actions/cache@v1+      name: Cache ~/.cabal/store+      with:+        path: ~/.cabal/store+        key: ${{ runner.os }}-${{ matrix.ghc }}-cabal++    - name: Build+      run: |+        cabal v2-update+        cabal v2-build --enable-tests --enable-benchmarks++    - name: Test+      run: |+        cabal v2-test --enable-tests
+ examples/full-batteries/.gitignore view
@@ -0,0 +1,57 @@+### Haskell+dist+dist-*+cabal-dev+*.o+*.hi+*.chi+*.chs.h+*.dyn_o+*.dyn_hi+*.prof+*.aux+*.hp+*.eventlog+.virtualenv+.hsenv+.hpc+.cabal-sandbox/+cabal.sandbox.config+cabal.config+cabal.project.local+.ghc.environment.*+.HTF/+# Stack+.stack-work/+stack.yaml.lock++### IDE/support+# Vim+[._]*.s[a-v][a-z]+[._]*.sw[a-p]+[._]s[a-v][a-z]+[._]sw[a-p]+*~+tags++# IntellijIDEA+.idea/+.ideaHaskellLib/+*.iml++# Atom+.haskell-ghc-mod.json++# VS+.vscode/++# Emacs+*#+.dir-locals.el+TAGS++# other+.DS_Store++# User specific+.secret
+ examples/full-batteries/.stylish-haskell.yaml view
@@ -0,0 +1,1 @@+This is stylish-haskell.yaml
+ examples/full-batteries/.travis.yml view
@@ -0,0 +1,72 @@+sudo: true+language: haskell++git:+  depth: 5++cabal: "2.4"++cache:+  directories:+  - "$HOME/.cabal/store"+  - "$HOME/.stack"+  - "$TRAVIS_BUILD_DIR/.stack-work"++matrix:+  include:+  - ghc: 8.0.2+  - ghc: 8.2.2+  - ghc: 8.4.4+  - ghc: 8.6.5+  - ghc: 8.8.3+  +  - ghc: 8.0.2+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.0.2.yaml"+  +  - ghc: 8.2.2+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.2.2.yaml"+  +  - ghc: 8.4.4+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.4.4.yaml"+  +  - ghc: 8.6.5+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.6.5.yaml"+  +  - ghc: 8.8.3+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack.yaml"+  +  allow_failures:+  +  - ghc: 8.0.2+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.0.2.yaml"+  +  - ghc: 8.2.2+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.2.2.yaml"+  +  - ghc: 8.4.4+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.4.4.yaml"++install:+  # HLint check+  - curl -sSL https://raw.github.com/ndmitchell/neil/master/misc/travis.sh | sh -s -- hlint .++  - |+    if [ -z "$STACK_YAML" ]; then+      cabal v2-update+      cabal v2-build --enable-tests --enable-benchmarks+    else+      curl -sSL https://get.haskellstack.org/ | sh+      stack --version+      stack build --system-ghc --test --bench --no-run-tests --no-run-benchmarks --ghc-options=-Werror+    fi++script:+  - |+    if [ -z "$STACK_YAML" ]; then+      cabal v2-test --enable-tests+    else+      stack test --system-ghc+    fi++notifications:+  email: false
+ examples/full-batteries/CHANGELOG.md view
@@ -0,0 +1,11 @@+# Changelog++`full-batteries` uses [PVP Versioning][1].+The changelog is available [on GitHub][2].++## 0.0.0.0++* Initially created.++[1]: https://pvp.haskell.org+[2]: https://github.com/kowainik/full-batteries/releases
+ examples/full-batteries/CONTRIBUTING.md view
@@ -0,0 +1,1 @@+This is contributing guide
+ examples/full-batteries/LICENSE view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2018 Kowainik++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
+ examples/full-batteries/README.md view
@@ -0,0 +1,11 @@+# full-batteries++[![GitHub CI](https://github.com/kowainik/full-batteries/workflows/CI/badge.svg)](https://github.com/kowainik/full-batteries/actions)+[![Build status](https://img.shields.io/travis/kowainik/full-batteries.svg?logo=travis)](https://travis-ci.org/kowainik/full-batteries)+[![Windows build status](https://ci.appveyor.com/api/projects/status/github/kowainik/full-batteries?branch=master&svg=true)](https://ci.appveyor.com/project/kowainik/full-batteries)+[![Hackage](https://img.shields.io/hackage/v/full-batteries.svg?logo=haskell)](https://hackage.haskell.org/package/full-batteries)+[![Stackage Lts](http://stackage.org/package/full-batteries/badge/lts)](http://stackage.org/lts/package/full-batteries)+[![Stackage Nightly](http://stackage.org/package/full-batteries/badge/nightly)](http://stackage.org/nightly/package/full-batteries)+[![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)++Full-featured test project
+ examples/full-batteries/app/Main.hs view
@@ -0,0 +1,7 @@+module Main (main) where++import FullBatteries (someFunc)+++main :: IO ()+main = someFunc
+ examples/full-batteries/appveyor.yml view
@@ -0,0 +1,34 @@+clone_folder: "c:\\WORK"+clone_depth: 5++# Do not build feature branch with open Pull Requests+skip_branch_with_pr: true++platform:+  - x86_64++cache:+  - "C:\\SR"+  - dist-newstyle++environment:+  global:+    CABOPTS: --store-dir=C:\\SR++  matrix:+    - GHCVER: 8.8.3++install:+  - choco source add -n mistuke -s https://www.myget.org/F/mistuke/api/v2+  - choco install -y cabal --version 2.4.1.0+  - choco install -y ghc   --version 8.8.3+  - refreshenv++before_build:+  - cabal --version+  - ghc   --version+  - cabal %CABOPTS% v2-update++build_script:+  - cabal %CABOPTS% v2-build --enable-tests+  - cabal %CABOPTS% v2-test  --enable-tests
+ examples/full-batteries/benchmark/Main.hs view
@@ -0,0 +1,7 @@+module Main (main) where++import Gauge.Main+++main :: IO ()+main = defaultMain [bench "const" (whnf const ())]
+ examples/full-batteries/extra.txt view
@@ -0,0 +1,1 @@+See full content of the file [here](@github)
+ examples/full-batteries/full-batteries.cabal view
@@ -0,0 +1,75 @@+cabal-version:       2.4+name:                full-batteries+version:             0.0.0.0+synopsis:            Full-featured test project+description:         Full-featured test project+homepage:            https://github.com/kowainik/full-batteries+bug-reports:         https://github.com/kowainik/full-batteries/issues+license:             MIT+license-file:        LICENSE+author:              Kowainik+maintainer:          Kowainik <xrom.xkov@gmail.com>+copyright:           2020 Kowainik+category:            Testing+build-type:          Simple+extra-doc-files:     README.md+                     CHANGELOG.md+tested-with:         GHC == 8.0.2+                     GHC == 8.2.2+                     GHC == 8.4.4+                     GHC == 8.6.5+                     GHC == 8.8.3++source-repository head+  type:                git+  location:            https://github.com/kowainik/full-batteries.git++common common-options+  build-depends:       base >= 4.9.1.0 && < 4.14+                     , relude+  +  mixins:              base hiding (Prelude)+                     , relude (Relude as Prelude)+  +  ghc-options:         -Wcompat+                       -Widentities++  default-language:    Haskell2010+  default-extensions:  ConstraintKinds+                       LambdaCase+                       OverloadedStrings++library+  import:              common-options+  hs-source-dirs:      src+  exposed-modules:     FullBatteries++executable full-batteries+  import:              common-options+  hs-source-dirs:      app+  main-is:             Main.hs+  build-depends:       full-batteries+  ghc-options:         -threaded+                       -rtsopts+                       -with-rtsopts=-N++test-suite full-batteries-test+  import:              common-options+  type:                exitcode-stdio-1.0+  hs-source-dirs:      test+  main-is:             Spec.hs+  build-depends:       full-batteries+  ghc-options:         -threaded+                       -rtsopts+                       -with-rtsopts=-N++benchmark full-batteries-benchmark+  import:              common-options+  type:                exitcode-stdio-1.0+  hs-source-dirs:      benchmark+  main-is:             Main.hs+  build-depends:       gauge+                     , full-batteries+  ghc-options:         -threaded+                       -rtsopts+                       -with-rtsopts=-N
+ examples/full-batteries/src/FullBatteries.hs view
@@ -0,0 +1,15 @@+{- |+Copyright: (c) 2020 Kowainik+SPDX-License-Identifier: MIT+Maintainer: Kowainik <xrom.xkov@gmail.com>++Full-featured test project+-}++module FullBatteries+       ( someFunc+       ) where+++someFunc :: IO ()+someFunc = putStrLn ("someFunc" :: String)
+ examples/full-batteries/stack-8.0.2.yaml view
@@ -0,0 +1,1 @@+resolver: lts-9.21
+ examples/full-batteries/stack-8.2.2.yaml view
@@ -0,0 +1,1 @@+resolver: lts-11.22
+ examples/full-batteries/stack-8.4.4.yaml view
@@ -0,0 +1,1 @@+resolver: lts-12.26
+ examples/full-batteries/stack-8.6.5.yaml view
@@ -0,0 +1,1 @@+resolver: lts-14.27
+ examples/full-batteries/stack.yaml view
@@ -0,0 +1,1 @@+resolver: lts-15.5
+ examples/full-batteries/test/Spec.hs view
@@ -0,0 +1,5 @@+module Main (main) where+++main :: IO ()+main = putStrLn ("Test suite is not implemented" :: String)
+ examples/stack-full/.gitignore view
@@ -0,0 +1,54 @@+### Haskell+dist+dist-*+cabal-dev+*.o+*.hi+*.chi+*.chs.h+*.dyn_o+*.dyn_hi+*.prof+*.aux+*.hp+*.eventlog+.virtualenv+.hsenv+.hpc+.cabal-sandbox/+cabal.sandbox.config+cabal.config+cabal.project.local+.ghc.environment.*+.HTF/+# Stack+.stack-work/+stack.yaml.lock++### IDE/support+# Vim+[._]*.s[a-v][a-z]+[._]*.sw[a-p]+[._]s[a-v][a-z]+[._]sw[a-p]+*~+tags++# IntellijIDEA+.idea/+.ideaHaskellLib/+*.iml++# Atom+.haskell-ghc-mod.json++# VS+.vscode/++# Emacs+*#+.dir-locals.el+TAGS++# other+.DS_Store
+ examples/stack-full/.travis.yml view
@@ -0,0 +1,45 @@+sudo: true+language: haskell++git:+  depth: 5++cabal: "2.4"++cache:+  directories:+  +  - "$HOME/.stack"+  - "$TRAVIS_BUILD_DIR/.stack-work"++matrix:+  include:+  +  +  - ghc: 8.4.4+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.4.4.yaml"+  +  - ghc: 8.6.5+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.6.5.yaml"+  +  - ghc: 8.8.3+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack.yaml"+  +  allow_failures:+  +  - ghc: 8.4.4+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.4.4.yaml"++install:+  # HLint check+  - curl -sSL https://raw.github.com/ndmitchell/neil/master/misc/travis.sh | sh -s -- hlint .++  - curl -sSL https://get.haskellstack.org/ | sh+  - stack --version+  - stack build --system-ghc --test --bench --no-run-tests --no-run-benchmarks --ghc-options=-Werror++script:+  - stack test --system-ghc++notifications:+  email: false
+ examples/stack-full/CHANGELOG.md view
@@ -0,0 +1,11 @@+# Changelog++`stack-full` uses [PVP Versioning][1].+The changelog is available [on GitHub][2].++## 0.0.0.0++* Initially created.++[1]: https://pvp.haskell.org+[2]: https://github.com/kowainik/stack-full/releases
+ examples/stack-full/LICENSE view
@@ -0,0 +1,29 @@+BSD 3-Clause License++Copyright (c) 2020, Kowainik+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice, this+   list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright notice,+   this list of conditions and the following disclaimer in the documentation+   and/or other materials provided with the distribution.++3. Neither the name of the copyright holder nor the names of its+   contributors may be used to endorse or promote products derived from+   this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ examples/stack-full/README.md view
@@ -0,0 +1,10 @@+# stack-full++[![Build status](https://img.shields.io/travis/kowainik/stack-full.svg?logo=travis)](https://travis-ci.org/kowainik/stack-full)+[![Windows build status](https://ci.appveyor.com/api/projects/status/github/kowainik/stack-full?branch=master&svg=true)](https://ci.appveyor.com/project/kowainik/stack-full)+[![Hackage](https://img.shields.io/hackage/v/stack-full.svg?logo=haskell)](https://hackage.haskell.org/package/stack-full)+[![Stackage Lts](http://stackage.org/package/stack-full/badge/lts)](http://stackage.org/lts/package/stack-full)+[![Stackage Nightly](http://stackage.org/package/stack-full/badge/nightly)](http://stackage.org/nightly/package/stack-full)+[![BSD-3-Clause license](https://img.shields.io/badge/license-BSD--3--Clause-blue.svg)](LICENSE)++Stack-only example with all integrations
+ examples/stack-full/app/Main.hs view
@@ -0,0 +1,7 @@+module Main (main) where++import StackFull (someFunc)+++main :: IO ()+main = someFunc
+ examples/stack-full/appveyor.yml view
@@ -0,0 +1,30 @@+clone_depth: 5++# Do not build feature branch with open Pull Requests+skip_branch_with_pr: true++environment:+  STACK_ROOT: C:\sr+  STACK_VERSION: 2.1.1++  # Workaround a gnarly bug https://github.com/haskell/cabal/issues/5386+  # See: https://www.fpcomplete.com/blog/2018/06/sed-a-debugging-story+  # TODO: check if it's fixed once we switch to lst-13 and GHC 8.6+  TMP: "c:\\tmp"++  matrix:+    - STACK_YAML: stack.yaml++cache:+  - "%STACK_ROOT% -> %STACK_YAML%, appveyor.yml"+  - ".stack-work -> %STACK_YAML%, appveyor.yml"++install:+  - choco install -y haskell-stack --version %STACK_VERSION%+  - stack setup > nul++build_script:+  - stack build --test --bench --no-run-tests --no-run-benchmarks --ghc-options=-Werror++test_script:+  - stack test
+ examples/stack-full/benchmark/Main.hs view
@@ -0,0 +1,7 @@+module Main (main) where++import Gauge.Main+++main :: IO ()+main = defaultMain [bench "const" (whnf const ())]
+ examples/stack-full/src/StackFull.hs view
@@ -0,0 +1,15 @@+{- |+Copyright: (c) 2020 Kowainik+SPDX-License-Identifier: BSD-3-Clause+Maintainer: Kowainik <xrom.xkov@gmail.com>++Stack-only example with all integrations+-}++module StackFull+       ( someFunc+       ) where+++someFunc :: IO ()+someFunc = putStrLn ("someFunc" :: String)
+ examples/stack-full/stack-8.4.4.yaml view
@@ -0,0 +1,1 @@+resolver: lts-12.26
+ examples/stack-full/stack-8.6.5.yaml view
@@ -0,0 +1,1 @@+resolver: lts-14.27
+ examples/stack-full/stack-full.cabal view
@@ -0,0 +1,84 @@+cabal-version:       2.4+name:                stack-full+version:             0.0.0.0+synopsis:            Stack-only example with all integrations+description:         Stack-only example with all integrations+homepage:            https://github.com/kowainik/stack-full+bug-reports:         https://github.com/kowainik/stack-full/issues+license:             BSD-3-Clause+license-file:        LICENSE+author:              Kowainik+maintainer:          Kowainik <xrom.xkov@gmail.com>+copyright:           2020 Kowainik+category:            Testing+build-type:          Simple+extra-doc-files:     README.md+                     CHANGELOG.md+tested-with:         GHC == 8.4.4+                     GHC == 8.6.5+                     GHC == 8.8.3++source-repository head+  type:                git+  location:            https://github.com/kowainik/stack-full.git++common common-options+  build-depends:       base >= 4.11.1.0 && < 4.14+                     , relude+  +  mixins:              base hiding (Prelude)+                     , relude (Relude as Prelude)+  +  ghc-options:         -Wall+                       -Wcompat+                       -Widentities+                       -Wincomplete-uni-patterns+                       -Wincomplete-record-updates+  if impl(ghc >= 8.0)+    ghc-options:       -Wredundant-constraints+  if impl(ghc >= 8.2)+    ghc-options:       -fhide-source-paths+  if impl(ghc >= 8.4)+    ghc-options:       -Wmissing-export-lists+                       -Wpartial-fields+  if impl(ghc >= 8.8)+    ghc-options:       -Wmissing-deriving-strategies++  default-language:    Haskell2010+  default-extensions:  DeriveGeneric+                       TypeApplications++library+  import:              common-options+  hs-source-dirs:      src+  exposed-modules:     StackFull++executable stack-full+  import:              common-options+  hs-source-dirs:      app+  main-is:             Main.hs+  build-depends:       stack-full+  ghc-options:         -threaded+                       -rtsopts+                       -with-rtsopts=-N++test-suite stack-full-test+  import:              common-options+  type:                exitcode-stdio-1.0+  hs-source-dirs:      test+  main-is:             Spec.hs+  build-depends:       stack-full+  ghc-options:         -threaded+                       -rtsopts+                       -with-rtsopts=-N++benchmark stack-full-benchmark+  import:              common-options+  type:                exitcode-stdio-1.0+  hs-source-dirs:      benchmark+  main-is:             Main.hs+  build-depends:       gauge+                     , stack-full+  ghc-options:         -threaded+                       -rtsopts+                       -with-rtsopts=-N
+ examples/stack-full/stack.yaml view
@@ -0,0 +1,1 @@+resolver: lts-15.5
+ examples/stack-full/test/Spec.hs view
@@ -0,0 +1,5 @@+module Main (main) where+++main :: IO ()+main = putStrLn ("Test suite is not implemented" :: String)
+ examples/summoner-default.toml view
@@ -0,0 +1,87 @@+# This file is automatically generated by Summoner.+# Edit required fields, uncomment additional settings or delete irrelevant+# lines for the personalized configuration.++# GitHub user name+owner = "kowainik"++# First and last name+fullName = "Kowainik"++# Email used at GitHub+email = "xrom.xkov@gmail.com"++# Default OSS license for your projects.+# Run the 'summon show license' command to see the list of supported licenses.+license = "MIT"++# Create projects with the Cabal support+# cabal = true++# Create projects with the Stack support+# stack = true++# Should your projects have the library stanza by default?+# lib = true++# Should your projects have an executable stanza by default?+# exe = true++# Should your projects have the test-suite stanza by default?+# test = true++# Should your projects have the benchmark stanza by default?+# bench = true++# Summoner suports 'git' version control system and GitHub as a platform for+# hosting 'git' repos. The following set of flags controls integration with GitHub.+# github = true    # enabled GitHub integration+# noUpload = true  # Init git repo, but don't create it on GitHub+# private = true  # create private repos by default+# gitignore =      # list of additional entries to be added in .gitignore+#     [ "build"+#     , "result"+#     ]++# Summoner supports various CI services. Uncomment those you want to use by default.+# githubActions = true  # GitHub Actions CI+# travis = true         # Travis CI+# appveyor = true       # AppVeyor CI++# List of additional GHC versions to support besides 8.8.3.+# Run the 'summon show ghc' command to see the list of all supported GHC versions.+# ghcVersions = ["8.4.4", "8.6.5"]++# List of default-extensions in the .cabal file+# extensions = [ "ConstraintKinds"+#              , "DeriveGeneric"+#              , "GeneralizedNewtypeDeriving"+#              , "InstanceSigs"+#              , "KindSignatures"+#              , "LambdaCase"+#              , "OverloadedStrings"+#              , "RecordWildCards"+#              , "ScopedTypeVariables"+#              , "StandaloneDeriving"+#              , "TupleSections"+#              , "TypeApplications"+#              , "ViewPatterns"+#              ]++# List of additional files to add after creating the project+# files =+#     [ { path = ".stylish-haskell.yaml"+#       , url  = "https://raw.githubusercontent.com/kowainik/org/master/.stylish-haskell.yaml"+#       }+#     , { path = ".github/CODEOWNERS"+#       , raw  = "*  @kowainik"+#       }+#     , { path  = "src/Foo.hs"+#       , local = "/home/user/.default/Foo.hs"+#       }+#     ]++# Alternative Prelude to be used instead of the default one if you prefer+# [prelude]+#     package = "relude"+#     module  = "Relude"
src/Summoner.hs view
@@ -18,6 +18,7 @@ import Summoner.Default as Summoner import Summoner.GhcVer as Summoner import Summoner.License as Summoner+import Summoner.Mode as Summoner import Summoner.Project as Summoner import Summoner.Question as Summoner import Summoner.Settings as Summoner
src/Summoner/Ansi.hs view
@@ -7,20 +7,9 @@ -}  module Summoner.Ansi-       ( Color (..)+       ( boldDefault        , putStrFlush-       , beautyPrint-       , boldCode-       , blueCode-       , bold-       , boldText-       , boldDefault-       , italic-       , redCode-       , reset-       , resetCode        , prompt-       , setColor        , successMessage        , warningMessage        , errorMessage@@ -28,10 +17,10 @@        , skipMessage        ) where -import System.Console.ANSI (Color (..), ColorIntensity (Vivid), ConsoleIntensity (BoldIntensity),-                            ConsoleLayer (Foreground), SGR (..), setSGR, setSGRCode)+import Colourista (blue, bold, formatWith) import System.IO (hFlush) +import qualified Colourista import qualified Data.Text as T  @@ -41,57 +30,23 @@     putText msg     hFlush stdout -setColor :: Color -> IO ()-setColor color = setSGR [SetColor Foreground Vivid color]---- | Starts bold printing.-bold :: IO ()-bold = setSGR [SetConsoleIntensity BoldIntensity]--italic :: IO ()-italic = setSGR [SetItalicized True]---- | Resets all previous settings.-reset :: IO ()-reset = do-    setSGR [Reset]-    hFlush stdout---- | Takes list of formatting options, prints text using this format options.-beautyPrint :: [IO ()] -> Text -> IO ()-beautyPrint formats msg = do-    sequence_ formats-    putText msg-    reset-+{- | Read 'Text' from standard input after arrow prompt.+-} prompt :: IO Text prompt = do-    setColor Blue-    putStrFlush "  ->   "-    reset+    putStrFlush $ formatWith [blue] "  ->   "     T.strip <$> getLine -boldText :: Text -> IO ()-boldText message = bold >> putStrFlush message >> reset--boldDefault :: Text -> IO ()-boldDefault message = boldText (" [" <> message <> "]")--colorMessage :: Color -> Text -> IO ()-colorMessage color message = do-    setColor color-    putTextLn $ "  " <> message-    reset+boldDefault :: Text -> Text+boldDefault message = formatWith [bold] $ " [" <> message <> "]"  errorMessage, warningMessage, successMessage, infoMessage, skipMessage :: Text -> IO ()-errorMessage   = colorMessage Red-warningMessage = colorMessage Yellow-successMessage = colorMessage Green-infoMessage    = colorMessage Blue-skipMessage    = colorMessage Cyan+errorMessage   = Colourista.errorMessage   . indent+warningMessage = Colourista.warningMessage . indent+successMessage = Colourista.successMessage . indent+infoMessage    = Colourista.infoMessage    . indent+skipMessage    = Colourista.skipMessage    . indent -blueCode, boldCode, redCode, resetCode :: String-redCode   = setSGRCode [SetColor Foreground Vivid Red]-blueCode  = setSGRCode [SetColor Foreground Vivid Blue]-boldCode  = setSGRCode [SetConsoleIntensity BoldIntensity]-resetCode = setSGRCode [Reset]+-- | Add 2 spaces in front.+indent :: Text -> Text+indent = ("  " <>)
src/Summoner/CLI.hs view
@@ -22,37 +22,39 @@        , summonCli           -- * Runners+       , runConfig        , runScript           -- * Common helper functions        , getFinalConfig+       , getCustomLicenseText        ) where +import Colourista (blue, bold, formatWith) import Data.Version (Version, showVersion)-import Development.GitRev (gitCommitDate, gitDirty, gitHash)+import Development.GitRev (gitCommitDate, gitHash) import NeatInterpolation (text) import Options.Applicative (Parser, ParserInfo, ParserPrefs, argument, command, customExecParser,                             flag, fullDesc, help, helpLongEquals, helper, info, infoFooter,-                            infoHeader, infoOption, long, maybeReader, metavar, option, optional,-                            prefs, progDesc, short, showHelpOnEmpty, strArgument, strOption,+                            infoHeader, infoOption, long, maybeReader, metavar, option, prefs,+                            progDesc, short, showDefault, showHelpOnEmpty, strArgument, strOption,                             subparser, subparserInline, switch, value) import Options.Applicative.Help.Chunk (stringChunk) import Relude.Extra.Enum (universe)-import Relude.Extra.Validation (Validation (..))-import Shellmet (($?), ($|)) import System.Directory (doesFileExist) import System.Info (os)+import Validation (Validation (..)) -import Summoner.Ansi (blueCode, boldCode, errorMessage, infoMessage, redCode, resetCode,-                      successMessage, warningMessage)+import Summoner.Ansi (errorMessage, infoMessage, successMessage, warningMessage) import Summoner.Config (Config, ConfigP (..), PartialConfig, defaultConfig, finalise,-                        loadFileConfig)+                        guessConfigFromGit, loadFileConfig) import Summoner.CustomPrelude (CustomPrelude (..)) import Summoner.Decision (Decision (..))-import Summoner.Default (defaultConfigFile, defaultGHC)+import Summoner.Default (currentYear, defaultConfigFile, defaultConfigFileContent, defaultGHC) import Summoner.GhcVer (GhcVer, ghcTable, parseGhcVer)-import Summoner.License (License (..), LicenseName (..), fetchLicense, parseLicenseName,+import Summoner.License (License (..), LicenseName (..), fetchLicenseCustom, parseLicenseName,                          showLicenseWithDesc)+import Summoner.Mode (ConnectMode (..), Interactivity (..), isOffline) import Summoner.Project (generateProject) import Summoner.Settings (Tool, parseTool) import Summoner.Template.Script (scriptFile)@@ -85,7 +87,36 @@     New opts -> runNew opts     Script opts -> runScript opts     ShowInfo opts -> runShow opts+    Config opts -> runConfig opts ++{- | Runs @config@ command++@+Usage: summon config [-f|--file=FILENAME]+  Create a default TOML configuration file for summoner++Available options:+  -h,--help                Show this help text+  -f,--file=FILENAME       Path to the toml file with configurations. If not+                           specified '~/.summoner.toml' will be used by default+@+-}+runConfig :: ConfigOpts -> IO ()+runConfig ConfigOpts{..} = do+    configFile <- whenNothing configOptsName defaultConfigFile+    let configFileTxt = toText configFile+    alreadyExist <- doesFileExist configFile+    if alreadyExist+    then do+        warningMessage $ "File '" <> configFileTxt <> "' already exits."+        infoMessage "Use 'summon config --file <path>' to specify another path."+        exitFailure+    else do+        writeFileText configFile defaultConfigFileContent+        infoMessage $ "Created default configuration file: " <> configFileTxt+        infoMessage "Open the file using the editor of your choice."+ {- | Runs @show@ command.  @@@ -115,12 +146,22 @@                 showBulletList @LicenseName show universe                 -- get and show a license`s text             Just licenseName -> do-                fetchedLicense <- fetchLicense licenseName-                putTextLn $ unLicense fetchedLicense+                licenseCustomText <- getCustomLicenseText licenseName+                putTextLn $ unLicense licenseCustomText   where     showBulletList :: (a -> Text) -> [a] -> IO ()     showBulletList showT = mapM_ (infoMessage . T.append "➤ " . showT) +-- | Get the customized License text for @summon show license NAME@ command.+getCustomLicenseText :: LicenseName -> IO License+getCustomLicenseText licenseName = do+    year <- currentYear+    guessConfig <- guessConfigFromGit+    fetchLicenseCustom+        licenseName+        (fromMaybe "YOUR NAME" $ getLast $ cFullName guessConfig)+        year+ {- | Runs @script@ command.  @@@ -166,7 +207,7 @@     -- get the final config     finalConfig <- getFinalConfig newOpts     -- Generate the project.-    generateProject newOptsOffline newOptsProjectName finalConfig+    generateProject newOptsInteractivity newOptsConnectMode newOptsProjectName finalConfig  -- | By the given 'NewOpts' return the final configurations. getFinalConfig :: NewOpts -> IO Config@@ -175,7 +216,7 @@     fileConfig <- readFileConfig newOptsIgnoreFile newOptsConfigFile      -- guess config from the global ~/.gitconfig file-    gitConfig <- guessFromGit+    gitConfig <- guessConfigFromGit      -- union all possible configs     let unionConfig = defaultConfig <> gitConfig <> fileConfig <> newOptsCliConfig@@ -184,19 +225,7 @@     case finalise unionConfig of         Success c    -> pure c         Failure msgs -> for_ msgs errorMessage >> exitFailure-  where-    guessFromGit :: IO PartialConfig-    guessFromGit = do-       gitOwner <- (Just <$> "git" $| ["config", "user.login"]) $? pure Nothing-       gitName  <- (Just <$> "git" $| ["config", "user.name"])  $? pure Nothing-       gitEmail <- (Just <$> "git" $| ["config", "user.email"]) $? pure Nothing-       pure $ defaultConfig-           { cOwner = Last gitOwner-           , cFullName = Last gitName-           , cEmail = Last gitEmail-           } - -- | Reads and parses the given config file. If no file is provided the default -- configuration returned. readFileConfig :: Bool -> Maybe FilePath -> IO PartialConfig@@ -230,17 +259,20 @@     | Script ScriptOpts     -- | @show@ command shows supported licenses or GHC versions     | ShowInfo ShowOpts+    -- | @config@ command creates the TOML configuration file+    | Config ConfigOpts --- | Options parsed with @new@ command+-- | Options parsed with the @new@ command data NewOpts = NewOpts-    { newOptsProjectName :: Text           -- ^ project name-    , newOptsIgnoreFile  :: Bool           -- ^ ignore all config files if 'True'-    , newOptsOffline     :: Bool           -- ^ Offline mode-    , newOptsConfigFile  :: Maybe FilePath -- ^ file with custom configuration-    , newOptsCliConfig   :: PartialConfig  -- ^ config gathered during CLI+    { newOptsProjectName   :: !Text             -- ^ Project name+    , newOptsIgnoreFile    :: !Bool             -- ^ Ignore all config files if 'True'+    , newOptsConnectMode   :: !ConnectMode      -- ^ 'Online'/'Offline' mode+    , newOptsInteractivity :: !Interactivity    -- ^ Interactive or non-interactive mode is on?+    , newOptsConfigFile    :: !(Maybe FilePath) -- ^ File with custom configuration+    , newOptsCliConfig     :: !PartialConfig    -- ^ Config gathered via command-line     } --- | Options parsed with @script@ command+-- | Options parsed with the @script@ command data ScriptOpts = ScriptOpts     { scriptOptsTool :: !Tool      -- ^ Build tool: `cabal` or `stack`     , scriptOptsName :: !FilePath  -- ^ File path to the script@@ -252,6 +284,11 @@     = GhcList     | LicenseList (Maybe String) +-- | Options parsed with the @config@ command+newtype ConfigOpts = ConfigOpts+    { configOptsName :: Maybe FilePath+    }+ ---------------------------------------------------------------------------- -- Parsers ----------------------------------------------------------------------------@@ -271,23 +308,32 @@    <> help "Show summoner's version"  summonerVersion :: Version -> String-summonerVersion version = toString-    $ intercalate "\n"-    $ [sVersion, sHash, sDate] ++ [sDirty | $(gitDirty)]+summonerVersion version = intercalate "\n" [sVersion, sHash, sDate]   where-    sVersion = blueCode <> boldCode <> "Summoner " <> "v" <>  showVersion version <> resetCode-    sHash = " ➤ " <> blueCode <> boldCode <> "Git revision: " <> resetCode <> $(gitHash)-    sDate = " ➤ " <> blueCode <> boldCode <> "Commit date:  " <> resetCode <> $(gitCommitDate)-    sDirty = redCode <> "There are non-committed files." <> resetCode+    sVersion, sHash, sDate :: String+    sVersion = formatWith [blue, bold] $ "Summoner " <> "v" <>  showVersion version+    sHash = " ➤ " <> formatWith [blue, bold] "Git revision: " <> $(gitHash)+    sDate = " ➤ " <> formatWith [blue, bold] "Commit date:  " <> $(gitCommitDate) --- All possible commands.+-- | All possible commands. summonerP :: Parser Command summonerP = subparser     $ command "new" (info (helper <*> newP) $ progDesc "Create a new Haskell project")    <> command "script" (info (helper <*> scriptP) $ progDesc "Create a new Haskell script")    <> command "show" (info (helper <*> showP) $ progDesc "Show supported licenses or ghc versions")+   <> command "config" (info (helper <*> configP) $ progDesc "Create a default TOML configuration file for summoner")  ----------------------------------------------------------------------------+-- @config@ command parsers+----------------------------------------------------------------------------++-- | Parses options of the @config@ command.+configP :: Parser Command+configP = do+    configOptsName <- optional configFileP+    pure $ Config ConfigOpts{..}++---------------------------------------------------------------------------- -- @show@ command parsers ---------------------------------------------------------------------------- @@ -332,6 +378,7 @@     (  long "ghc"     <> short 'g'     <> value defaultGHC+    <> showDefault     <> metavar "GHC_VERSION"     <> help "Version of the compiler to be used for script"     )@@ -343,11 +390,12 @@ -- | Parses options of the @new@ command. newP :: Parser Command newP = do-    newOptsProjectName <- strArgument (metavar "PROJECT_NAME")-    newOptsIgnoreFile  <- ignoreFileP-    noUpload           <- noUploadP-    newOptsOffline     <- offlineP-    newOptsConfigFile  <- optional fileP+    newOptsProjectName   <- strArgument (metavar "PROJECT_NAME")+    newOptsIgnoreFile    <- ignoreFileP+    noUpload             <- noUploadP+    newOptsConnectMode   <- connectModeP+    newOptsInteractivity <- interactivityP+    newOptsConfigFile    <- optional configFileP     cabal <- cabalP     stack <- stackP     preludePack <- optional preludePackP@@ -360,79 +408,96 @@             { cPrelude = Last $ CustomPrelude <$> preludePack <*> preludeMod             , cCabal = cabal             , cStack = stack-            , cNoUpload = Any $ noUpload || newOptsOffline+            , cNoUpload = Any $ noUpload || isOffline newOptsConnectMode             }         , ..         }  targetsP ::  Decision -> Parser PartialConfig targetsP d = do-    cGitHub  <- githubP    d-    cTravis  <- travisP    d-    cAppVey  <- appVeyorP  d-    cPrivate <- privateP   d-    cLib     <- libraryP   d-    cExe     <- execP      d-    cTest    <- testP      d-    cBench   <- benchmarkP d+    cGitHub    <- githubP    d+    cGhActions <- ghActionsP d+    cTravis    <- travisP    d+    cAppVey    <- appVeyorP  d+    cPrivate   <- privateP   d+    cLib       <- libraryP   d+    cExe       <- execP      d+    cTest      <- testP      d+    cBench     <- benchmarkP d     pure mempty-        { cGitHub = cGitHub-        , cTravis = cTravis-        , cAppVey = cAppVey-        , cPrivate= cPrivate-        , cLib    = cLib-        , cExe    = cExe-        , cTest   = cTest-        , cBench  = cBench+        { cGitHub    = cGitHub+        , cGhActions = cGhActions+        , cTravis    = cTravis+        , cAppVey    = cAppVey+        , cPrivate   = cPrivate+        , cLib       = cLib+        , cExe       = cExe+        , cTest      = cTest+        , cBench     = cBench         }  githubP :: Decision -> Parser Decision-githubP d = flag Idk d-          $ long "github"-         <> short 'g'-         <> help "GitHub integration"+githubP d = flag Idk d $ mconcat+    [ long "github"+    , short 'g'+    , help "GitHub integration"+    ] +ghActionsP :: Decision -> Parser Decision+ghActionsP d = flag Idk d $ mconcat+    [ long "actions"+    , short 'a'+    , help "GitHub Actions CI"+    ]+ travisP :: Decision -> Parser Decision-travisP d = flag Idk d-          $ long "travis"-         <> short 'c'-         <> help "Travis CI integration"+travisP d = flag Idk d $ mconcat+    [ long "travis"+    , short 'c'+    , help "Travis CI integration"+    ]  appVeyorP :: Decision -> Parser Decision-appVeyorP d = flag Idk d-            $ long "app-veyor"-           <> short 'w'-           <> help "AppVeyor CI integration"+appVeyorP d = flag Idk d $ mconcat+    [ long "app-veyor"+    , short 'w'+    , help "AppVeyor CI integration"+    ]  privateP :: Decision -> Parser Decision-privateP d = flag Idk d-           $ long "private"-          <> short 'p'-          <> help "Private repository"+privateP d = flag Idk d $ mconcat+    [ long "private"+    , short 'p'+    , help "Private repository"+    ]  libraryP :: Decision -> Parser Decision-libraryP d = flag Idk d-           $ long "library"-          <> short 'l'-          <> help "Library folder"+libraryP d = flag Idk d $ mconcat+    [ long "library"+    , short 'l'+    , help "Library folder"+    ]  execP :: Decision -> Parser Decision-execP d = flag Idk d-        $ long "exec"-       <> short 'e'-       <> help "Executable target"+execP d = flag Idk d $ mconcat+    [ long "exec"+    , short 'e'+    , help "Executable target"+    ]  testP :: Decision -> Parser Decision-testP d = flag Idk d-        $ long "test"-       <> short 't'-       <> help "Test target"+testP d = flag Idk d $ mconcat+    [ long "test"+    , short 't'+    , help "Test target"+    ]  benchmarkP :: Decision -> Parser Decision-benchmarkP d = flag Idk d-             $ long "benchmark"-            <> short 'b'-            <> help "Benchmarks"+benchmarkP d = flag Idk d $ mconcat+    [ long "benchmark"+    , short 'b'+    , help "Benchmarks"+    ]  withP :: Parser PartialConfig withP = subparser $ mconcat@@ -447,44 +512,63 @@     ]  ignoreFileP :: Parser Bool-ignoreFileP = switch $ long "ignore-config" <> help "Ignore configuration file"+ignoreFileP = switch $ mconcat+    [ long "ignore-config"+    , help "Ignore configuration file"+    ]  noUploadP :: Parser Bool-noUploadP = switch $ long "no-upload" <> help "Do not upload to GitHub. Special case of the '--offline' flag."+noUploadP = switch $ mconcat+    [ long "no-upload"+    , help "Do not upload to GitHub. Special case of the '--offline' flag."+    ] -offlineP :: Parser Bool-offlineP = switch-    $ long "offline"-   <> help "Offline mode: create project with 'All Rights Reserved' license and without uploading to GitHub."+connectModeP :: Parser ConnectMode+connectModeP = flag Online Offline $ mconcat+    [ long "offline"+    , help "Offline mode: create a project with 'All Rights Reserved' license and without uploading to GitHub."+    ] -fileP :: Parser FilePath-fileP = strOption-    $ long "file"-   <> short 'f'-   <> metavar "FILENAME"-   <> help "Path to the toml file with configurations. If not specified '~/.summoner.toml' will be used if present"+interactivityP :: Parser Interactivity+interactivityP = flag Interactive NonInteractive $ mconcat+    [ long "non-interactive"+    , short 'n'+    , help "Non-interactive mode: create a project without interactive questions."+    ] +configFileP :: Parser FilePath+configFileP = strOption $ mconcat+    [ long "file"+    , short 'f'+    , metavar "FILENAME"+    , help "Path to the toml file with configurations. If not specified '~/.summoner.toml' will be used by default"+    ]+ preludePackP :: Parser Text-preludePackP = strOption-    $ long "prelude-package"-   <> metavar "PACKAGE_NAME"-   <> help "Name for the package of the custom prelude to use in the project"+preludePackP = strOption $ mconcat+    [ long "prelude-package"+    , metavar "PACKAGE_NAME"+    , help "Name for the package of the custom prelude to use in the project"+    ]  preludeModP :: Parser Text-preludeModP = strOption-    $ long "prelude-module"-   <> metavar "MODULE_NAME"-   <> help "Name for the module of the custom prelude to use in the project"+preludeModP = strOption $ mconcat+    [ long "prelude-module"+    , 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"+cabalP = flag Idk Yes $ mconcat+    [ long "cabal"+    , help "Cabal support for the project"+    ]  stackP :: Parser Decision-stackP = flag Idk Yes-       $ long "stack"-      <> help "Stack support for the project"+stackP = flag Idk Yes $ mconcat+    [ long "stack"+    , help "Stack support for the project"+    ]  ---------------------------------------------------------------------------- -- Beauty util
src/Summoner/Config.hs view
@@ -1,7 +1,4 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}- {-# LANGUAGE DataKinds            #-}-{-# LANGUAGE DeriveAnyClass       #-} {-# LANGUAGE FlexibleContexts     #-} {-# LANGUAGE FlexibleInstances    #-} {-# LANGUAGE StandaloneDeriving   #-}@@ -24,22 +21,24 @@        , Config        , configCodec        , defaultConfig+       , guessConfigFromGit        , finalise         , loadFileConfig        ) where  import Data.List (lookup)-import Generics.Deriving.Monoid (GMonoid (..), gmemptydefault)-import Generics.Deriving.Semigroup (GSemigroup (..), gsappenddefault)+import Generic.Data (gmappend, gmempty)+import Shellmet (($?), ($|)) import Toml (Key, TomlBiMap, TomlCodec, (.=))-import Relude.Extra.Validation (Validation (..))+import Validation (Validation (..))  import Summoner.CustomPrelude (CustomPrelude (..), customPreludeT) import Summoner.Decision (Decision (..))+import Summoner.Default (defaultEmail, defaultFullName, defaultLicenseName, defaultOwner) import Summoner.GhcVer (GhcVer (..), parseGhcVer, showGhcVer) import Summoner.License (LicenseName (..), parseLicenseName)-import Summoner.Source (Source, sourceT, sourceCodec)+import Summoner.Source (Source, sourceCodec)  import qualified Toml @@ -49,45 +48,40 @@     = Partial     | Final +{- | Type family to map 'Phase' to the corresponding field. This is a+Higher-Kinded Data approach specialised to custom enumeration.+-}+infixl 3 :-+type family phase :- field where+    'Partial :- field = Last field+    'Final   :- field = field+ -- | Potentially incomplete configuration.-data ConfigP (p :: Phase) = Config-    { cOwner        :: !(p :- Text)-    , cFullName     :: !(p :- Text)-    , cEmail        :: !(p :- Text)-    , cLicense      :: !(p :- LicenseName)-    , cGhcVer       :: !(p :- [GhcVer])-    , cCabal        :: !Decision-    , cStack        :: !Decision-    , cGitHub       :: !Decision-    , cTravis       :: !Decision-    , cAppVey       :: !Decision-    , cPrivate      :: !Decision-    , cLib          :: !Decision-    , cExe          :: !Decision-    , cTest         :: !Decision-    , cBench        :: !Decision-    , cPrelude      :: !(Last CustomPrelude)-    , cExtensions   :: ![Text]-    , cGhcOptions   :: ![Text]  -- ^ GHC options to add to each stanza-    , cGitignore    :: ![Text]-    , cStylish      :: !(Last Source)  -- ^ DEPRECATED: source to .stylish-haskell.yaml-    , cContributing :: !(Last Source)  -- ^ DEPRECATED: source to CONTRIBUTING.md-    , cNoUpload     :: !Any  -- ^ Do not upload to the GitHub (even if enabled)-    , cFiles        :: !(Map FilePath Source)  -- ^ Custom files+data ConfigP (p :: Phase) = ConfigP+    { cOwner      :: !(p :- Text)+    , cFullName   :: !(p :- Text)+    , cEmail      :: !(p :- Text)+    , cLicense    :: !(p :- LicenseName)+    , cGhcVer     :: !(p :- [GhcVer])+    , cCabal      :: !Decision+    , cStack      :: !Decision+    , cGitHub     :: !Decision+    , cGhActions  :: !Decision+    , cTravis     :: !Decision+    , cAppVey     :: !Decision+    , cPrivate    :: !Decision+    , cLib        :: !Decision+    , cExe        :: !Decision+    , cTest       :: !Decision+    , cBench      :: !Decision+    , cPrelude    :: !(Last CustomPrelude)+    , cExtensions :: ![Text]+    , cGhcOptions :: ![Text]  -- ^ GHC options to add to each stanza+    , cGitignore  :: ![Text]+    , cNoUpload   :: !Any  -- ^ Do not upload to the GitHub (even if enabled)+    , cFiles      :: !(Map FilePath Source)  -- ^ Custom files     } deriving stock (Generic) -deriving anyclass instance-    ( GSemigroup (p :- Text)-    , GSemigroup (p :- LicenseName)-    , GSemigroup (p :- [GhcVer])-    ) => GSemigroup (ConfigP p)--deriving anyclass instance-    ( GMonoid (p :- Text)-    , GMonoid (p :- LicenseName)-    , GMonoid (p :- [GhcVer])-    ) => GMonoid (ConfigP p)- deriving stock instance     ( Eq (p :- Text)     , Eq (p :- LicenseName)@@ -100,85 +94,71 @@     , Show (p :- [GhcVer])     ) => Show (ConfigP p) -infixl 3 :--type family phase :- field where-    'Partial :- field = Last field-    'Final   :- field = field---- | Incomplete configurations.-type PartialConfig = ConfigP 'Partial---- | Complete configurations.-type Config = ConfigP 'Final- instance Semigroup PartialConfig where-    (<>) = gsappenddefault+    (<>) = gmappend  instance Monoid PartialConfig where-    mempty = gmemptydefault+    mempty  = gmempty     mappend = (<>) -instance Ord k => GSemigroup (Map k v) where-    gsappend = (<>)+-- | Incomplete configurations.+type PartialConfig = ConfigP 'Partial -instance Ord k => GMonoid (Map k v) where-    gmempty = mempty-    gmappend = (<>)+-- | Complete configurations.+type Config = ConfigP 'Final  -- | Default 'Config' configurations. defaultConfig :: PartialConfig-defaultConfig = Config-    { cOwner    = Last (Just "kowainik")-    , cFullName = Last (Just "Kowainik")-    , cEmail    = Last (Just "xrom.xkov@gmail.com")-    , cLicense  = Last (Just MIT)-    , cGhcVer   = Last (Just [])-    , cCabal    = Idk-    , cStack    = Idk-    , cGitHub   = Idk-    , cTravis   = Idk-    , cAppVey   = Idk-    , cPrivate  = Idk-    , cLib      = Idk-    , cExe      = Idk-    , cTest     = Idk-    , cBench    = Idk-    , cPrelude  = Last Nothing-    , cExtensions = []-    , cGhcOptions = []-    , cGitignore = []-    , cStylish  = Last Nothing-    , cContributing = Last Nothing-    , cNoUpload = Any False-    , cFiles = mempty+defaultConfig = ConfigP+    { cOwner        = Last (Just defaultOwner)+    , cFullName     = Last (Just defaultFullName)+    , cEmail        = Last (Just defaultEmail)+    , cLicense      = Last (Just defaultLicenseName)+    , cGhcVer       = Last (Just [])+    , cCabal        = Idk+    , cStack        = Idk+    , cGitHub       = Idk+    , cGhActions    = Idk+    , cTravis       = Idk+    , cAppVey       = Idk+    , cPrivate      = Idk+    , cLib          = Idk+    , cExe          = Idk+    , cTest         = Idk+    , cBench        = Idk+    , cPrelude      = Last Nothing+    , cExtensions   = []+    , cGhcOptions   = []+    , cGitignore    = []+    , cNoUpload     = Any False+    , cFiles        = mempty     }  -- | Identifies how to read 'Config' data from the @.toml@ file. configCodec :: TomlCodec PartialConfig-configCodec = Config-    <$> Toml.last Toml.text "owner"        .= cOwner-    <*> Toml.last Toml.text "fullName"     .= cFullName-    <*> Toml.last Toml.text "email"        .= cEmail-    <*> Toml.last license   "license"      .= cLicense-    <*> Toml.last ghcVerArr "ghcVersions"  .= cGhcVer-    <*> decision            "cabal"        .= cCabal-    <*> decision            "stack"        .= cStack-    <*> decision            "github"       .= cGitHub-    <*> decision            "travis"       .= cTravis-    <*> decision            "appveyor"     .= cAppVey-    <*> decision            "private"      .= cPrivate-    <*> decision            "lib"          .= cLib-    <*> decision            "exe"          .= cExe-    <*> decision            "test"         .= cTest-    <*> decision            "bench"        .= cBench-    <*> Toml.last preludeT  "prelude"      .= cPrelude-    <*> textArr             "extensions"   .= cExtensions-    <*> textArr             "ghc-options"  .= cGhcOptions-    <*> textArr             "gitignore"    .= cGitignore-    <*> Toml.last sourceT   "stylish"      .= cStylish-    <*> Toml.last sourceT   "contributing" .= cContributing-    <*> Toml.any            "noUpload"     .= cNoUpload-    <*> filesCodec          "files"        .= cFiles+configCodec = ConfigP+    <$> Toml.last Toml.text "owner"         .= cOwner+    <*> Toml.last Toml.text "fullName"      .= cFullName+    <*> Toml.last Toml.text "email"         .= cEmail+    <*> Toml.last license   "license"       .= cLicense+    <*> Toml.last ghcVerArr "ghcVersions"   .= cGhcVer+    <*> decision            "cabal"         .= cCabal+    <*> decision            "stack"         .= cStack+    <*> decision            "github"        .= cGitHub+    <*> decision            "githubActions" .= cGhActions+    <*> decision            "travis"        .= cTravis+    <*> decision            "appveyor"      .= cAppVey+    <*> decision            "private"       .= cPrivate+    <*> decision            "lib"           .= cLib+    <*> decision            "exe"           .= cExe+    <*> decision            "test"          .= cTest+    <*> decision            "bench"         .= cBench+    <*> Toml.last preludeT  "prelude"       .= cPrelude+    <*> textArr             "extensions"    .= cExtensions+    <*> textArr             "ghc-options"   .= cGhcOptions+    <*> textArr             "gitignore"     .= cGitignore+    <*> Toml.any            "noUpload"      .= cNoUpload+    <*> filesCodec          "files"         .= cFiles   where     _GhcVer :: TomlBiMap GhcVer Toml.AnyValue     _GhcVer = Toml._TextBy showGhcVer (maybeToRight "Wrong GHC version" . parseGhcVer)@@ -213,9 +193,24 @@     filesCodec :: Key -> TomlCodec (Map FilePath Source)     filesCodec = Toml.map (Toml.string "path") sourceCodec +{- | Try to retrieve user information from Git config.+Return the 'PartialConfig' with the corresponding filled fields if the+information is applicable.+-}+guessConfigFromGit :: IO PartialConfig+guessConfigFromGit = do+   gitOwner <- (Just <$> "git" $| ["config", "user.login"]) $? pure Nothing+   gitName  <- (Just <$> "git" $| ["config", "user.name"])  $? pure Nothing+   gitEmail <- (Just <$> "git" $| ["config", "user.email"]) $? pure Nothing+   pure $ defaultConfig+       { cOwner = Last gitOwner+       , cFullName = Last gitName+       , cEmail = Last gitEmail+       }+ -- | Make sure that all the required configurations options were specified. finalise :: PartialConfig -> Validation [Text] Config-finalise Config{..} = Config+finalise ConfigP{..} = ConfigP     <$> fin  "owner"      cOwner     <*> fin  "fullName"   cFullName     <*> fin  "email"      cEmail@@ -224,6 +219,7 @@     <*> pure cCabal     <*> pure cStack     <*> pure cGitHub+    <*> pure cGhActions     <*> pure cTravis     <*> pure cAppVey     <*> pure cPrivate@@ -235,8 +231,6 @@     <*> pure cExtensions     <*> pure cGhcOptions     <*> pure cGitignore-    <*> pure cStylish-    <*> pure cContributing     <*> pure cNoUpload     <*> pure cFiles   where
src/Summoner/Decision.hs view
@@ -9,11 +9,10 @@ module Summoner.Decision        ( Decision (..)        , decisionToBool+       , decisionsToBools+       , promptDecisionToBool        ) where -import Generics.Deriving.Monoid (GMonoid (..))-import Generics.Deriving.Semigroup (GSemigroup (..))- import Summoner.Question (YesNoPrompt (..), chooseYesNoBool, falseMessage, trueMessage)  @@ -34,15 +33,26 @@     mempty  = Idk     mappend = (<>) -instance GSemigroup Decision where-    gsappend = (<>)--instance GMonoid Decision where-    gmempty = mempty-    gmappend = (<>)+-- | Translate 'Decision' to 'Bool'.+decisionToBool :: Decision -> Bool+decisionToBool = \case+    Yes -> True+    Nop -> False+    Idk -> False -decisionToBool :: Decision -> YesNoPrompt -> IO Bool-decisionToBool decision target@YesNoPrompt {..} = case decision of+-- | Prompt the 'Decision' to terminal output depending on the value.+promptDecisionToBool :: Decision -> YesNoPrompt -> IO Bool+promptDecisionToBool decision target@YesNoPrompt {..} = case decision of     Yes -> trueMessage  yesNoTarget     Nop -> falseMessage yesNoTarget     Idk -> chooseYesNoBool target++-- | Translate a pair of dependant 'Decision's to the pair of 'Bool's.+decisionsToBools :: (Decision, Decision) -> (Bool, Bool)+decisionsToBools = \case+    (Idk, Idk) -> (True, True)+    (Yes, Idk) -> (True, False)+    (Idk, Yes) -> (False, True)+    (Nop, Idk) -> (False, True)+    (Idk, Nop) -> (True, False)+    (x, y)     -> (decisionToBool x, decisionToBool y)
src/Summoner/Default.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE QuasiQuotes #-}+ {- | Copyright: (c) 2017-2019 Kowainik SPDX-License-Identifier: MPL-2.0@@ -9,17 +11,24 @@ module Summoner.Default        ( defaultGHC        , defaultCabal+       , defaultLicenseName+       , defaultOwner+       , defaultFullName+       , defaultEmail        , defaultTomlFile        , defaultConfigFile+       , defaultConfigFileContent        , defaultDescription        , currentYear        ) where  import Data.Time (getCurrentTime, toGregorian, utctDay)+import NeatInterpolation (text) import System.Directory (getHomeDirectory) import System.FilePath ((</>)) -import Summoner.GhcVer (GhcVer)+import Summoner.GhcVer (GhcVer, showGhcVer)+import Summoner.License (LicenseName (MIT))   -- | Default GHC version is the latest available.@@ -28,8 +37,20 @@  -- | Default version of the Cabal. defaultCabal :: Text-defaultCabal = "2.0"+defaultCabal = "2.4" +defaultLicenseName :: LicenseName+defaultLicenseName = MIT++defaultOwner :: Text+defaultOwner = "kowainik"++defaultFullName :: Text+defaultFullName = "Kowainik"++defaultEmail :: Text+defaultEmail = "xrom.xkov@gmail.com"+ defaultTomlFile :: FilePath defaultTomlFile = ".summoner.toml" @@ -44,3 +65,103 @@     now <- getCurrentTime     let (year, _, _) = toGregorian $ utctDay now     pure $ show year++{- | Default content of the @~/summoner.toml@ file to be generated by+the @summon config@ command.+-}+defaultConfigFileContent :: Text+defaultConfigFileContent = [text|+    # This file is automatically generated by Summoner.+    # Edit required fields, uncomment additional settings or delete irrelevant+    # lines for the personalized configuration.++    # GitHub user name+    owner = "$defaultOwner"++    # First and last name+    fullName = "$defaultFullName"++    # Email used at GitHub+    email = "$defaultEmail"++    # Default OSS license for your projects.+    # Run the 'summon show license' command to see the list of supported licenses.+    license = "$licenseName"++    # Create projects with the Cabal support+    # cabal = true++    # Create projects with the Stack support+    # stack = true++    # Should your projects have the library stanza by default?+    # lib = true++    # Should your projects have an executable stanza by default?+    # exe = true++    # Should your projects have the test-suite stanza by default?+    # test = true++    # Should your projects have the benchmark stanza by default?+    # bench = true++    # Summoner suports 'git' version control system and GitHub as a platform for+    # hosting 'git' repos. The following set of flags controls integration with GitHub.+    # github = true    # enabled GitHub integration+    # noUpload = true  # Init git repo, but don't create it on GitHub+    # private = true  # create private repos by default+    # gitignore =      # list of additional entries to be added in .gitignore+    #     [ "build"+    #     , "result"+    #     ]++    # Summoner supports various CI services. Uncomment those you want to use by default.+    # githubActions = true  # GitHub Actions CI+    # travis = true         # Travis CI+    # appveyor = true       # AppVeyor CI++    # List of additional GHC versions to support besides $defaultGhcVer.+    # Run the 'summon show ghc' command to see the list of all supported GHC versions.+    # ghcVersions = ["8.4.4", "8.6.5"]++    # List of default-extensions in the .cabal file+    # extensions = [ "ConstraintKinds"+    #              , "DeriveGeneric"+    #              , "GeneralizedNewtypeDeriving"+    #              , "InstanceSigs"+    #              , "KindSignatures"+    #              , "LambdaCase"+    #              , "OverloadedStrings"+    #              , "RecordWildCards"+    #              , "ScopedTypeVariables"+    #              , "StandaloneDeriving"+    #              , "TupleSections"+    #              , "TypeApplications"+    #              , "ViewPatterns"+    #              ]++    # List of additional files to add after creating the project+    # files =+    #     [ { path = ".stylish-haskell.yaml"+    #       , url  = "https://raw.githubusercontent.com/kowainik/org/master/.stylish-haskell.yaml"+    #       }+    #     , { path = ".github/CODEOWNERS"+    #       , raw  = "*  @$defaultOwner"+    #       }+    #     , { path  = "src/Foo.hs"+    #       , local = "/home/user/.default/Foo.hs"+    #       }+    #     ]++    # Alternative Prelude to be used instead of the default one if you prefer+    # [prelude]+    #     package = "relude"+    #     module  = "Relude"+|]+  where+    licenseName :: Text+    licenseName = show defaultLicenseName++    defaultGhcVer :: Text+    defaultGhcVer = showGhcVer defaultGHC
src/Summoner/GhcVer.hs view
@@ -24,8 +24,8 @@ import Data.List (maximum, minimum) import Relude.Extra.Enum (inverseMap, universe) -import qualified Text.Show as Show import qualified Data.Text as T+import qualified Text.Show as Show   -- | Represents some selected set of GHC versions.@@ -35,7 +35,7 @@     | Ghc822     | Ghc844     | Ghc865-    | Ghc881+    | Ghc883     deriving stock (Eq, Ord, Show, Enum, Bounded)  -- | Converts 'GhcVer' into dot-separated string.@@ -46,11 +46,13 @@     Ghc822  -> "8.2.2"     Ghc844  -> "8.4.4"     Ghc865  -> "8.6.5"-    Ghc881  -> "8.8.1"+    Ghc883  -> "8.8.3" --- | These are old GHC versions that are not working with default GHC versions when using Stack.+{- | These are old GHC versions that are not working with default GHC versions+when using Stack.+-} oldGhcs :: [GhcVer]-oldGhcs = [minBound .. Ghc802]+oldGhcs = [minBound .. Ghc844]  parseGhcVer :: Text -> Maybe GhcVer parseGhcVer = inverseMap showGhcVer@@ -62,8 +64,8 @@     Ghc802  -> "lts-9.21"     Ghc822  -> "lts-11.22"     Ghc844  -> "lts-12.26"-    Ghc865  -> "lts-14.18"-    Ghc881  -> "nightly-2019-12-25"+    Ghc865  -> "lts-14.27"+    Ghc883  -> "lts-15.5"  -- | Represents PVP versioning (4 numbers). data Pvp = Pvp@@ -85,7 +87,7 @@     Ghc822  -> Pvp 4 10 1 0     Ghc844  -> Pvp 4 11 1 0     Ghc865  -> Pvp 4 12 0 0-    Ghc881  -> Pvp 4 13 0 0+    Ghc883  -> Pvp 4 13 0 0  -- | Returns corresponding @base@ version of the given GHC version. baseVer :: GhcVer -> Text@@ -144,4 +146,4 @@     <> "  "     <> T.justifyLeft 14 ' ' gmBase     <> "  "-    <> T.justifyLeft 18 ' ' gmResolver+    <> gmResolver
src/Summoner/License.hs view
@@ -1,5 +1,5 @@ {- |-Copyright: (c) 2017-2019 Kowainik+Copyright: (c) 2017-2020 Kowainik SPDX-License-Identifier: MPL-2.0 Maintainer: Kowainik <xrom.xkov@gmail.com> @@ -10,11 +10,11 @@ module Summoner.License        ( LicenseName(..)        , License(..)-       , cabalLicense        , customizeLicense        , githubLicenseQueryNames        , parseLicenseName        , fetchLicense+       , fetchLicenseCustom        , licenseShortDesc        , showLicenseWithDesc        ) where@@ -41,21 +41,23 @@     | AGPL3     | Apache20     | MPL20-    | None+    | ISC+    | NONE     deriving stock (Eq, Ord, Enum, Bounded, Generic)  instance Show LicenseName where     show MIT      = "MIT"-    show BSD2     = "BSD2"-    show BSD3     = "BSD3"-    show GPL2     = "GPL-2"-    show GPL3     = "GPL-3"-    show LGPL21   = "LGPL-2.1"-    show LGPL3    = "LGPL-3"-    show AGPL3    = "AGPL-3"+    show BSD2     = "BSD-2-Clause"+    show BSD3     = "BSD-3-Clause"+    show GPL2     = "GPL-2.0-only"+    show GPL3     = "GPL-3.0-only"+    show LGPL21   = "LGPL-2.1-only"+    show LGPL3    = "LGPL-3.0-only"+    show AGPL3    = "AGPL-3.0-only"     show Apache20 = "Apache-2.0"     show MPL20    = "MPL-2.0"-    show None     = "None"+    show ISC      = "ISC"+    show NONE     = "NONE"  newtype License = License     { unLicense :: Text@@ -65,11 +67,6 @@ instance FromJSON License where     parseJSON = withObject "License" $ \o -> License <$> o .: "body" --- | As it will be shown in the @cabal@ file.-cabalLicense :: LicenseName -> Text-cabalLicense None = "AllRightsReserved"-cabalLicense l    = show l- -- | Used for downloading the license text form @Github@. githubLicenseQueryNames :: LicenseName -> Text githubLicenseQueryNames = \case@@ -83,7 +80,8 @@     AGPL3    -> "agpl-3.0"     Apache20 -> "apache-2.0"     MPL20    -> "mpl-2.0"-    None     -> "none"+    ISC      -> "isc"+    NONE     -> "none"  parseLicenseName :: Text -> Maybe LicenseName parseLicenseName = inverseMap show@@ -91,7 +89,7 @@ -- | Replaces name/year placeholders with the actual data. customizeLicense :: LicenseName -> License -> Text -> Text -> License customizeLicense l license@(License licenseText) nm year-    | l `elem` [MIT, BSD2, BSD3] = License updatedLicenseText+    | l `elem` [MIT, BSD2, BSD3, ISC] = License updatedLicenseText     | otherwise                  = license   where     updatedLicenseText :: Text@@ -102,14 +100,17 @@             afterN           = T.tail $ T.dropWhile (/= ']') withN         in  beforeY <> year <> beforeN <> nm <> afterN +-- | Download the given LICENSE text as it is from GitHub API. fetchLicense :: LicenseName -> IO License-fetchLicense None = pure $ License $ licenseShortDesc None+fetchLicense NONE = pure $ License $ licenseShortDesc NONE fetchLicense name = do     let licenseLink = "https://api.github.com/licenses/" <> githubLicenseQueryNames name     licenseJson <- "curl" $|         [ licenseLink         , "-H"         , "Accept: application/vnd.github.drax-preview+json"+        , "--silent"+        , "--fail"         ]      whenNothing (decodeStrict @License $ encodeUtf8 licenseJson) $ do@@ -117,6 +118,14 @@         putTextLn $ "Fetched content:\n" <> licenseJson         exitFailure +{- | Fetches the license by given name and customises user information where+applicable.+-}+fetchLicenseCustom :: LicenseName -> Text -> Text -> IO License+fetchLicenseCustom license fullName year = do+    licenseText <- fetchLicense license+    pure $ customizeLicense license licenseText fullName year+ -- | Show short information for the 'LicenseName'. licenseShortDesc :: LicenseName -> Text licenseShortDesc = \case@@ -129,10 +138,10 @@     LGPL3    -> "GNU Lesser General Public License, version 3"     AGPL3    -> "GNU Affero General Public License, version 3"     Apache20 -> "Apache License, version 2.0"-    MPL20    -> "Mozilla Public License, version 2.0."-    None     -> "License file won't be added. Explicitly 'All Rights Reserved', eg \-        \for proprietary software. The package may not be legally modified or \-        \redistributed by anyone but the rightsholder"+    MPL20    -> "Mozilla Public License, version 2.0"+    ISC      -> "Internet Systems Consortium"+    NONE -> "License file won't be added. The package may not be legally \+        \modified or redistributed by anyone but the rightsholder"  -- | Show license name along with its short description. showLicenseWithDesc :: LicenseName -> Text
+ src/Summoner/Mode.hs view
@@ -0,0 +1,40 @@+{- |+Copyright: (c) 2020 Kowainik+SPDX-License-Identifier: MPL-2.0+Maintainer: Kowainik <xrom.xkov@gmail.com>++This module introduces different modes in which the command-line interface+could be.+-}++module Summoner.Mode+    ( Interactivity (..)+    , isNonInteractive+    , ConnectMode (..)+    , isOffline+    ) where+++-- | Switcher for non-interactive mode.+data Interactivity+    = Interactive+    | NonInteractive+    deriving stock (Show, Eq)++-- | Is interactivity mode 'NonInteractive'?+isNonInteractive :: Interactivity -> Bool+isNonInteractive = \case+    NonInteractive -> True+    Interactive -> False++-- | Switcher for offline mode.+data ConnectMode+    = Online+    | Offline+    deriving stock (Show, Eq)++-- | Is connection mode 'Offline'?+isOffline :: ConnectMode -> Bool+isOffline = \case+    Offline -> True+    Online  -> False
src/Summoner/Project.hs view
@@ -1,5 +1,7 @@ {-# LANGUAGE QuasiQuotes #-} +{- HLINT ignore "Reduce duplication" -}+ {- | Copyright: (c) 2017-2019 Kowainik SPDX-License-Identifier: MPL-2.0@@ -10,44 +12,55 @@  module Summoner.Project        ( generateProject+       , generateProjectInteractive+       , generateProjectNonInteractive        , initializeProject-       , fetchSources        ) where -import Data.List (intersect)+import Colourista (bold, formattedMessage, green) import NeatInterpolation (text) import Relude.Extra.Enum (universe)-import Shellmet ()-import System.Directory (setCurrentDirectory)+import Shellmet (($?))+import System.Directory (findExecutable, setCurrentDirectory) -import Summoner.Ansi (Color (Green), beautyPrint, bold, errorMessage, infoMessage, setColor,-                      skipMessage, successMessage, warningMessage)+import Summoner.Ansi (errorMessage, infoMessage, skipMessage, successMessage, warningMessage) import Summoner.Config (Config, ConfigP (..)) import Summoner.CustomPrelude (CustomPrelude (..))-import Summoner.Decision (Decision (..), decisionToBool)+import Summoner.Decision (Decision (..), decisionToBool, decisionsToBools, promptDecisionToBool) import Summoner.Default (currentYear, defaultDescription, defaultGHC)-import Summoner.GhcVer (oldGhcs, parseGhcVer, showGhcVer)-import Summoner.License (LicenseName (..), customizeLicense, fetchLicense, licenseShortDesc,-                         parseLicenseName)-import Summoner.Question (YesNoPrompt (..), checkUniqueName, choose, falseMessage,-                          mkDefaultYesNoPrompt, query, queryDef, queryManyRepeatOnFail,-                          queryWithPredicate, targetMessageWithText, trueMessage)+import Summoner.GhcVer (parseGhcVer, showGhcVer)+import Summoner.License (LicenseName (..), fetchLicenseCustom, licenseShortDesc, parseLicenseName)+import Summoner.Mode (ConnectMode (..), Interactivity (..), isOffline)+import Summoner.Question (YesNoPrompt (..), checkUniqueName, choose, doesExistProjectName,+                          falseMessage, mkDefaultYesNoPrompt, query, queryDef,+                          queryManyRepeatOnFail, queryWithPredicate, targetMessageWithText,+                          trueMessage) import Summoner.Settings (Settings (..))-import Summoner.Source (Source, fetchSource)+import Summoner.Source (fetchSources) import Summoner.Template (createProjectTemplate)+import Summoner.Template.Mempty (memptyIfFalse) import Summoner.Text (intercalateMap, moduleNameValid, packageNameValid, packageToModule)-import Summoner.Tree (TreeFs, pathToTree, showBoldTree, traverseTree)--import qualified Data.Map.Strict as Map+import Summoner.Tree (showBoldTree, traverseTree)   -- | Generate the project. generateProject-    :: Bool        -- ^ @offline@ mode option-    -> Text        -- ^ Given project name.-    -> Config      -- ^ Given configurations.+    :: Interactivity  -- ^ Is it interactive or non-interactive mode?+    -> ConnectMode    -- ^ @offline@ mode option.+    -> Text           -- ^ Given project name.+    -> Config         -- ^ Given configurations.     -> IO ()-generateProject isOffline projectName Config{..} = do+generateProject Interactive    = generateProjectInteractive+generateProject NonInteractive = generateProjectNonInteractive+++-- | Generate the project.+generateProjectInteractive+    :: ConnectMode    -- ^ @offline@ mode option.+    -> Text           -- ^ Given project name.+    -> Config         -- ^ Given configurations.+    -> IO ()+generateProjectInteractive connectMode projectName ConfigP{..} = do     settingsRepo <- checkUniqueName projectName     -- decide cabal stack or both     (settingsCabal, settingsStack) <- getCabalStack (cCabal, cStack)@@ -61,20 +74,18 @@     settingsCategories <- query "Category: "      putText licenseText-    settingsLicenseName  <- if isOffline-        then None <$ infoMessage "'AllRightsReserved' license is used in offline mode"+    settingsLicenseName  <- if isOffline connectMode+        then NONE <$ infoMessage "'NONE' license is used in offline mode"         else choose parseLicenseName "License: " $ ordNub (cLicense : universe)      -- License creation-    fetchedLicense <- fetchLicense settingsLicenseName     settingsYear <- currentYear-    let settingsLicenseText = customizeLicense-            settingsLicenseName-            fetchedLicense-            settingsFullName-            settingsYear+    settingsLicenseText <- fetchLicenseCustom+        settingsLicenseName+        settingsFullName+        settingsYear -    settingsGitHub   <- decisionToBool cGitHub+    settingsGitHub   <- promptDecisionToBool cGitHub         (YesNoPrompt "GitHub integration" "Do you want to create a GitHub repository?")      let settingsNoUpload = getAny cNoUpload@@ -85,19 +96,17 @@         (settingsGitHub && not settingsNoUpload)         (YesNoPrompt "private repository" "Create as a private repository (Requires a GitHub private repo plan)?")         cPrivate-    settingsTravis   <- decisionIf settingsGitHub (mkDefaultYesNoPrompt "Travis CI integration") cTravis-    settingsAppVeyor <- decisionIf settingsGitHub (mkDefaultYesNoPrompt "AppVeyor CI integration") cAppVey-    settingsIsLib    <- decisionToBool cLib (mkDefaultYesNoPrompt "library target")-    settingsIsExe    <- let target = "executable target" in+    settingsGhActions <- decisionIf (settingsCabal && settingsGitHub) (mkDefaultYesNoPrompt "GitHub Actions CI integration") cGhActions+    settingsTravis    <- decisionIf settingsGitHub (mkDefaultYesNoPrompt "Travis CI integration") cTravis+    settingsAppVeyor  <- decisionIf settingsGitHub (mkDefaultYesNoPrompt "AppVeyor CI integration") cAppVey+    settingsIsLib     <- promptDecisionToBool cLib (mkDefaultYesNoPrompt "library target")+    settingsIsExe     <- let target = "executable target" in         if settingsIsLib-        then decisionToBool cExe (mkDefaultYesNoPrompt target)+        then promptDecisionToBool cExe (mkDefaultYesNoPrompt target)         else trueMessage target-    settingsTest     <- decisionToBool cTest (mkDefaultYesNoPrompt "tests")-    settingsBench    <- decisionToBool cBench (mkDefaultYesNoPrompt "benchmarks")-    settingsPrelude  <- if settingsIsLib then getPrelude else pure Nothing-    let settingsBaseType = case settingsPrelude of-            Nothing -> "base"-            Just _  -> "base-noprelude"+    settingsTest      <- promptDecisionToBool cTest (mkDefaultYesNoPrompt "tests")+    settingsBench     <- promptDecisionToBool cBench (mkDefaultYesNoPrompt "benchmarks")+    settingsPrelude   <- getPrelude      let settingsExtensions = cExtensions     let settingsGhcOptions = cGhcOptions@@ -113,22 +122,8 @@         vers -> do             putTextLn $ "Also these GHC versions will be added: " <> intercalateMap " " showGhcVer vers             pure vers-    -- Inform if there are old GHCs that won't be included to Travis Stack matrix-    let oldGhcIncluded = not $ null $ settingsTestedVersions `intersect` oldGhcs-    when (oldGhcIncluded && settingsStack && settingsTravis) $-        warningMessage "Old GHC versions won't be included into Stack matrix at Travis CI because of the Stack issue with newer Cabal versions." -    let fetchLast :: Text -> Last Source -> IO (Maybe Text)-        fetchLast option (Last mSource) = case mSource of-            Nothing -> pure Nothing-            Just source -> do-                let msg = [text|The option '${option}' is deprecated. Use 'files' instead.|]-                warningMessage msg-                fetchSource isOffline source--    settingsStylish      <- fetchLast "stylish.{url,file,link}" cStylish-    settingsContributing <- fetchLast "contributing.{url,file,link}" cContributing-    settingsFiles <- fetchSources isOffline cFiles+    settingsFiles <- fetchSources connectMode cFiles      -- Create project data from all variables in scope     -- and make a project from it.@@ -136,10 +131,9 @@  where     decisionIf :: Bool -> YesNoPrompt -> Decision -> IO Bool     decisionIf p ynPrompt decision = if p-        then decisionToBool decision ynPrompt+        then promptDecisionToBool decision ynPrompt         else falseMessage (yesNoTarget ynPrompt) -     categoryText :: Text     categoryText =         [text|@@ -194,8 +188,8 @@     -- 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 (mkDefaultYesNoPrompt "cabal") >>= \c ->-            if c then decisionToBool cStack (mkDefaultYesNoPrompt "stack") >>= \s -> pure (c, s)+        (Idk, Idk) -> promptDecisionToBool cCabal (mkDefaultYesNoPrompt "cabal") >>= \c ->+            if c then promptDecisionToBool cStack (mkDefaultYesNoPrompt "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)@@ -210,26 +204,73 @@         cabalMsg c = targetMessageWithText c "Cabal" "used in this project"         stackMsg c = targetMessageWithText c "Stack" "used in this project" +----------------------------------------------------------------------------+-- Non-interactive+----------------------------------------------------------------------------++generateProjectNonInteractive+    :: ConnectMode    -- ^ @offline@ mode option.+    -> Text           -- ^ Given project name.+    -> Config         -- ^ Given configurations.+    -> IO ()+generateProjectNonInteractive connectMode projectName ConfigP{..} = do+    isNonUnique <- doesExistProjectName projectName+    when isNonUnique $ do+        errorMessage "Project with this name is already exist. Please choose another one."+        exitFailure+    let settingsRepo = projectName+    -- decide cabal stack or both+    let (settingsCabal, settingsStack) = decisionsToBools (cCabal, cStack)++    let settingsOwner       = cOwner+    let settingsDescription = defaultDescription+    let settingsFullName    = cFullName+    let settingsEmail       = cEmail+    let settingsCategories  = ""+    let settingsLicenseName = if isOffline connectMode then NONE else cLicense++    -- License creation+    settingsYear <- currentYear+    settingsLicenseText <- fetchLicenseCustom+        settingsLicenseName+        settingsFullName+        settingsYear++    let settingsGitHub   = decisionToBool cGitHub+    let settingsNoUpload = getAny cNoUpload || isOffline connectMode++    let settingsPrivate = decisionIf (settingsGitHub && not settingsNoUpload) cPrivate+    let settingsGhActions = decisionIf (settingsCabal && settingsGitHub) cGhActions+    let settingsTravis    = decisionIf settingsGitHub cTravis+    let settingsAppVeyor  = decisionIf settingsGitHub cAppVey+    let (settingsIsLib, settingsIsExe) = decisionsToBools (cLib, cExe)+    let settingsTest    = decisionToBool cTest+    let settingsBench   = decisionToBool cBench+    let settingsPrelude = getLast cPrelude++    let settingsExtensions = cExtensions+    let settingsGhcOptions = cGhcOptions+    let settingsGitignore  = cGitignore+    let settingsTestedVersions = sortNub $ defaultGHC : cGhcVer+    settingsFiles <- fetchSources connectMode cFiles++    -- Create project data from all variables in scope+    -- and make a project from it.+    initializeProject Settings{..}+  where+    decisionIf :: Bool -> Decision -> Bool+    decisionIf p d = p && decisionToBool d++----------------------------------------------------------------------------+-- Initialize+----------------------------------------------------------------------------+ -- | Creates the directory and run GitHub commands. initializeProject :: Settings -> IO () initializeProject settings@Settings{..} = do     createProjectDirectory settings     when settingsGitHub $ doGithubCommands settings-    beautyPrint [bold, setColor Green] "\nJob's done\n"--{- | This function fetches contents of extra file sources.--}-fetchSources :: Bool -> Map FilePath Source -> IO [TreeFs]-fetchSources isOffline = mapMaybeM sourceToTree . Map.toList-  where-    sourceToTree :: (FilePath, Source) -> IO (Maybe TreeFs)-    sourceToTree (path, source) = do-        infoMessage $ "Fetching content of the extra file: " <> toText path-        fetchSource isOffline source >>= \case-            Nothing -> do-                errorMessage $ "Error fetching: " <> toText path-                pure Nothing-            Just content -> pure $ Just $ pathToTree path content+    formattedMessage [bold, green] "\nJob's done"  -- | From the given 'Settings' creates the project. createProjectDirectory :: Settings -> IO ()@@ -248,7 +289,29 @@     "git" ["add", "."]     "git" ["commit", "-m", "Create the project"]     unless settingsNoUpload $ do-        "hub" $ ["create", "-d", settingsDescription, settingsOwner <> "/" <> settingsRepo]-             ++ ["-p" | settingsPrivate]  -- Create private repository if asked so-         -- Upload repository to GitHub.-        "git" ["push", "-u", "origin", "master"]+        let repo = settingsOwner <> "/" <> settingsRepo+        hubInstalled <- findExecutable "hub"+        case hubInstalled of+            Just _ -> do+                isHubSuccess <- runHub repo+                if isHubSuccess+                then "git" ["push", "-u", "origin", "master"]+                else do+                    warningMessage "Error running 'hub'. Possible reason: incorrect password."+                    hubHelp repo+            Nothing -> do+                warningMessage "'hub' is not found at this machine. Cannot create the GitHub repository."+                warningMessage "Please install 'hub' for the proper work of Summoner."+                hubHelp repo+  where+    -- Create repo on GitHub and return 'True' in case of sucsess+    runHub :: Text -> IO Bool+    runHub repo =+        True <$ "hub" (["create", "-d", settingsDescription, repo]+             ++ ["-p" | settingsPrivate])  -- Create private repository if asked so+             $? pure False++    hubHelp :: Text -> IO ()+    hubHelp repo = do+        infoMessage "To finish the process manually you can run the following command:"+        putTextLn $ "    $ hub create -d '" <> settingsDescription <> "' " <> repo <> memptyIfFalse settingsPrivate " -p"
src/Summoner/Question.hs view
@@ -27,6 +27,7 @@        , queryDef        , queryManyRepeatOnFail        , checkUniqueName+       , doesExistProjectName           -- * Customize target message        , targetMessageWithText@@ -35,17 +36,19 @@        , falseMessage        ) where +import Colourista (bold, cyan, formatWith, formattedMessage, green, italic) import System.Directory (doesPathExist, getCurrentDirectory) import System.FilePath ((</>)) -import Summoner.Ansi (Color (..), beautyPrint, bold, boldDefault, errorMessage, italic, prompt,-                      putStrFlush, setColor, warningMessage)+import Summoner.Ansi (boldDefault, errorMessage, prompt, putStrFlush, warningMessage) import Summoner.Text (headToUpper, intercalateMap)  import qualified Data.Text as T import qualified Relude.Unsafe as Unsafe  +{- HLINT ignore "Redundant multi-way if" -}+ {- | Build a prompt  For example,@@ -115,8 +118,7 @@     -> IO () printQuestion question [] = putTextLn question printQuestion question (def:rest) = do-    putStrFlush question-    boldDefault def+    putStrFlush $ question <> boldDefault def     let restSlash = T.intercalate "/" rest     if restSlash == ""     then putTextLn ""@@ -166,13 +168,13 @@ 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-    putTextLn ""+          then (green, " will be "  <> text)+          else (cyan,  " won't be " <> text) +    putTextLn $ mconcat+            [ formatWith [italic, bold, color] $ "  " <> headToUpper target+            , formatWith [color] actionResult+            ]     pure result  -- | Like 'targetMessageWithText' but the text is "added to the project"@@ -202,7 +204,7 @@     loop :: IO Text     loop = do         printQuestion question options-        beautyPrint [italic] $ instruction <> "\n"+        formattedMessage [italic] instruction         input <- prompt         if input /= "" && not (p input)         then errorMessage ("'" <> input <> "' doesn't satisfy the requirements.") >> loop@@ -222,9 +224,7 @@ -- | Like 'query' but has the default answer if no answer is specified. queryDef :: Text -> Text -> IO Text queryDef question defAnswer = do-    putStrFlush question-    boldDefault defAnswer-    putTextLn ""+    putTextLn $ question <> boldDefault defAnswer     answer <- prompt     if | T.null answer -> pure defAnswer        | otherwise     -> pure answer@@ -261,11 +261,16 @@  checkUniqueName :: Text -> IO Text checkUniqueName nm = do-    curPath <- getCurrentDirectory-    exist   <- doesPathExist $ curPath </> toString nm+    exist <- doesExistProjectName nm     if exist then do         warningMessage "Project with this name is already exist. Please choose another one"         newNm <- queryNotNull "Project name: "         checkUniqueName newNm     else         pure nm++-- | Check if the folder with the suggested project name is already exist.+doesExistProjectName :: Text -> IO Bool+doesExistProjectName projectName = do+    curPath <- getCurrentDirectory+    doesPathExist $ curPath </> toString projectName
src/Summoner/Settings.hs view
@@ -35,6 +35,7 @@     , settingsLicenseText    :: !License -- ^ license text     , settingsGitHub         :: !Bool   -- ^ GitHub repository     , settingsPrivate        :: !Bool   -- ^ private repository+    , settingsGhActions      :: !Bool   -- ^ GitHub Actions CI integration     , settingsTravis         :: !Bool   -- ^ Travis CI integration     , settingsAppVeyor       :: !Bool   -- ^ AppVeyor CI integration     , settingsIsLib          :: !Bool   -- ^ is library@@ -42,15 +43,12 @@     , settingsTest           :: !Bool   -- ^ add tests     , settingsBench          :: !Bool   -- ^ add benchmarks     , settingsTestedVersions :: ![GhcVer]  -- ^ GHC versions-    , settingsBaseType       :: !Text -- ^ Base library to use     , settingsPrelude        :: !(Maybe CustomPrelude)  -- ^ custom prelude to be used     , settingsExtensions     :: ![Text] -- ^ default extensions     , settingsGhcOptions     :: ![Text] -- ^ default GHC options     , settingsGitignore      :: ![Text] -- ^ .gitignore file     , settingsCabal          :: !Bool     , settingsStack          :: !Bool-    , settingsStylish        :: !(Maybe Text) -- ^ @.stylish-haskell.yaml@ file-    , settingsContributing   :: !(Maybe Text) -- ^ @CONTRIBUTING.md@ file     , settingsNoUpload       :: !Bool  -- ^ do not upload to GitHub     , settingsFiles          :: ![TreeFs]  -- ^ Tree nodes of extra files     } deriving stock (Show)
src/Summoner/Source.hs view
@@ -8,18 +8,20 @@  module Summoner.Source        ( Source (..)-       , sourceT        , sourceCodec+       , fetchSources        , fetchSource        ) where -import Control.Arrow ((>>>)) import Control.Exception (catch) import System.Process (readProcess)-import Toml (Key, TomlBiMap, TomlBiMapError (..), TomlCodec)+import Toml (TomlBiMapError (..), TomlCodec)  import Summoner.Ansi (errorMessage, infoMessage)+import Summoner.Mode (ConnectMode (..), isOffline)+import Summoner.Tree (TreeFs, pathToTree) +import qualified Data.Map.Strict as Map import qualified Toml  @@ -60,21 +62,6 @@ matchRaw (Raw raw) = Right raw matchRaw e         = Left $ WrongConstructor "Raw" $ showSource e --- DEPRECATED: To be removed in 2.0-sourceT :: Key -> TomlCodec Source-sourceT nm = Toml.match (_Url  >>> Toml._Text) (nm <> "url")-         <|> Toml.match (_Local >>> Toml._String) (nm <> "Local")-         <|> Toml.match (_Raw  >>> Toml._Text) (nm <> "raw")-  where-    _Url :: TomlBiMap Source Text-    _Url = Toml.prism Url matchUrl--    _Local :: TomlBiMap Source FilePath-    _Local = Toml.prism Local matchLocal--    _Raw :: TomlBiMap Source Text-    _Raw = Toml.prism Raw matchRaw- {- | This 'TomlCodec' is used in the @files@ field of config. It decodes corresponding constructor from the top-level key. -}@@ -85,21 +72,40 @@     , Toml.dimatch (rightToMaybe . matchRaw) Raw (Toml.text "raw")     ] -fetchSource :: Bool -> Source -> IO (Maybe Text)-fetchSource isOffline = \case+{- | This function fetches contents of extra file sources.+-}+fetchSources :: ConnectMode -> Map FilePath Source -> IO [TreeFs]+fetchSources connectMode = mapMaybeM sourceToTree . Map.toList+  where+    sourceToTree :: (FilePath, Source) -> IO (Maybe TreeFs)+    sourceToTree (path, source) = do+        infoMessage $ "Fetching content of the extra file: " <> toText path+        fetchSource connectMode source >>= \case+            Nothing -> Nothing <$ errorMessage ("Error fetching: " <> toText path)+            Just content -> pure $ Just $ pathToTree path content++{- | Fetches content of the given extra file source.+Doesn't fetch 'Url' if the 'ConnectMode' is 'Offline'.+-}+fetchSource :: ConnectMode -> Source -> IO (Maybe Text)+fetchSource connectMode = \case     Local path -> catch (Just <$> readFileText path) (localError path)-    Url url -> if isOffline+    Url url -> if isOffline connectMode         then Nothing <$ infoMessage ("Ignoring fetching from URL in offline mode from source: " <> url)         else fetchUrl url `catch` urlError url     Raw raw -> pure $ Just raw   where     localError :: FilePath -> SomeException -> IO (Maybe Text)-    localError path _ = errorMessage ("Couldn't read file: " <> toText path)-                    >> pure Nothing+    localError path err = do+        errorMessage ("Couldn't read file: " <> toText path)+        errorMessage $ toText $ displayException err+        pure Nothing      urlError :: Text -> SomeException -> IO (Maybe Text)-    urlError url _ = errorMessage ("Couldn't get to link: " <> url)-                  >> pure Nothing+    urlError url err = do+        errorMessage ("Couldn't get to link: " <> url)+        errorMessage $ toText $ displayException err+        pure Nothing      fetchUrl :: Text -> IO (Maybe Text)-    fetchUrl url = Just . toText <$> readProcess "curl" [toString url] ""+    fetchUrl url = Just . toText <$> readProcess "curl" [toString url, "--silent", "--fail"] ""
src/Summoner/Template/Cabal.hs view
@@ -16,8 +16,8 @@  import Summoner.CustomPrelude (CustomPrelude (..)) import Summoner.Default (defaultCabal)-import Summoner.GhcVer (GhcVer (..), cabalBaseVersions, showGhcVer)-import Summoner.License (LicenseName (..), cabalLicense)+import Summoner.GhcVer (cabalBaseVersions, showGhcVer)+import Summoner.License (LicenseName (..)) import Summoner.Settings (Settings (..)) import Summoner.Template.Mempty (memptyIfFalse) import Summoner.Text (endLine, intercalateMap, packageToModule)@@ -34,10 +34,11 @@     cabalFileContent = T.concat         [ cabalHeader         , memptyIfFalse settingsGitHub sourceRepository-        , memptyIfFalse settingsIsLib   libraryStanza-        , memptyIfFalse settingsIsExe $ executableStanza $ memptyIfFalse settingsIsLib $ ", " <> settingsRepo-        , memptyIfFalse settingsTest  $ testSuiteStanza  $ memptyIfFalse settingsIsLib $ ", " <> settingsRepo-        , memptyIfFalse settingsBench $ benchmarkStanza  $ memptyIfFalse settingsIsLib $ ", " <> settingsRepo+        , commonStanza+        , memptyIfFalse settingsIsLib libraryStanza+        , memptyIfFalse settingsIsExe executableStanza+        , memptyIfFalse settingsTest  testSuiteStanza+        , memptyIfFalse settingsBench $ benchmarkStanza $ memptyIfFalse settingsIsLib $ ", " <> settingsRepo         ]      -- TODO: do something to not have empty lines@@ -51,14 +52,14 @@         [ "homepage:            " <> githubUrl        | settingsGitHub ] ++         [ "bug-reports:         " <> githubBugReports | settingsGitHub ] ++         ( "license:             " <> licenseName) :-        [ "license-file:        LICENSE" | settingsLicenseName /= None] +++        [ "license-file:        LICENSE" | settingsLicenseName /= NONE] ++         [ "author:              " <> settingsFullName-        , "maintainer:          " <> settingsEmail+        , "maintainer:          " <> settingsFullName <> " <" <> settingsEmail <> ">"         , "copyright:           " <> settingsYear <> " " <> settingsFullName ] ++         [ "category:            " <> settingsCategories | "" /= settingsCategories ] ++         [ "build-type:          Simple"         , "extra-doc-files:     README.md"-        , "                   , CHANGELOG.md"+        , "                     CHANGELOG.md"         , "tested-with:         " <> testedGhcs         ] @@ -67,12 +68,12 @@     githubBugReports = githubUrl <> "/issues"      licenseName, libModuleName :: Text-    licenseName   = cabalLicense settingsLicenseName+    licenseName   = show settingsLicenseName     libModuleName = packageToModule settingsRepo      testedGhcs :: Text     testedGhcs = intercalateMap-        ("\n" <> T.replicate 19 " " <> ", ")+        ("\n" <> T.replicate 21 " ")         (mappend "GHC == " . showGhcVer)         settingsTestedVersions @@ -85,98 +86,124 @@           location:            ${githubUrl}.git         |] +    commonStanza :: Text+    commonStanza =+        [text|+        $endLine+        common common-options+          build-depends:       base $baseBounds+          $customPrelude+          $ghcOptions++          default-language:    Haskell2010+    |] <> defaultExtensions+     baseBounds :: Text     baseBounds = cabalBaseVersions settingsTestedVersions +    ghcOptions :: Text+    ghcOptions = case settingsGhcOptions of+        [] -> defaultGhcOptions+        x:xs ->+            let customGhcOptions = T.intercalate "\n" $ x : map (T.replicate 21 " " <>) xs in+            [text|+            ghc-options:         $customGhcOptions+            |]++    defaultGhcOptions :: Text+    defaultGhcOptions =+        [text|+        ghc-options:         -Wall+                             -Wcompat+                             -Widentities+                             -Wincomplete-uni-patterns+                             -Wincomplete-record-updates+        if impl(ghc >= 8.0)+          ghc-options:       -Wredundant-constraints+        if impl(ghc >= 8.2)+          ghc-options:       -fhide-source-paths+        if impl(ghc >= 8.4)+          ghc-options:       -Wmissing-export-lists+                             -Wpartial-fields+        if impl(ghc >= 8.8)+          ghc-options:       -Wmissing-deriving-strategies+        |]+     libraryStanza :: Text     libraryStanza =         [text|         $endLine         library+          import:              common-options           hs-source-dirs:      src           exposed-modules:     $libModuleName-                               $preludeMod--          build-depends:       $settingsBaseType $baseBounds-                             $commaPreludeLibrary--          ghc-options:         -Wall-                               $ghcOptions--          default-language:    Haskell2010-        |] <> defaultExtensions+        |] -    executableStanza :: Text -> Text-    executableStanza commaRepo =+    executableStanza :: Text+    executableStanza =         [text|         $endLine         executable $settingsRepo+          import:              common-options           hs-source-dirs:      app           main-is:             Main.hs--          build-depends:       $settingsBaseType $baseBounds-                             $commaRepo-                             $commaPreludeLibrary--          ghc-options:         -Wall-                               -threaded-                               -rtsopts-                               -with-rtsopts=-N-                               $ghcOptions--          default-language:    Haskell2010-        |] <> defaultExtensions+          $buildDepends+          $rtsOptions+        |] -    testSuiteStanza :: Text -> Text-    testSuiteStanza commaRepo =+    testSuiteStanza :: Text+    testSuiteStanza =         [text|         $endLine         test-suite ${settingsRepo}-test+          import:              common-options           type:                exitcode-stdio-1.0           hs-source-dirs:      test           main-is:             Spec.hs--          build-depends:       $settingsBaseType $baseBounds-                             $commaRepo-                             $commaPreludeLibrary--          ghc-options:         -Wall-                               -threaded-                               -rtsopts-                               -with-rtsopts=-N-                               $ghcOptions--          default-language:    Haskell2010-        |] <> defaultExtensions+          $buildDepends+          $rtsOptions+        |]      benchmarkStanza :: Text -> Text     benchmarkStanza commaRepo =         [text|         $endLine         benchmark ${settingsRepo}-benchmark+          import:              common-options           type:                exitcode-stdio-1.0           hs-source-dirs:      benchmark           main-is:             Main.hs--          build-depends:       $settingsBaseType $baseBounds-                             , gauge+          build-depends:       gauge                              $commaRepo-                             $commaPreludeLibrary--          ghc-options:         -Wall-                               -threaded-                               -rtsopts-                               -with-rtsopts=-N-                               $ghcOptions+          $rtsOptions+          |] -          default-language:    Haskell2010-        |] <> defaultExtensions+    -- | @build-depends@ for the repo, only if the library is on.+    buildDepends :: Text+    buildDepends =+        if settingsIsLib+        then "build-depends:       " <> settingsRepo+        else "" +    rtsOptions :: Text+    rtsOptions =+        [text|+        ghc-options:         -threaded+                             -rtsopts+                             -with-rtsopts=-N+        |] -    preludeMod, commaPreludeLibrary :: Text-    (preludeMod, commaPreludeLibrary) = case settingsPrelude of-        Nothing                -> ("", "")-        Just CustomPrelude{..} -> ("Prelude", ", " <> cpPackage)+    customPrelude :: Text+    customPrelude = case settingsPrelude of+        Nothing -> ""+        Just CustomPrelude{..} ->+            "                   , " <> cpPackage <> "\n" <>+            [text|+            $endLine+            mixins:              base hiding (Prelude)+                               , $cpPackage ($cpModule as Prelude)+            $endLine+            |]      defaultExtensions :: Text     defaultExtensions = case settingsExtensions of@@ -184,35 +211,3 @@         xs -> "  default-extensions:  "            <> T.intercalate "\n                       " xs            <> "\n"--    ghcOptions :: Text-    ghcOptions = case settingsGhcOptions of-        [] -> defaultGhcOptions-        xs -> T.intercalate "\n" xs--    defaultGhcOptions :: Text-    defaultGhcOptions =-        [text|-        -Wincomplete-uni-patterns-        -Wincomplete-record-updates-        -Wcompat-        -Widentities-        $versionGhcOptions-        |]--    versionGhcOptions :: Text-    versionGhcOptions-        =  memptyIfFalse (settingsTestedVersions `hasLeast` Ghc802)-            "-Wredundant-constraints\n"-        <> memptyIfFalse (settingsTestedVersions `hasLeast` Ghc822)-            "-fhide-source-paths\n"-        <> memptyIfFalse (settingsTestedVersions `hasLeast` Ghc844)-            [text|-            -Wmissing-export-lists-            -Wpartial-fields-            |]-        <> memptyIfFalse (settingsTestedVersions `hasLeast` Ghc881)-            "-Wmissing-deriving-strategies\n"-      where-        hasLeast :: [GhcVer] -> GhcVer -> Bool-        hasLeast list el = all (>= el) list
src/Summoner/Template/Doc.hs view
@@ -6,7 +6,6 @@ Templates for various documentation files:  * CHANGELOG.md-* CONTRIBUTING.md * LICENSE * README.md -}@@ -15,7 +14,7 @@        ( docFiles        ) where -import Summoner.License (License (..), LicenseName (None))+import Summoner.License (License (..), LicenseName (NONE)) import Summoner.Settings (Settings (..)) import Summoner.Tree (TreeFs (..)) @@ -26,11 +25,10 @@ docFiles Settings{..} =     [ File "README.md" readme     , File "CHANGELOG.md" changelog ] ++-    [ File "LICENSE" (unLicense settingsLicenseText) | hasLicense ] ++-    maybeToList (File "CONTRIBUTING.md" <$> settingsContributing)+    [ File "LICENSE" (unLicense settingsLicenseText) | hasLicense ]   where     hasLicense :: Bool-    hasLicense = settingsLicenseName /= None+    hasLicense = settingsLicenseName /= NONE      licenseName :: Text     licenseName = show settingsLicenseName@@ -40,57 +38,61 @@         [ "# " <> settingsRepo         , ""         ]-     ++ [travisBadge       | settingsTravis]-     ++ [appVeyorBadge     | settingsAppVeyor]-     ++ [hackage]-     ++ [stackLtsBadge     | settingsStack]-     ++ [stackNightlyBadge | settingsStack]-     ++ [licenseBadge      | hasLicense]+     ++ [githubActionsBadge | settingsGhActions]+     ++ [travisBadge        | settingsTravis]+     ++ [appVeyorBadge      | settingsAppVeyor]+     ++ [hackageBadge]+     ++ [stackLtsBadge      | settingsStack]+     ++ [stackNightlyBadge  | settingsStack]+     ++ [licenseBadge       | hasLicense]      ++ [""         , settingsDescription         ]       where-        hackageShield :: Text =-            "https://img.shields.io/hackage/v/" <> settingsRepo <> ".svg?logo=haskell"-        hackageLink :: Text =-            "https://hackage.haskell.org/package/" <> settingsRepo-        hackage :: Text = makeBadge "Hackage" hackageShield hackageLink+        shieldsIo :: Text+        shieldsIo = "https://img.shields.io/" -        licenseShield :: Text =-            "https://img.shields.io/badge/license-" <> T.replace "-" "--" licenseName <> "-blue.svg"-        licenseBadge :: Text =-            makeBadge (licenseName <> " license") licenseShield "LICENSE"+        hackageShield, hackageLink, hackageBadge :: Text+        hackageShield = shieldsIo <> "hackage/v/" <> settingsRepo <> ".svg?logo=haskell"+        hackageLink   = "https://hackage.haskell.org/package/" <> settingsRepo+        hackageBadge  = makeBadge "Hackage" hackageShield hackageLink -        stackShieldLts :: Text =-            "http://stackage.org/package/" <> settingsRepo <> "/badge/lts"-        stackLinkLts :: Text =-            "http://stackage.org/lts/package/" <> settingsRepo+        licenseShield, licenseBadge :: Text+        licenseShield = shieldsIo <> "badge/license-" <> T.replace "-" "--" licenseName <> "-blue.svg"+        licenseBadge  = makeBadge (licenseName <> " license") licenseShield "LICENSE" -        stackShieldNightly :: Text =-            "http://stackage.org/package/" <> settingsRepo <> "/badge/nightly"-        stackLinkNightly :: Text =-            "http://stackage.org/nightly/package/" <> settingsRepo-        stackLtsBadge :: Text =-            makeBadge "Stackage Lts" stackShieldLts stackLinkLts-        stackNightlyBadge :: Text =-            makeBadge "Stackage Nightly" stackShieldNightly stackLinkNightly+        stackOrg, stackLtsShield, stackLtsLink, stackLtsBadge :: Text+        stackOrg       = "http://stackage.org/"+        stackLtsShield = stackOrg <> "package/" <> settingsRepo <> "/badge/lts"+        stackLtsLink   = stackOrg <> "lts/package/" <> settingsRepo+        stackLtsBadge  = makeBadge "Stackage Lts" stackLtsShield stackLtsLink -        travisShield :: Text =-            "https://img.shields.io/travis/" <> settingsOwner <> "/" <> settingsRepo <> ".svg?logo=travis"-        travisLink :: Text =-            "https://travis-ci.org/" <> settingsOwner <> "/" <> settingsRepo-        travisBadge :: Text =-            makeBadge "Build status" travisShield travisLink+        stackNightlyShield, stackNightlyLink, stackNightlyBadge :: Text+        stackNightlyShield = stackOrg <> "package/" <> settingsRepo <> "/badge/nightly"+        stackNightlyLink   = stackOrg <> "nightly/package/" <> settingsRepo+        stackNightlyBadge  = makeBadge "Stackage Nightly" stackNightlyShield stackNightlyLink -        appVeyorShield :: Text =-            "https://ci.appveyor.com/api/projects/status/github/" <> settingsOwner <> "/" <> settingsRepo <> "?branch=master&svg=true"-        appVeyorLink :: Text =-            "https://ci.appveyor.com/project/" <> settingsOwner <> "/" <> settingsRepo-        appVeyorBadge :: Text =-            makeBadge "Windows build status" appVeyorShield appVeyorLink+        githubActionsShield, githubActionsLink, githubActionsBadge :: Text+        githubActionsShield = "https://github.com/" <> ownerRepo <> "/workflows/CI/badge.svg"+        githubActionsLink   = "https://github.com/" <> ownerRepo <> "/actions"+        githubActionsBadge  = makeBadge "GitHub CI" githubActionsShield githubActionsLink +        travisShield, travisLink, travisBadge :: Text+        travisShield = shieldsIo <> "travis/" <> ownerRepo <> ".svg?logo=travis"+        travisLink   = "https://travis-ci.org/" <> ownerRepo+        travisBadge  = makeBadge "Build status" travisShield travisLink++        appVeyorCom, appVeyorShield, appVeyorLink, appVeyorBadge :: Text+        appVeyorCom    = "https://ci.appveyor.com/"+        appVeyorShield = appVeyorCom <> "api/projects/status/github/" <> ownerRepo <> "?branch=master&svg=true"+        appVeyorLink   = appVeyorCom <> "project/" <> ownerRepo+        appVeyorBadge  = makeBadge "Windows build status" appVeyorShield appVeyorLink+         makeBadge :: Text -> Text -> Text -> Text         makeBadge title shield link = "[![" <> title <> "](" <> shield <> ")](" <> link <> ")"++        ownerRepo :: Text+        ownerRepo = settingsOwner <> "/" <> settingsRepo      changelog :: Text     changelog = unlines $
src/Summoner/Template/GitHub.hs view
@@ -9,12 +9,13 @@ This module contains template for GitHub related docs:   * @.gitignore@ — static file with all Haskell related ignored files.- * @appveyor.yml@ — Appveyor CI for Stack project only.+ * @.github/workflows/ci.yml@ — GitHub acttions for Cabal projects.+ * @appveyor.yml@ — Appveyor CI for Cabal or Stack projects.  * @.travis.yml@ — depending on the build tool and supported GHC versions    builds the Travis matrix with all necessary checks, including HLint check.-   __NOTE:__ Old GHC versions is not included into Travis matrix for Stack due to-   Stack limitations with the Cabal version usage on each GHC. See this issue to-   track the problem:+   __NOTE:__ Old GHC versions are included into @allow_failure@ Travis matrix+   section for Stack due to Stack limitations with the Cabal version usage on+   each GHC. See this issue to track the problem:      + https://github.com/commercialhaskell/stack/issues/4488 -}@@ -23,20 +24,21 @@        ( gitHubFiles        ) where -import Data.List ((\\))+import Data.List (delete, intersect) import NeatInterpolation (text) -import Summoner.Default (defaultGHC)+import Summoner.Default (defaultCabal, defaultGHC) import Summoner.GhcVer (GhcVer (..), oldGhcs, showGhcVer) import Summoner.Settings (Settings (..)) import Summoner.Template.Mempty (memptyIfFalse)-import Summoner.Text (endLine, tconcatMap)+import Summoner.Text (endLine, intercalateMap, tconcatMap) import Summoner.Tree (TreeFs (..))   gitHubFiles :: Settings -> [TreeFs] gitHubFiles Settings{..} = concat     [ [File ".gitignore" (gitignoreDefault <> gitignoreCustom) | settingsGitHub]+    , [Dir ".github" [ Dir "workflows" [ File "ci.yml" ghActionsYml ]] | settingsGhActions ]     , [File ".travis.yml" travisYml    | settingsTravis]     , [File "appveyor.yml" appVeyorYml | settingsAppVeyor]     ]@@ -107,6 +109,62 @@         then ""         else unlines ("\n# User specific" : settingsGitignore) +    ghActionsYml :: Text+    ghActionsYml = [text|+        name: CI++        # Trigger the workflow on push or pull request, but only for the master branch+        on:+          pull_request:+          push:+            branches: [master]++        jobs:+          build:+            name: ghc ${{ matrix.ghc }}+            runs-on: ubuntu-16.04+            strategy:+              matrix:+                cabal: ["${defaultCabal}"]+                ghc:+                  ${ghActionsVersions}++            steps:+            - uses: actions/checkout@v2+              if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/master'++            - uses: actions/setup-haskell@v1+              name: Setup Haskell+              with:+                ghc-version: ${{ matrix.ghc }}+                cabal-version: ${{ matrix.cabal }}++            - uses: actions/cache@v1+              name: Cache ~/.cabal/store+              with:+                path: ~/.cabal/store+                key: ${{ runner.os }}-${{ matrix.ghc }}-cabal++            - name: Build+              run: |+                $cabalUpdate+                $cabalBuild++            - name: Test+              run: |+                ${cabalTest}+        |]+++    ghActionsVersions :: Text+    ghActionsVersions = intercalateMap+        "\n"+        (\ghc -> "- " <> ghActionsMatrixItem ghc)+        settingsTestedVersions++    ghActionsMatrixItem :: GhcVer -> Text+    ghActionsMatrixItem v = "\"" <> showGhcVer v <> "\""+     -- create travis.yml template     travisYml :: Text     travisYml =@@ -117,7 +175,7 @@         git:           depth: 5 -        cabal: "2.4"+        cabal: "${defaultCabal}"          cache:           directories:@@ -128,6 +186,7 @@           include:           $travisCabalMtr           $travisStackMtr+          $travisStackAllowFailuresMtr          $installAndScript @@ -143,12 +202,6 @@         - "$$TRAVIS_BUILD_DIR/.stack-work"         |] --    cabalTest :: Text-    cabalTest = if settingsTest-        then "cabal new-test --enable-tests"-        else "echo 'No tests'"-     travisCabalMtr :: Text     travisCabalMtr = memptyIfFalse settingsCabal $         tconcatMap travisCabalMatrixItem settingsTestedVersions@@ -156,12 +209,27 @@     travisCabalMatrixItem :: GhcVer -> Text     travisCabalMatrixItem (showGhcVer -> ghcV) = [text|- ghc: $ghcV|] -    -- Due to Stach issues with newer Cabal versions we are not supporting Travis CI for GHC <= 8.0.2 for stack+    -- Due to the Stack issues with newer Cabal versions TravisCI for 'oldGhcs'+    -- can fail. Possible failure jobs are added to the @allow-failures@ section.     travisStackMtr :: Text     travisStackMtr = memptyIfFalse settingsStack $ tconcatMap-           travisStackMatrixItem (settingsTestedVersions \\ (defaultGHC:oldGhcs))+           travisStackMatrixItem (delete defaultGHC settingsTestedVersions)         <> travisStackMatrixDefaultItem +    travisStackAllowFailuresMtr :: Text+    travisStackAllowFailuresMtr = memptyIfFalse (settingsStack && not (null old))+        [text|+        $endLine+        allow_failures:+        $matrix+        |]+      where+        old :: [GhcVer]+        old = settingsTestedVersions `intersect` oldGhcs++        matrix :: Text+        matrix = tconcatMap travisStackMatrixItem old+     travisStackMatrixItem :: GhcVer -> Text     travisStackMatrixItem (showGhcVer -> ghcV) =         [text|@@ -194,22 +262,20 @@            - |             if [ -z "$$STACK_YAML" ]; then-              ghc --version-              cabal --version-              cabal new-update-              cabal new-build --enable-tests --enable-benchmarks+              $cabalUpdate+              $cabalBuild             else               curl -sSL https://get.haskellstack.org/ | sh               stack --version-              stack build --system-ghc --test --bench --no-run-tests --no-run-benchmarks --ghc-options=-Werror+              $stackBuild             fi          script:           - |             if [ -z "$$STACK_YAML" ]; then-               ${cabalTest}+              ${cabalTest}             else-              stack test --system-ghc+              $stackTest             fi         |] @@ -219,8 +285,8 @@         install:           $hlintCheck -          - cabal new-update-          - cabal new-build --enable-tests --enable-benchmarks+          - $cabalUpdate+          - $cabalBuild          script:           - ${cabalTest}@@ -234,12 +300,29 @@            - curl -sSL https://get.haskellstack.org/ | sh           - stack --version-          - stack build --system-ghc --test --bench --no-run-tests --no-run-benchmarks --ghc-options=-Werror+          - $stackBuild          script:-          - stack test --system-ghc+          - $stackTest         |] +    cabalUpdate :: Text+    cabalUpdate = "cabal v2-update"++    cabalBuild :: Text+    cabalBuild = "cabal v2-build --enable-tests --enable-benchmarks"++    cabalTest :: Text+    cabalTest = if settingsTest+        then "cabal v2-test --enable-tests"+        else "echo 'No tests'"++    stackBuild :: Text+    stackBuild = "stack build --system-ghc --test --bench --no-run-tests --no-run-benchmarks --ghc-options=-Werror"++    stackTest :: Text+    stackTest = "stack test --system-ghc"+     hlintCheck :: Text     hlintCheck =         [text|@@ -322,7 +405,7 @@           - stack setup > nul          build_script:-          - stack build --test --bench --no-run-tests --no-run-benchmarks+          - stack build --test --bench --no-run-tests --no-run-benchmarks --ghc-options=-Werror          test_script:           - stack test
src/Summoner/Template/Haskell.hs view
@@ -14,7 +14,6 @@  import NeatInterpolation (text) -import Summoner.CustomPrelude (CustomPrelude (..)) import Summoner.Settings (Settings (..)) import Summoner.Text (packageToModule) import Summoner.Tree (TreeFs (..))@@ -22,19 +21,28 @@  haskellFiles :: Settings -> [TreeFs] haskellFiles Settings{..} = concat-    [ [ Dir "src"     $ libFile : preludeFile   | settingsIsLib ]-    , [ Dir "app"       [exeFile]               | settingsIsExe ]-    , [ Dir "test"      [testFile]              | settingsTest  ]-    , [ Dir "benchmark" [benchmarkFile]         | settingsBench ]-    ] ++ maybeToList (File ".stylish-haskell.yaml" <$> settingsStylish)+    [ [ Dir "src"       [libFile]       | settingsIsLib ]+    , [ Dir "app"       [exeFile]       | settingsIsExe ]+    , [ Dir "test"      [testFile]      | settingsTest  ]+    , [ Dir "benchmark" [benchmarkFile] | settingsBench ]+    ]   where     libFile :: TreeFs     libFile = File (toString libModuleName <> ".hs")         [text|+        {- |+        Copyright: (c) $settingsYear $settingsFullName+        SPDX-License-Identifier: $licenseName+        Maintainer: $settingsFullName <$settingsEmail>++        $settingsDescription+        -}+         module $libModuleName                ( someFunc                ) where +         someFunc :: IO ()         someFunc = putStrLn ("someFunc" :: String)         |]@@ -42,18 +50,8 @@     libModuleName :: Text     libModuleName = packageToModule settingsRepo -    preludeFile :: [TreeFs]-    preludeFile = maybeToList $-        settingsPrelude <&> \CustomPrelude{..} -> File "Prelude.hs"-            [text|-            -- | Uses [$cpPackage](https://hackage.haskell.org/package/${cpPackage}) as default Prelude.--            module Prelude-                   ( module $cpModule-                   ) where--            import $cpModule-            |]+    licenseName :: Text+    licenseName = show settingsLicenseName      exeFile :: TreeFs     exeFile = File "Main.hs" $ if settingsIsLib then createExe else createOnlyExe@@ -63,6 +61,7 @@         [text|         module Main (main) where +         main :: IO ()         main = putStrLn ("Hello, world!" :: String)         |]@@ -84,8 +83,9 @@         [text|         module Main (main) where +         main :: IO ()-        main = putStrLn ("Test suite not yet implemented" :: String)+        main = putStrLn ("Test suite is not implemented" :: String)         |]      benchmarkFile :: TreeFs
src/Summoner/Template/Stack.hs view
@@ -11,7 +11,7 @@        ) where  import Summoner.Default (defaultGHC)-import Summoner.GhcVer (GhcVer (..), baseVer, latestLts, showGhcVer)+import Summoner.GhcVer (GhcVer (..), latestLts, showGhcVer) import Summoner.Settings (Settings (..)) import Summoner.Tree (TreeFs (..)) @@ -22,14 +22,9 @@     -- create @stack.yaml@ file with LTS corresponding to specified ghc version     createStackYaml :: GhcVer -> TreeFs     createStackYaml ghcV = File (toString $ "stack" <> ver <> ".yaml")-        $ "resolver: " <> latestLts ghcV <> extraDeps+        $ "resolver: " <> latestLts ghcV <> "\n"       where         ver :: Text         ver = if ghcV == defaultGHC               then ""               else "-" <> showGhcVer ghcV--        extraDeps :: Text-        extraDeps = case settingsPrelude of-            Nothing -> ""-            Just _  -> "\n\nextra-deps: [base-noprelude-" <> baseVer ghcV <> "]"
src/Summoner/Text.hs view
@@ -49,8 +49,9 @@         && T.all C.isAlphaNum s         && C.isUpper (T.head s) --- | Converts every element of list into 'Text' and then joins every element--- into single 'Text' like 'T.intercalate'.+{- | Converts every element of list into 'Text' and then joins every element+into single 'Text' like 'T.intercalate'.+-} intercalateMap :: Text -> (a -> Text) -> [a] -> Text intercalateMap between showT = T.intercalate between . map showT 
src/Summoner/Tree.hs view
@@ -17,12 +17,11 @@        , showTree        ) where +import Colourista (bold, reset) import System.Directory (createDirectoryIfMissing, withCurrentDirectory) import System.FilePath (splitDirectories) -import Summoner.Ansi (boldCode, resetCode) - -- | Describes simple structure of filesystem tree. data TreeFs       -- | Name of directory (relative) and its containing entries@@ -55,11 +54,11 @@ pathToTree path content =     let pathParts = splitDirectories path     in case pathParts of-        [] -> Dir path []  -- shouldn't happen+        []   -> Dir path []  -- shouldn't happen         x:xs -> go x xs   where     go :: FilePath -> [FilePath] -> TreeFs-    go p [] = File p content+    go p []     = File p content     go p (x:xs) = Dir p [go x xs]  {- | This functions inserts given 'TreeFs' node into the list of existing@@ -103,7 +102,7 @@             boldDir :: FilePath -> Text             boldDir str = toText $                 if isBold-                then boldCode <> str <> resetCode+                then bold <> str <> reset                 else str          extension :: Text
summoner.cabal view
@@ -1,6 +1,6 @@ cabal-version:       2.4 name:                summoner-version:             1.4.0.0+version:             2.0.0.0 synopsis:            Tool for scaffolding fully configured batteries-included production-level Haskell projects. description:         Tool for scaffolding fully configured batteries-included production-level Haskell projects.                      See [README.md](https://github.com/kowainik/summoner#-summoner) for details.@@ -15,55 +15,84 @@ build-type:          Simple stability:           stable extra-doc-files:     README.md-                   , CHANGELOG.md-tested-with:         GHC == 8.2.2-                   , GHC == 8.4.4-                   , GHC == 8.6.5-                   , GHC == 8.8.1+                     CHANGELOG.md+tested-with:         GHC == 8.4.4+                     GHC == 8.6.5+                     GHC == 8.8.3 extra-source-files:-    test/golden/fullProject/*.yml-    test/golden/fullProject/*.yaml-    test/golden/fullProject/*.md-    test/golden/fullProject/*.cabal-    test/golden/fullProject/src/*.hs-    test/golden/fullProject/app/*.hs-    test/golden/fullProject/test/*.hs-    test/golden/fullProject/benchmark/*.hs-    test/golden/fullProject/.gitignore-    test/golden/fullProject/.travis.yml-    test/golden/fullProject/.stylish-haskell.yaml-    test/golden/fullProject/stack-8.4.4.yaml-    test/golden/fullProject/stack-8.2.2.yaml-    test/golden/fullProject/stack-8.0.2.yaml-    test/golden/fullProject/LICENSE+    examples/summoner-default.toml -    test/golden/smallProject/*.md-    test/golden/smallProject/*.cabal-    test/golden/smallProject/app/*.hs+    examples/cabal-minimal/*.md+    examples/cabal-minimal/*.cabal+    examples/cabal-minimal/app/*.hs +    examples/cabal-full/*.yml+    examples/cabal-full/*.md+    examples/cabal-full/*.cabal+    examples/cabal-full/src/*.hs+    examples/cabal-full/app/*.hs+    examples/cabal-full/test/*.hs+    examples/cabal-full/benchmark/*.hs+    examples/cabal-full/.gitignore+    examples/cabal-full/.github/workflows/ci.yml+    examples/cabal-full/.travis.yml+    examples/cabal-full/LICENSE++    examples/stack-full/*.yml+    examples/stack-full/*.yaml+    examples/stack-full/*.md+    examples/stack-full/*.cabal+    examples/stack-full/src/*.hs+    examples/stack-full/app/*.hs+    examples/stack-full/test/*.hs+    examples/stack-full/benchmark/*.hs+    examples/stack-full/.gitignore+    examples/stack-full/.travis.yml+    examples/stack-full/LICENSE++    examples/full-batteries/*.yml+    examples/full-batteries/*.yaml+    examples/full-batteries/*.md+    examples/full-batteries/*.cabal+    examples/full-batteries/*.txt+    examples/full-batteries/src/*.hs+    examples/full-batteries/app/*.hs+    examples/full-batteries/test/*.hs+    examples/full-batteries/benchmark/*.hs+    examples/full-batteries/.gitignore+    examples/full-batteries/.github/CODEOWNERS+    examples/full-batteries/.github/workflows/ci.yml+    examples/full-batteries/.stylish-haskell.yaml+    examples/full-batteries/.travis.yml+    examples/full-batteries/LICENSE+ source-repository head   type:     git   location: git@github.com:kowainik/summoner.git  common common-options-  build-depends:       base >= 4.10 && < 4.14+  build-depends:       base >= 4.11 && < 4.14                      , relude ^>= 0.6.0.0    mixins:              base hiding (Prelude)                      , relude (Relude as Prelude                               , Relude.Extra.Enum-                              , Relude.Extra.Validation                               , Relude.Unsafe                               )    ghc-options:         -Wall-                       -Wincomplete-uni-patterns-                       -Wincomplete-record-updates                        -Wcompat                        -Widentities-                       -Wredundant-constraints-                       -fhide-source-paths-  if impl(ghc >= 8.8.1)+                       -Wincomplete-uni-patterns+                       -Wincomplete-record-updates+  if impl(ghc >= 8.0)+    ghc-options:       -Wredundant-constraints+  if impl(ghc >= 8.2)+    ghc-options:       -fhide-source-paths+  if impl(ghc >= 8.4)+    ghc-options:       -Wmissing-export-lists+                       -Wpartial-fields+  if impl(ghc >= 8.8)     ghc-options:       -Wmissing-deriving-strategies                        -Werror=missing-deriving-strategies @@ -91,6 +120,7 @@                          Summoner.Default                          Summoner.GhcVer                          Summoner.License+                         Summoner.Mode                          Summoner.Project                          Summoner.Question                          Summoner.Settings@@ -110,12 +140,12 @@   other-modules:       Paths_summoner    build-depends:       aeson >= 1.2.4.0 && < 1.5-                     , ansi-terminal >= 0.8 && < 0.11                      , bytestring ^>= 0.10.8.2-                     , containers+                     , colourista ^>= 0.0+                     , containers ^>= 0.6                      , directory ^>= 1.3.0.2                      , filepath ^>= 1.4.1.2-                     , generic-deriving >= 1.12.2 && < 1.14+                     , generic-data ^>= 0.8.0.0                      , gitrev ^>= 1.3.1                      , neat-interpolation ^>= 0.3.2.2                      , optparse-applicative ^>= 0.15@@ -124,6 +154,7 @@                      , text ^>= 1.2.3.0                      , time >= 1.8 && < 1.10                      , tomland ^>= 1.2.1.0+                     , validation-selective ^>= 0.0.0.0  executable summon   import:              common-options@@ -153,11 +184,13 @@                      , filepath                      , hedgehog >= 0.5.3 && < 1.1                      , hspec >= 2.4.8+                     , hspec-hedgehog ^>= 0.0.1.1                      , neat-interpolation                      , text                      , tomland                      , tree-diff >= 0.0.2 && < 0.2                      , summoner+                     , validation-selective    ghc-options:         -threaded                        -rtsopts
test/Spec.hs view
@@ -1,33 +1,22 @@-module Main where+module Main (main) where -import Hedgehog (Group (..), checkParallel) import Test.Hspec (hspec)  import Test.CustomPrelude (customPreludeSpec)-import Test.DecisionSpec (decisionMonoidMempty, decisionSemigroupAssoc)+import Test.DecisionSpec (decisionPropertySpec) import Test.Golden (goldenSpec) import Test.QuestionSpec (yesNoPromptSpec) import Test.Script (scriptSpec) import Test.Show (showCommandSpec)-import Test.TomlSpec (tomlProp)+import Test.TomlSpec (tomlSpec)   main :: IO ()-main = do-    hspec $ do-        yesNoPromptSpec-        scriptSpec-        showCommandSpec-        goldenSpec-        customPreludeSpec-    ifM (checkParallel hedgehogTests) exitSuccess exitFailure--hedgehogTests :: Group-hedgehogTests = Group "Roundtrip properties"-    [ decisionSemigroupAssoc `named` "Decision Semigroup:Assoc"-    , decisionMonoidMempty   `named` "Decision Monoid:Mempty"-    , tomlProp               `named` "decode . encode == id"-    ]-  where-    named :: a -> b -> (b, a)-    named = flip (,)+main = hspec $ do+    yesNoPromptSpec+    scriptSpec+    showCommandSpec+    goldenSpec+    customPreludeSpec+    tomlSpec+    decisionPropertySpec
test/Test/DecisionSpec.hs view
@@ -2,32 +2,33 @@ {- HLINT ignore "Monoid law, left identity" -}  module Test.DecisionSpec-       ( decisionSemigroupAssoc-       , decisionMonoidMempty+       ( decisionPropertySpec           -- * Gen        , genDecision        ) where -import Hedgehog (MonadGen, Property, forAll, property, (===))+import Hedgehog (MonadGen, forAll, (===))+import Test.Hspec (Spec, describe, it)+import Test.Hspec.Hedgehog (hedgehog)  import Summoner.Decision (Decision)  import qualified Hedgehog.Gen as Gen  -decisionSemigroupAssoc :: Property-decisionSemigroupAssoc = property $ do-    x <- forAll genDecision-    y <- forAll genDecision-    z <- forAll genDecision-    (x <> y) <> z === x <> (y <> z)+decisionPropertySpec :: Spec+decisionPropertySpec = describe "Decision property tests" $ do+    it "Decision Semigroup:Assoc" $ hedgehog $ do+        x <- forAll genDecision+        y <- forAll genDecision+        z <- forAll genDecision+        (x <> y) <> z === x <> (y <> z) -decisionMonoidMempty :: Property-decisionMonoidMempty = property $ do-    x <- forAll genDecision-    x <> mempty === x-    mempty <> x === x+    it "Decision Monoid:Mempty" $ hedgehog $ do+        x <- forAll genDecision+        x <> mempty === x+        mempty <> x === x  genDecision :: MonadGen m => m Decision genDecision = Gen.enumBounded
test/Test/Golden.hs view
@@ -33,10 +33,14 @@  goldenSpec :: Spec goldenSpec = describe "golden tests" $ do-    it "correctly creates full project" $-        checkProject "test/golden/fullProject" fullProject-    it "correctly creates small project" $-        checkProject "test/golden/smallProject" smallProject+    it "correctly scaffolds the 'cabal-minimal' project" $+        checkProject "examples/cabal-minimal" cabalMinimal+    it "correctly scaffolds the 'cabal-full' project" $+        checkProject "examples/cabal-full" cabalFull+    it "correctly scaffolds the 'stack-full' project" $+        checkProject "examples/stack-full" stackFull+    it "correctly scaffolds the 'full-batteries' project" $+        checkProject "examples/full-batteries" fullBatteries   where     checkProject :: FilePath -> Settings -> IO ()     checkProject path settings = do@@ -61,18 +65,19 @@     Dir path fs -> Dir path $ sort $ map sortTree fs  -fullProject :: Settings-fullProject = Settings-    { settingsRepo           = "fullProject"+fullBatteries :: Settings+fullBatteries = Settings+    { settingsRepo           = "full-batteries"     , settingsOwner          = "kowainik"-    , settingsDescription    = "Full test project"+    , settingsDescription    = "Full-featured test project"     , settingsFullName       = "Kowainik"     , settingsEmail          = "xrom.xkov@gmail.com"-    , settingsYear           = "2018"+    , settingsYear           = "2020"     , settingsCategories     = "Testing"     , settingsLicenseName    = MIT     , settingsLicenseText    = mitLicense     , settingsGitHub         = True+    , settingsGhActions      = True     , settingsPrivate        = True     , settingsTravis         = True     , settingsAppVeyor       = True@@ -81,59 +86,121 @@     , settingsTest           = True     , settingsBench          = True     , settingsTestedVersions = [Ghc802 .. defaultGHC]-    , settingsBaseType       = "base-noprelude"     , settingsPrelude        = Just $ CustomPrelude "relude" "Relude"     , settingsExtensions     = ["ConstraintKinds", "LambdaCase", "OverloadedStrings"]     , settingsGitignore      = [".secret"]     , settingsGhcOptions     = ["-Wcompat", "-Widentities"]     , settingsCabal          = True     , settingsStack          = True-    , settingsStylish        = Just "This is stylish-haskell.yaml\n"-    , settingsContributing   = Just "This is contributing guide\n"     , settingsNoUpload       = True     , settingsFiles          =         [ File "extra.txt" "See full content of the file [here](@github)\n"         , Dir ".github" [File "CODEOWNERS" "*  @chshersh @vrom911\n"]+        , File ".stylish-haskell.yaml" "This is stylish-haskell.yaml\n"+        , File "CONTRIBUTING.md" "This is contributing guide\n"         ]     }   where     mitLicense :: License     mitLicense = License [text|-    MIT License+MIT License -    Copyright (c) 2018 Kowainik+Copyright (c) 2018 Kowainik -    Permission is hereby granted, free of charge, to any person obtaining a copy-    of this software and associated documentation files (the "Software"), to deal-    in the Software without restriction, including without limitation the rights-    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell-    copies of the Software, and to permit persons to whom the Software is-    furnished to do so, subject to the following conditions:+Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions: -    The above copyright notice and this permission notice shall be included in all-    copies or substantial portions of the Software.+The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software. -    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR-    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,-    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE-    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER-    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,-    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE-    SOFTWARE.-    |]+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.+|] -smallProject :: Settings-smallProject = Settings-    { settingsRepo           = "smallProject"+stackFull :: Settings+stackFull = Settings+    { settingsRepo           = "stack-full"     , settingsOwner          = "kowainik"-    , settingsDescription    = "Small test project"+    , settingsDescription    = "Stack-only example with all integrations"     , settingsFullName       = "Kowainik"     , settingsEmail          = "xrom.xkov@gmail.com"-    , settingsYear           = "2018"+    , settingsYear           = "2020"+    , settingsCategories     = "Testing"+    , settingsLicenseName    = BSD3+    , settingsLicenseText    = bsd3License+    , settingsGitHub         = True+    , settingsGhActions      = False+    , settingsPrivate        = False+    , settingsTravis         = True+    , settingsAppVeyor       = True+    , settingsIsLib          = True+    , settingsIsExe          = True+    , settingsTest           = True+    , settingsBench          = True+    , settingsTestedVersions = [Ghc844 .. defaultGHC]+    , settingsPrelude        = Just $ CustomPrelude "relude" "Relude"+    , settingsExtensions     = ["DeriveGeneric", "TypeApplications"]+    , settingsGitignore      = []+    , settingsGhcOptions     = []+    , settingsCabal          = False+    , settingsStack          = True+    , settingsNoUpload       = False+    , settingsFiles          = []+    }++cabalFull :: Settings+cabalFull = Settings+    { settingsRepo           = "cabal-full"+    , settingsOwner          = "kowainik"+    , settingsDescription    = "Cabal-only example with all integrations"+    , settingsFullName       = "Kowainik"+    , settingsEmail          = "xrom.xkov@gmail.com"+    , settingsYear           = "2020"+    , settingsCategories     = "Testing"+    , settingsLicenseName    = BSD3+    , settingsLicenseText    = bsd3License+    , settingsGitHub         = True+    , settingsGhActions      = True+    , settingsPrivate        = False+    , settingsTravis         = True+    , settingsAppVeyor       = True+    , settingsIsLib          = True+    , settingsIsExe          = True+    , settingsTest           = True+    , settingsBench          = True+    , settingsTestedVersions = [Ghc844 .. defaultGHC]+    , settingsPrelude        = Just $ CustomPrelude "relude" "Relude"+    , settingsExtensions     = ["DeriveGeneric", "TypeApplications"]+    , settingsGitignore      = []+    , settingsGhcOptions     = []+    , settingsCabal          = True+    , settingsStack          = False+    , settingsNoUpload       = False+    , settingsFiles          = []+    }++cabalMinimal :: Settings+cabalMinimal = Settings+    { settingsRepo           = "cabal-minimal"+    , settingsOwner          = "kowainik"+    , settingsDescription    = "Minimal cabal-only test project"+    , settingsFullName       = "Kowainik"+    , settingsEmail          = "xrom.xkov@gmail.com"+    , settingsYear           = "2020"     , settingsCategories     = ""-    , settingsLicenseName    = None+    , settingsLicenseName    = NONE     , settingsLicenseText    = ""     , settingsGitHub         = False+    , settingsGhActions      = False     , settingsPrivate        = False     , settingsTravis         = False     , settingsAppVeyor       = False@@ -142,18 +209,48 @@     , settingsTest           = False     , settingsBench          = False     , settingsTestedVersions = [defaultGHC]-    , settingsBaseType       = "base"     , settingsPrelude        = Nothing     , settingsExtensions     = []     , settingsGhcOptions     = []     , settingsGitignore      = []     , settingsCabal          = True     , settingsStack          = False-    , settingsStylish        = Nothing-    , settingsContributing   = Nothing     , settingsNoUpload       = True     , settingsFiles          = mempty     }++bsd3License :: License+bsd3License = License [text|+BSD 3-Clause License++Copyright (c) 2020, Kowainik+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice, this+   list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright notice,+   this list of conditions and the following disclaimer in the documentation+   and/or other materials provided with the distribution.++3. Neither the name of the copyright holder nor the names of its+   contributors may be used to endorse or promote products derived from+   this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+|]  -- Orphan instances 
test/Test/Script.hs view
@@ -35,7 +35,7 @@ stackScript = [text| #!/usr/bin/env stack {- stack-  --resolver lts-14.18+  --resolver lts-14.27   script   --package base -}
test/Test/Show.hs view
@@ -14,10 +14,10 @@  goldenGhcTable :: [Text] goldenGhcTable =-  [ "GHC-7.10.3    base-4.8.0.2    lts-6.35          "-  , "GHC-8.0.2     base-4.9.1.0    lts-9.21          "-  , "GHC-8.2.2     base-4.10.1.0   lts-11.22         "-  , "GHC-8.4.4     base-4.11.1.0   lts-12.26         "-  , "GHC-8.6.5     base-4.12.0.0   lts-14.18         "-  , "GHC-8.8.1     base-4.13.0.0   nightly-2019-12-25"+  [ "GHC-7.10.3    base-4.8.0.2    lts-6.35"+  , "GHC-8.0.2     base-4.9.1.0    lts-9.21"+  , "GHC-8.2.2     base-4.10.1.0   lts-11.22"+  , "GHC-8.4.4     base-4.11.1.0   lts-12.26"+  , "GHC-8.6.5     base-4.12.0.0   lts-14.27"+  , "GHC-8.8.3     base-4.13.0.0   lts-15.5"   ]
test/Test/TomlSpec.hs view
@@ -1,13 +1,17 @@ module Test.TomlSpec-       ( tomlProp+       ( tomlSpec        ) where -import Hedgehog (MonadGen, Property, forAll, property, tripping)+import Hedgehog (MonadGen, forAll, tripping) import Relude.Extra.Enum (universe)+import Test.Hspec (Spec, describe, it, shouldReturn, shouldSatisfy)+import Test.Hspec.Hedgehog (hedgehog) import Toml.Bi.Code (decode, encode)+import Validation (Validation (..)) -import Summoner.Config (ConfigP (..), PartialConfig, configCodec)+import Summoner.Config (ConfigP (..), PartialConfig, configCodec, defaultConfig, finalise) import Summoner.CustomPrelude (CustomPrelude (..))+import Summoner.Default (defaultConfigFileContent) import Summoner.GhcVer (GhcVer) import Summoner.License (LicenseName) import Summoner.Source (Source (..))@@ -18,11 +22,30 @@ import qualified Hedgehog.Range as Range  -tomlProp :: Property-tomlProp = property $ do-    configToml <- forAll genPartialConfig-    tripping configToml (encode configCodec) (decode configCodec)+tomlSpec :: Spec+tomlSpec = describe "TOML Testing" $ do+    tomlConfigSpec+    tomlProp +tomlConfigSpec :: Spec+tomlConfigSpec = describe "TOML configuration spec" $ do+    it "finalises default configuration" $+        finalise defaultConfig `shouldSatisfy` isSuccess+    it "parses default configuration" $+        decode configCodec defaultConfigFileContent `shouldSatisfy` isRight+    it "default configuration is up-to-date" $+        readFileText "examples/summoner-default.toml"+            `shouldReturn` defaultConfigFileContent+  where+    isSuccess :: Validation e a -> Bool+    isSuccess = \case { Success _ -> True; _ -> False }++tomlProp :: Spec+tomlProp = describe "TOML property tests" $+    it "decode . encode == id" $ hedgehog $ do+        configToml <- forAll genPartialConfig+        tripping configToml (encode configCodec) (decode configCodec)+ ---------------------------------------------------------------------------- -- Generators ----------------------------------------------------------------------------@@ -72,6 +95,7 @@     cCabal      <- genDecision     cStack      <- genDecision     cGitHub     <- genDecision+    cGhActions  <- genDecision     cTravis     <- genDecision     cAppVey     <- genDecision     cPrivate    <- genDecision@@ -83,8 +107,6 @@     cExtensions <- genTextArr     cGhcOptions <- genTextArr     cGitignore  <- genTextArr-    cStylish    <- Last <$> Gen.maybe genSource-    cContributing <- Last <$> Gen.maybe genSource     cNoUpload   <- Any <$> Gen.bool     cFiles <- Gen.map (Range.constant 0 10) (liftA2 (,) genString genSource)-    pure Config{..}+    pure ConfigP{..}
− test/golden/fullProject/.gitignore
@@ -1,57 +0,0 @@-### Haskell-dist-dist-*-cabal-dev-*.o-*.hi-*.chi-*.chs.h-*.dyn_o-*.dyn_hi-*.prof-*.aux-*.hp-*.eventlog-.virtualenv-.hsenv-.hpc-.cabal-sandbox/-cabal.sandbox.config-cabal.config-cabal.project.local-.ghc.environment.*-.HTF/-# Stack-.stack-work/-stack.yaml.lock--### IDE/support-# Vim-[._]*.s[a-v][a-z]-[._]*.sw[a-p]-[._]s[a-v][a-z]-[._]sw[a-p]-*~-tags--# IntellijIDEA-.idea/-.ideaHaskellLib/-*.iml--# Atom-.haskell-ghc-mod.json--# VS-.vscode/--# Emacs-*#-.dir-locals.el-TAGS--# other-.DS_Store--# User specific-.secret
− test/golden/fullProject/.stylish-haskell.yaml
@@ -1,1 +0,0 @@-This is stylish-haskell.yaml
− test/golden/fullProject/.travis.yml
@@ -1,60 +0,0 @@-sudo: true-language: haskell--git:-  depth: 5--cabal: "2.4"--cache:-  directories:-  - "$HOME/.cabal/store"-  - "$HOME/.stack"-  - "$TRAVIS_BUILD_DIR/.stack-work"--matrix:-  include:-  - ghc: 8.0.2-  - ghc: 8.2.2-  - ghc: 8.4.4-  - ghc: 8.6.5-  - ghc: 8.8.1-  -  - ghc: 8.2.2-    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.2.2.yaml"-  -  - ghc: 8.4.4-    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.4.4.yaml"-  -  - ghc: 8.6.5-    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.6.5.yaml"-  -  - ghc: 8.8.1-    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack.yaml"--install:-  # HLint check-  - curl -sSL https://raw.github.com/ndmitchell/neil/master/misc/travis.sh | sh -s -- hlint .--  - |-    if [ -z "$STACK_YAML" ]; then-      ghc --version-      cabal --version-      cabal new-update-      cabal new-build --enable-tests --enable-benchmarks-    else-      curl -sSL https://get.haskellstack.org/ | sh-      stack --version-      stack build --system-ghc --test --bench --no-run-tests --no-run-benchmarks --ghc-options=-Werror-    fi--script:-  - |-    if [ -z "$STACK_YAML" ]; then-       cabal new-test --enable-tests-    else-      stack test --system-ghc-    fi--notifications:-  email: false
− test/golden/fullProject/CHANGELOG.md
@@ -1,11 +0,0 @@-# Changelog--`fullProject` uses [PVP Versioning][1].-The changelog is available [on GitHub][2].--## 0.0.0.0--* Initially created.--[1]: https://pvp.haskell.org-[2]: https://github.com/kowainik/fullProject/releases
− test/golden/fullProject/CONTRIBUTING.md
@@ -1,1 +0,0 @@-This is contributing guide
− test/golden/fullProject/LICENSE
@@ -1,21 +0,0 @@-MIT License--Copyright (c) 2018 Kowainik--Permission is hereby granted, free of charge, to any person obtaining a copy-of this software and associated documentation files (the "Software"), to deal-in the Software without restriction, including without limitation the rights-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell-copies of the Software, and to permit persons to whom the Software is-furnished to do so, subject to the following conditions:--The above copyright notice and this permission notice shall be included in all-copies or substantial portions of the Software.--THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE-SOFTWARE.
− test/golden/fullProject/README.md
@@ -1,10 +0,0 @@-# fullProject--[![Build status](https://img.shields.io/travis/kowainik/fullProject.svg?logo=travis)](https://travis-ci.org/kowainik/fullProject)-[![Windows build status](https://ci.appveyor.com/api/projects/status/github/kowainik/fullProject?branch=master&svg=true)](https://ci.appveyor.com/project/kowainik/fullProject)-[![Hackage](https://img.shields.io/hackage/v/fullProject.svg?logo=haskell)](https://hackage.haskell.org/package/fullProject)-[![Stackage Lts](http://stackage.org/package/fullProject/badge/lts)](http://stackage.org/lts/package/fullProject)-[![Stackage Nightly](http://stackage.org/package/fullProject/badge/nightly)](http://stackage.org/nightly/package/fullProject)-[![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)--Full test project
− test/golden/fullProject/app/Main.hs
@@ -1,7 +0,0 @@-module Main (main) where--import FullProject (someFunc)---main :: IO ()-main = someFunc
− test/golden/fullProject/appveyor.yml
@@ -1,34 +0,0 @@-clone_folder: "c:\\WORK"-clone_depth: 5--# Do not build feature branch with open Pull Requests-skip_branch_with_pr: true--platform:-  - x86_64--cache:-  - "C:\\SR"-  - dist-newstyle--environment:-  global:-    CABOPTS: --store-dir=C:\\SR--  matrix:-    - GHCVER: 8.8.1--install:-  - choco source add -n mistuke -s https://www.myget.org/F/mistuke/api/v2-  - choco install -y cabal --version 2.4.1.0-  - choco install -y ghc   --version 8.8.1-  - refreshenv--before_build:-  - cabal --version-  - ghc   --version-  - cabal %CABOPTS% v2-update--build_script:-  - cabal %CABOPTS% v2-build --enable-tests-  - cabal %CABOPTS% v2-test  --enable-tests
− test/golden/fullProject/benchmark/Main.hs
@@ -1,7 +0,0 @@-module Main (main) where--import Gauge.Main---main :: IO ()-main = defaultMain [bench "const" (whnf const ())]
− test/golden/fullProject/fullProject.cabal
@@ -1,105 +0,0 @@-cabal-version:       2.0-name:                fullProject-version:             0.0.0.0-synopsis:            Full test project-description:         Full test project-homepage:            https://github.com/kowainik/fullProject-bug-reports:         https://github.com/kowainik/fullProject/issues-license:             MIT-license-file:        LICENSE-author:              Kowainik-maintainer:          xrom.xkov@gmail.com-copyright:           2018 Kowainik-category:            Testing-build-type:          Simple-extra-doc-files:     README.md-                   , CHANGELOG.md-tested-with:         GHC == 8.0.2-                   , GHC == 8.2.2-                   , GHC == 8.4.4-                   , GHC == 8.6.5-                   , GHC == 8.8.1--source-repository head-  type:                git-  location:            https://github.com/kowainik/fullProject.git--library-  hs-source-dirs:      src-  exposed-modules:     FullProject-                       Prelude--  build-depends:       base-noprelude >= 4.9.1.0 && < 4.14-                     , relude--  ghc-options:         -Wall-                       -Wcompat-                       -Widentities--  default-language:    Haskell2010-  default-extensions:  ConstraintKinds-                       LambdaCase-                       OverloadedStrings--executable fullProject-  hs-source-dirs:      app-  main-is:             Main.hs--  build-depends:       base-noprelude >= 4.9.1.0 && < 4.14-                     , fullProject-                     , relude--  ghc-options:         -Wall-                       -threaded-                       -rtsopts-                       -with-rtsopts=-N-                       -Wcompat-                       -Widentities--  default-language:    Haskell2010-  default-extensions:  ConstraintKinds-                       LambdaCase-                       OverloadedStrings--test-suite fullProject-test-  type:                exitcode-stdio-1.0-  hs-source-dirs:      test-  main-is:             Spec.hs--  build-depends:       base-noprelude >= 4.9.1.0 && < 4.14-                     , fullProject-                     , relude--  ghc-options:         -Wall-                       -threaded-                       -rtsopts-                       -with-rtsopts=-N-                       -Wcompat-                       -Widentities--  default-language:    Haskell2010-  default-extensions:  ConstraintKinds-                       LambdaCase-                       OverloadedStrings--benchmark fullProject-benchmark-  type:                exitcode-stdio-1.0-  hs-source-dirs:      benchmark-  main-is:             Main.hs--  build-depends:       base-noprelude >= 4.9.1.0 && < 4.14-                     , gauge-                     , fullProject-                     , relude--  ghc-options:         -Wall-                       -threaded-                       -rtsopts-                       -with-rtsopts=-N-                       -Wcompat-                       -Widentities--  default-language:    Haskell2010-  default-extensions:  ConstraintKinds-                       LambdaCase-                       OverloadedStrings
− test/golden/fullProject/src/FullProject.hs
@@ -1,6 +0,0 @@-module FullProject-       ( someFunc-       ) where--someFunc :: IO ()-someFunc = putStrLn ("someFunc" :: String)
− test/golden/fullProject/src/Prelude.hs
@@ -1,7 +0,0 @@--- | Uses [relude](https://hackage.haskell.org/package/relude) as default Prelude.--module Prelude-       ( module Relude-       ) where--import Relude
− test/golden/fullProject/stack-8.0.2.yaml
@@ -1,3 +0,0 @@-resolver: lts-9.21--extra-deps: [base-noprelude-4.9.1.0]
− test/golden/fullProject/stack-8.2.2.yaml
@@ -1,3 +0,0 @@-resolver: lts-11.22--extra-deps: [base-noprelude-4.10.1.0]
− test/golden/fullProject/stack-8.4.4.yaml
@@ -1,3 +0,0 @@-resolver: lts-12.26--extra-deps: [base-noprelude-4.11.1.0]
− test/golden/fullProject/stack-8.6.5.yaml
@@ -1,3 +0,0 @@-resolver: lts-14.18--extra-deps: [base-noprelude-4.12.0.0]
− test/golden/fullProject/stack.yaml
@@ -1,3 +0,0 @@-resolver: nightly-2019-12-25--extra-deps: [base-noprelude-4.13.0.0]
− test/golden/fullProject/test/Spec.hs
@@ -1,4 +0,0 @@-module Main (main) where--main :: IO ()-main = putStrLn ("Test suite not yet implemented" :: String)
− test/golden/smallProject/CHANGELOG.md
@@ -1,9 +0,0 @@-# Changelog--`smallProject` uses [PVP Versioning][1].--## 0.0.0.0--* Initially created.--[1]: https://pvp.haskell.org
− test/golden/smallProject/README.md
@@ -1,5 +0,0 @@-# smallProject--[![Hackage](https://img.shields.io/hackage/v/smallProject.svg?logo=haskell)](https://hackage.haskell.org/package/smallProject)--Small test project
− test/golden/smallProject/app/Main.hs
@@ -1,4 +0,0 @@-module Main (main) where--main :: IO ()-main = putStrLn ("Hello, world!" :: String)
− test/golden/smallProject/smallProject.cabal
@@ -1,37 +0,0 @@-cabal-version:       2.0-name:                smallProject-version:             0.0.0.0-synopsis:            Small test project-description:         Small test project-license:             AllRightsReserved-author:              Kowainik-maintainer:          xrom.xkov@gmail.com-copyright:           2018 Kowainik-build-type:          Simple-extra-doc-files:     README.md-                   , CHANGELOG.md-tested-with:         GHC == 8.8.1--executable smallProject-  hs-source-dirs:      app-  main-is:             Main.hs--  build-depends:       base ^>= 4.13.0.0-                     -                     --  ghc-options:         -Wall-                       -threaded-                       -rtsopts-                       -with-rtsopts=-N-                       -Wincomplete-uni-patterns-                       -Wincomplete-record-updates-                       -Wcompat-                       -Widentities-                       -Wredundant-constraints-                       -fhide-source-paths-                       -Wmissing-export-lists-                       -Wpartial-fields-                       -Wmissing-deriving-strategies--  default-language:    Haskell2010