summoner-tui 1.4.0.0 → 2.0.0.0
raw patch · 8 files changed
+346/−159 lines, 8 filesdep +validation-selectivedep ~basedep ~brickdep ~summonerPVP ok
version bump matches the API change (PVP)
Dependencies added: validation-selective
Dependency ranges changed: base, brick, summoner, vty
API changes (from Hackage documentation)
- Summoner.Tui.Kit: [summonKitContributing] :: SummonKit -> !Maybe Source
- Summoner.Tui.Kit: [summonKitOffline] :: SummonKit -> !Bool
- Summoner.Tui.Kit: [summonKitStylish] :: SummonKit -> !Maybe Source
- Summoner.Tui.Kit: contributing :: HasContributing s a => Lens' s a
- Summoner.Tui.Kit: instance Summoner.Tui.Kit.HasContributing Summoner.Tui.Kit.SummonKit (GHC.Maybe.Maybe Summoner.Source.Source)
- Summoner.Tui.Kit: instance Summoner.Tui.Kit.HasOffline Summoner.Tui.Kit.SummonKit GHC.Types.Bool
- Summoner.Tui.Kit: instance Summoner.Tui.Kit.HasStylish Summoner.Tui.Kit.SummonKit (GHC.Maybe.Maybe Summoner.Source.Source)
- Summoner.Tui.Kit: offline :: HasOffline s a => Lens' s a
- Summoner.Tui.Kit: stylish :: HasStylish s a => Lens' s a
+ Summoner.Tui.Form: GitHubActions :: SummonForm
+ Summoner.Tui.Kit: [gitHubActions] :: GitHub -> !Bool
+ Summoner.Tui.Kit: [summonKitConnectMode] :: SummonKit -> !ConnectMode
+ Summoner.Tui.Kit: actions :: HasActions s a => Lens' s a
+ Summoner.Tui.Kit: connectMode :: HasConnectMode s a => Lens' s a
+ Summoner.Tui.Kit: instance Summoner.Tui.Kit.HasActions Summoner.Tui.Kit.GitHub GHC.Types.Bool
+ Summoner.Tui.Kit: instance Summoner.Tui.Kit.HasConnectMode Summoner.Tui.Kit.SummonKit Summoner.Mode.ConnectMode
- Summoner.Tui.Kit: GitHub :: !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> GitHub
+ Summoner.Tui.Kit: GitHub :: !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> GitHub
- Summoner.Tui.Kit: SummonKit :: !User -> !Project -> !Bool -> !Bool -> !ProjectMeta -> !GitHub -> ![Text] -> ![Text] -> ![Text] -> !Maybe Source -> !Maybe Source -> !Bool -> !Decision -> !Maybe FilePath -> ![TreeFs] -> SummonKit
+ Summoner.Tui.Kit: SummonKit :: !User -> !Project -> !Bool -> !Bool -> !ProjectMeta -> !GitHub -> ![Text] -> ![Text] -> ![Text] -> !ConnectMode -> !Decision -> !Maybe FilePath -> ![TreeFs] -> SummonKit
- Summoner.Tui.Kit: configToSummonKit :: Text -> Bool -> Maybe FilePath -> [TreeFs] -> Config -> SummonKit
+ Summoner.Tui.Kit: configToSummonKit :: Text -> ConnectMode -> Maybe FilePath -> [TreeFs] -> Config -> SummonKit
Files
- CHANGELOG.md +119/−0
- README.md +155/−63
- app/Tui.hs +1/−1
- src/Summoner/Tui.hs +19/−20
- src/Summoner/Tui/Form.hs +3/−0
- src/Summoner/Tui/Kit.hs +28/−57
- src/Summoner/Tui/Validation.hs +1/−1
- summoner-tui.cabal +20/−17
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 +[](https://github.com/kowainik/summoner/actions) [](http://travis-ci.org/kowainik/summoner) [](https://ci.appveyor.com/project/kowainik/summoner) [](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) -[](https://asciinema.org/a/214424)+[](https://asciinema.org/a/314375) ### CLI demo [↑](#structure) -[](https://asciinema.org/a/214433)+[](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/Tui.hs view
@@ -1,4 +1,4 @@-module Main where+module Main (main) where import System.IO (hSetEncoding, utf8)
src/Summoner/Tui.hs view
@@ -32,14 +32,16 @@ import System.Directory (doesDirectoryExist, doesFileExist, getCurrentDirectory, listDirectory) import Summoner.Ansi (errorMessage, infoMessage)-import Summoner.CLI (Command (..), NewOpts (..), ShowOpts (..), getFinalConfig, runScript, summon)+import Summoner.CLI (Command (..), NewOpts (..), ShowOpts (..), getCustomLicenseText,+ getFinalConfig, runConfig, runScript, summon) import Summoner.Config (ConfigP (cFiles)) import Summoner.Decision (Decision (..)) import Summoner.Default (defaultConfigFile) import Summoner.GhcVer (ghcTable)-import Summoner.License (License (..), LicenseName, fetchLicense, parseLicenseName,- showLicenseWithDesc)-import Summoner.Project (fetchSources, initializeProject)+import Summoner.License (License (..), LicenseName, parseLicenseName, showLicenseWithDesc)+import Summoner.Mode (isNonInteractive)+import Summoner.Project (generateProjectNonInteractive, initializeProject)+import Summoner.Source (fetchSources) import Summoner.Tui.Field (disabledAttr) import Summoner.Tui.Form (KitForm, SummonForm (..), getCurrentFocus, isActive, mkForm, recreateForm) import Summoner.Tui.Kit@@ -60,8 +62,9 @@ runTuiCommand :: Command -> IO () runTuiCommand = \case New opts -> summonTuiNew opts- Script opts -> runScript opts -- TODO: implement TUI for script command ShowInfo opts -> summonTuiShow opts+ Script opts -> runScript opts -- TODO: implement TUI for script command+ Config opts -> runConfig opts ---------------------------------------------------------------------------- -- New command@@ -74,11 +77,17 @@ summonTuiNew newOpts@NewOpts{..} = do -- configure initial state for TUI application finalConfig <- getFinalConfig newOpts- files <- fetchSources newOptsOffline (cFiles finalConfig)+ when (isNonInteractive newOptsInteractivity) $ do+ generateProjectNonInteractive+ newOptsConnectMode+ newOptsProjectName+ finalConfig+ () <$ exitSuccess+ files <- fetchSources newOptsConnectMode (cFiles finalConfig) configFilePath <- findConfigFile let initialKit = configToSummonKit newOptsProjectName- newOptsOffline+ newOptsConnectMode configFilePath files finalConfig@@ -171,6 +180,7 @@ -> SummonForm -> EventM SummonForm (Next (KitForm e)) handleCheckboxActivation ev form = \case+ CabalField -> withForm ev form mkNewForm StackField -> withForm ev form mkNewForm GitHubEnable -> withForm ev form mkNewForm GitHubDisable -> withForm ev form mkNewForm@@ -221,7 +231,7 @@ form = borderLabel "Summon new project" (renderForm kitForm) tree :: Widget SummonForm- tree = hLimitPercent 25 $ vLimit 21 $ borderLabel "Project Structure" $ vBox+ tree = hLimitPercent 25 $ vLimit 22 $ borderLabel "Project Structure" $ vBox [ withAttr "tree" $ txt $ renderWidgetTree kit -- to fill all the space that widget should take. , fill ' '@@ -233,7 +243,6 @@ [ informationBlock , validationBlock , configBlock- , deprecationBlock , fill ' ' ] where@@ -247,9 +256,6 @@ infoTxt :: Text -> Widget SummonForm infoTxt = withAttr "blue-fg" . txtWrap . (<>) " ⓘ " - deprecationTxt :: Text -> Widget SummonForm- deprecationTxt = withAttr "yellow-fg" . txtWrap . (<>) " ⚠ "- validationBlock :: Widget SummonForm validationBlock = vBox $ case formErrorMessages dirs kitForm of [] -> [withAttr "green-fg" $ str " ✔ Project configuration is valid"]@@ -260,13 +266,6 @@ Nothing -> emptyWidget Just file -> infoTxt $ toText file <> " file is used" - deprecationBlock :: Widget SummonForm- deprecationBlock = case (kit ^. stylish, kit ^. contributing) of- (Nothing, Nothing) -> emptyWidget- (s, c) -> vBox $- [ deprecationTxt "Option 'stylish' is deprecated, use 'files'" | isJust s ]- ++ [ deprecationTxt "Option 'contributing' is deprecated, use 'files'" | isJust c]- help, helpBody :: Widget SummonForm help = borderLabel "Help" (helpBody <+> fill ' ') helpBody = vBox@@ -306,7 +305,7 @@ errorMessage $ "Error parsing license name: " <> name infoMessage "Use 'summon show license' command to see the list of all available licenses" Just licenseName -> do- lc <- fetchLicense licenseName+ lc <- getCustomLicenseText licenseName runApp (licenseApp licenseName lc) () where licenseApp :: LicenseName -> License -> App () e ()
src/Summoner/Tui/Form.hs view
@@ -66,6 +66,7 @@ | GitHubDisable | GitHubNoUpload | GitHubPrivate+ | GitHubActions | GitHubTravis | GitHubAppVeyor deriving stock (Show, Eq, Ord, Enum, Bounded)@@ -121,6 +122,7 @@ ] , 1 |> activeCheckboxField (gitHub . noUpload) isActive GitHubNoUpload "No upload" , 1 |> activeCheckboxField (gitHub . private) isActive GitHubPrivate "Private"+ , 1 |> activeCheckboxField (gitHub . actions) isActive GitHubActions "GitHub Actions" , 1 |> activeCheckboxField (gitHub . travis) isActive GitHubTravis "Travis" , 2 |> activeCheckboxField (gitHub . appVeyor) isActive GitHubAppVeyor "AppVeyor" ]@@ -142,6 +144,7 @@ isActive kit = \case GitHubNoUpload -> isGitHubEnabled GitHubPrivate -> isGitHubEnabled && isUploadEnabled+ GitHubActions -> isGitHubEnabled && (kit ^. cabal) GitHubTravis -> isGitHubEnabled GitHubAppVeyor -> isGitHubEnabled _ -> True
src/Summoner/Tui/Kit.hs view
@@ -33,9 +33,7 @@ , gitHub , extensions , ghcOptions- , stylish- , contributing- , offline+ , connectMode , shouldSummon , configFile @@ -64,6 +62,7 @@ , enabled , noUpload , private+ , actions , travis , appVeyor ) where@@ -73,12 +72,12 @@ import Summoner.Config (Config, ConfigP (..)) import Summoner.CustomPrelude (CustomPrelude (..))-import Summoner.Decision (Decision (..))+import Summoner.Decision (Decision (..), decisionToBool, decisionsToBools) import Summoner.Default (currentYear, defaultDescription, defaultGHC) import Summoner.GhcVer (GhcVer)-import Summoner.License (LicenseName (..), customizeLicense, fetchLicense)+import Summoner.License (LicenseName (..), fetchLicenseCustom)+import Summoner.Mode (ConnectMode (..), isOffline) import Summoner.Settings (Settings (..))-import Summoner.Source (Source, fetchSource) import Summoner.Template (createProjectTemplate) import Summoner.Tree (TreeFs, showTree) @@ -97,9 +96,7 @@ , summonKitExtensions :: ![Text] -- ^ Can be recieved from the config file. , summonKitGhcOptions :: ![Text] -- ^ Can be recieved from the config file. , summonKitGitignore :: ![Text] -- ^ Received from the config file.- , summonKitStylish :: !(Maybe Source) -- ^ Can be recieved from the config file.- , summonKitContributing :: !(Maybe Source) -- ^ Can be recieved from the config file.- , summonKitOffline :: !Bool+ , summonKitConnectMode :: !ConnectMode , summonKitShouldSummon :: !Decision -- ^ Check if project needs to be created. , summonKitConfigFile :: !(Maybe FilePath) -- ^ Just if configuration file was used. , summonKitExtraFiles :: ![TreeFs] -- ^ Extra files@@ -136,6 +133,7 @@ { gitHubEnabled :: !Bool , gitHubNoUpload :: !Bool -- ^ Do not upload to GitHub, only local initialization. , gitHubPrivate :: !Bool+ , gitHubActions :: !Bool , gitHubTravis :: !Bool , gitHubAppVeyor :: !Bool } deriving stock (Show)@@ -171,23 +169,21 @@ , settingsLicenseName = sk ^. project . license , settingsLicenseText = "" , settingsGitHub = isGitHub+ , settingsGhActions = isGitHub && sk ^. gitHub . actions && sk ^. cabal , settingsPrivate = isGitHub && sk ^. gitHub . private , settingsTravis = isGitHub && sk ^. gitHub . travis- , settingsAppVeyor = isGitHub && sk ^. gitHub . appVeyor && sk ^. stack+ , settingsAppVeyor = isGitHub && sk ^. gitHub . appVeyor , settingsIsLib = sk ^. projectMeta . lib , settingsIsExe = sk ^. projectMeta . exe , settingsTest = sk ^. projectMeta . test , settingsBench = sk ^. projectMeta . bench , settingsTestedVersions = sortNub $ defaultGHC : (sk ^. projectMeta . ghcs)- , settingsBaseType = baseT , settingsPrelude = cP , settingsExtensions = sk ^. extensions , settingsGhcOptions = sk ^. ghcOptions , settingsGitignore = sk ^. gitignore , settingsCabal = sk ^. cabal , settingsStack = sk ^. stack- , settingsStylish = "" <$ sk ^. stylish- , settingsContributing = "" <$ sk ^. contributing , settingsNoUpload = sk ^. gitHub . noUpload , settingsFiles = sk ^. extraFiles }@@ -195,47 +191,38 @@ isGitHub :: Bool isGitHub = sk ^. gitHub . enabled - baseT :: Text cP :: Maybe CustomPrelude- (baseT, cP) =+ cP = let cpPackage = T.strip $ sk ^. projectMeta . preludeName cpModule = T.strip $ sk ^. projectMeta . preludeModule in if ("" /= cpPackage) && ("" /= cpModule)- then ("base-noprelude", Just CustomPrelude{..})- else ("base", Nothing)+ then Just CustomPrelude{..}+ else Nothing -- | Gets 'Settings' on successful application complition. finalSettings :: SummonKit -> IO Settings finalSettings sk = do year <- currentYear let licenseName = sk ^. project . license- fetchedLicense <- fetchLicense licenseName- let licenseText = customizeLicense- licenseName- fetchedLicense- (sk ^. user . fullName)- year-- let fetch = maybe (pure Nothing) (fetchSource (sk ^. offline))- sStylish <- fetch $ sk ^. stylish- sContributing <- fetch $ sk ^. contributing+ licenseText <- fetchLicenseCustom+ licenseName+ (sk ^. user . fullName)+ year pure (summonKitToSettings sk) { settingsYear = year , settingsLicenseText = licenseText- , settingsStylish = sStylish- , settingsContributing = sContributing } -- | Gets the initial 'SummonKit' from the given 'Config'. configToSummonKit :: Text -- ^ Given project name- -> Bool -- ^ @offline@ mode option+ -> ConnectMode -- ^ @offline@ mode option -> Maybe FilePath -- ^ Configuration file used -> [TreeFs] -- ^ Extra files -> Config -- ^ Given configurations. -> SummonKit-configToSummonKit cRepo cOffline cConfigFile files Config{..} = SummonKit+configToSummonKit cRepo cConnectMode cConfigFile files ConfigP{..} = SummonKit { summonKitUser = User { userOwner = cOwner , userFullName = cFullName@@ -245,13 +232,13 @@ { projectRepo = cRepo , projectDesc = defaultDescription , projectCategory = ""- , projectLicense = if cOffline then None else cLicense+ , projectLicense = if isOffline cConnectMode then NONE else cLicense } , summonKitProjectMeta = ProjectMeta { projectMetaLib = kitLib , projectMetaExe = kitExe- , projectMetaTest = toBool cTest- , projectMetaBench = toBool cBench+ , projectMetaTest = decisionToBool cTest+ , projectMetaBench = decisionToBool cBench , projectMetaGhcs = List.delete defaultGHC cGhcVer , projectMetaPreludeName = kitPreludeName , projectMetaPreludeModule = kitPreludeModule@@ -260,40 +247,24 @@ , summonKitStack = kitStack , summonKitGitHub = GitHub { gitHubEnabled = cGitHub /= Nop- , gitHubNoUpload = getAny cNoUpload || cOffline- , gitHubPrivate = toBool cPrivate+ , gitHubNoUpload = getAny cNoUpload || isOffline cConnectMode+ , gitHubPrivate = decisionToBool cPrivate+ , gitHubActions = (cGitHub /= Nop) && (cGhActions /= Nop) && kitCabal , gitHubTravis = (cGitHub /= Nop) && (cTravis /= Nop)- , gitHubAppVeyor = toBool cAppVey && kitStack+ , gitHubAppVeyor = decisionToBool cAppVey } , summonKitExtensions = cExtensions , summonKitGhcOptions = cGhcOptions , summonKitGitignore = cGitignore- , summonKitStylish = getLast cStylish- , summonKitContributing = getLast cContributing- , summonKitOffline = cOffline+ , summonKitConnectMode = cConnectMode , summonKitShouldSummon = Nop , summonKitConfigFile = cConfigFile , summonKitExtraFiles = files } where kitCabal, kitStack, kitLib, kitExe :: Bool- (kitCabal, kitStack) = decToBools (cCabal, cStack)- (kitLib, kitExe) = decToBools (cLib, cExe)-- decToBools :: (Decision, Decision) -> (Bool, Bool)- decToBools = \case- (Idk, Idk) -> (True, True)- (Yes, Idk) -> (True, False)- (Idk, Yes) -> (False, True)- (Nop, Idk) -> (False, True)- (Idk, Nop) -> (True, False)- (x, y) -> (toBool x, toBool y)-- toBool :: Decision -> Bool- toBool = \case- Yes -> True- Nop -> False- Idk -> False+ (kitCabal, kitStack) = decisionsToBools (cCabal, cStack)+ (kitLib, kitExe) = decisionsToBools (cLib, cExe) kitPreludeName, kitPreludeModule :: Text (kitPreludeName, kitPreludeModule) = case getLast cPrelude of
src/Summoner/Tui/Validation.hs view
@@ -19,7 +19,7 @@ import Brick.Forms (formState, invalidFields, setFieldValid, setFormFocus) import Lens.Micro (Lens', (%~), (.~), (^.)) import Relude.Extra.Enum (universe)-import Relude.Extra.Validation (Validation (..))+import Validation (Validation (..)) import Summoner.Text (moduleNameValid, packageNameValid, packageToModule) import Summoner.Tui.Form (KitForm, SummonForm (..), getCurrentFocus, mkForm)
summoner-tui.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: summoner-tui-version: 1.4.0.0+version: 2.0.0.0 synopsis: Tool for scaffolding fully configured batteries-included production-level Haskell projects using TUI. description: Tool for scaffolding fully configured batteries-included production-level Haskell projects using TUI. See [README.md](https://github.com/kowainik/summoner#-summoner) for details.@@ -15,34 +15,36 @@ build-type: Simple stability: experimental 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 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 )- 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 @@ -74,14 +76,15 @@ autogen-modules: Paths_summoner_tui other-modules: Paths_summoner_tui - build-depends: brick >= 0.47 && < 0.51+ build-depends: brick >= 0.47 && < 0.53 , directory ^>= 1.3.0.2 , filepath ^>= 1.4.1.2 , microlens ^>= 0.4 , microlens-th ^>= 0.4- , summoner ^>= 1.4.0+ , summoner ^>= 2.0.0.0 , text ^>= 1.2.3.0- , vty >= 5.25 && < 5.27+ , validation-selective ^>= 0.0.0.0+ , vty >= 5.25 && < 5.29 executable summon-tui import: common-options