packages feed

summoner 2.0.1.1 → 2.1.0.0

raw patch · 85 files changed

+2095/−1332 lines, 85 filesdep +microaesondep −aesondep −containersdep −neat-interpolationdep ~basedep ~colouristadep ~filepathnew-component:exe:ggPVP ok

version bump matches the API change (PVP)

Dependencies added: microaeson

Dependencies removed: aeson, containers, neat-interpolation, text

Dependency ranges changed: base, colourista, filepath, generic-data, hedgehog, hspec-hedgehog, optparse-applicative, relude, shellmet, time, tree-diff, validation-selective

API changes (from Hackage documentation)

- Summoner.GhcVer: Ghc7103 :: GhcVer
- Summoner.GhcVer: Ghc883 :: GhcVer
- Summoner.License: instance Data.Aeson.Types.FromJSON.FromJSON Summoner.License.License
- Summoner.Text: endLine :: Text
- Summoner.Text: tconcatMap :: (a -> Text) -> [a] -> Text
+ Summoner.Default: defaultCabalVersion :: Text
+ Summoner.Default: defaultStack :: Text
+ Summoner.Default: ghcActionsCacheVersion :: Text
+ Summoner.Default: ghcActionsCheckoutVersion :: Text
+ Summoner.Default: ghcActionsSetupHaskellVersion :: Text
+ Summoner.GhcVer: Ghc8107 :: GhcVer
+ Summoner.GhcVer: Ghc884 :: GhcVer
+ Summoner.GhcVer: Ghc902 :: GhcVer
+ Summoner.GhcVer: Ghc9103 :: GhcVer
+ Summoner.GhcVer: Ghc9123 :: GhcVer
+ Summoner.GhcVer: Ghc928 :: GhcVer
+ Summoner.GhcVer: Ghc948 :: GhcVer
+ Summoner.GhcVer: Ghc967 :: GhcVer
+ Summoner.GhcVer: Ghc984 :: GhcVer
+ Summoner.Golden: cabalFull :: Settings
+ Summoner.Golden: cabalMinimal :: Settings
+ Summoner.Golden: fullBatteries :: Settings
+ Summoner.Golden: generateProjects :: IO ()
+ Summoner.Golden: generateScripts :: IO ()
+ Summoner.Golden: generateTomlConfig :: IO ()
+ Summoner.Golden: stackFull :: Settings
+ Summoner.License: instance Data.Aeson.Micro.FromJSON Summoner.License.License
+ Summoner.Text: quote :: Text -> Text
- Summoner.CLI: Config :: ConfigOpts -> Command
+ Summoner.CLI: Config :: !ConfigOpts -> Command
- Summoner.CLI: LicenseList :: Maybe String -> ShowOpts
+ Summoner.CLI: LicenseList :: !Maybe String -> ShowOpts
- Summoner.CLI: New :: NewOpts -> Command
+ Summoner.CLI: New :: !NewOpts -> Command
- Summoner.CLI: Script :: ScriptOpts -> Command
+ Summoner.CLI: Script :: !ScriptOpts -> Command
- Summoner.CLI: ShowInfo :: ShowOpts -> Command
+ Summoner.CLI: ShowInfo :: !ShowOpts -> Command
- Summoner.GhcVer: Pvp :: Int -> Int -> Int -> Int -> Pvp
+ Summoner.GhcVer: Pvp :: !Int -> !Int -> !Int -> !Int -> Pvp
- Summoner.GhcVer: [pvpFirst] :: Pvp -> Int
+ Summoner.GhcVer: [pvpFirst] :: Pvp -> !Int
- Summoner.GhcVer: [pvpFourth] :: Pvp -> Int
+ Summoner.GhcVer: [pvpFourth] :: Pvp -> !Int
- Summoner.GhcVer: [pvpSecond] :: Pvp -> Int
+ Summoner.GhcVer: [pvpSecond] :: Pvp -> !Int
- Summoner.GhcVer: [pvpThird] :: Pvp -> Int
+ Summoner.GhcVer: [pvpThird] :: Pvp -> !Int
- Summoner.Question: queryManyRepeatOnFail :: forall a. (Text -> Maybe a) -> IO [a]
+ Summoner.Question: queryManyRepeatOnFail :: (Text -> Maybe a) -> IO [a]
- Summoner.Tree: Dir :: FilePath -> [TreeFs] -> TreeFs
+ Summoner.Tree: Dir :: !FilePath -> ![TreeFs] -> TreeFs
- Summoner.Tree: File :: FilePath -> Text -> TreeFs
+ Summoner.Tree: File :: !FilePath -> !Text -> TreeFs

Files

CHANGELOG.md view
@@ -3,6 +3,76 @@ `summoner` uses [PVP Versioning][1]. The changelog is available [on GitHub][2]. +## 2.1.0.0 — Jan 6, 2026++* Support GHC-9.12.3. Use GHC-9.12.3 as the default version for+  generated projects with `nightly-2026-01-04` Stack resolver.+* Support GHC-9.10.3 in generated projects with `lts-24.26`.+* Update GHC-9.8 to GHC-9.8.4 with `lts-23.28`.+* Update GHC-9.6 to GHC-9.6.7 with `lts-22.44`.+* Update `base` upper bound to `< 4.22`.+* Update GitHub Actions in generated projects: replace deprecated+  `haskell/actions/setup` with `haskell-actions/setup`.+* Update `optparse-applicative`, `shellmet`, `time`, `hedgehog`, `brick` upper bounds.+* Add new GHC warnings for GHC >= 9.10:+  `-Wincomplete-record-selectors`, `-Wdeprecated-type-abstractions`,+  `-Wdata-kinds-tc`, `-Wdefaulted-exception-context`.+* Add new GHC warning for GHC >= 9.12: `-Wview-pattern-signatures`.+* Fix encoding issues when reading source files by using `readFileBS`+  with `decodeUtf8` instead of `readFileText`.+* Update Stack resolver to `lts-24.26`. Update Stack version in CI to 3.3.++* [#564](https://github.com/kowainik/summoner/issues/564):+  Upgrade `brick` to version `>=1.0`.+* [#565](https://github.com/kowainik/summoner/issues/565):+  Build Summoner with GHC-9.2.+* [#539](https://github.com/kowainik/summoner/issues/539):+  Use GHC-9.0 as default version for generated projects.+* [#540](https://github.com/kowainik/summoner/issues/540):+  Build Summoner with GHC-9.0.+* [#520](https://github.com/kowainik/summoner/issues/520):+  Output the link to the GitHub project at the end of the process.+* [#476](https://github.com/kowainik/summoner/issues/476):+  Switch from `aeson` to `microaeson`.+* [#466](https://github.com/kowainik/summoner/issues/466):+  Add ` --test-show-details=direct` to `cabal test` on CI.+* [#444](https://github.com/kowainik/summoner/issues/444)+  [#547](https://github.com/kowainik/summoner/issues/547):+  Support GHC-8.10.1 in the generated projects.+  Use GHC-8.10.1 by default in the generated projects.+  Use `nightly-2020-06-29` for stack resolver.+  UPD: Use GHC-8.10.3 and `lts-17.0` instead.+  UPD: Use GHC-8.10.7 and `lts-18.10` instead.+* [#445](https://github.com/kowainik/summoner/issues/445):+  Add `-Wunused-packages` for GHC-8.10.+* [#477](https://github.com/kowainik/summoner/issues/477):+  Remove `neat-interpolation` from dependencies.+  As a result, remove some trailing spaces from the generated files.+* [#442](https://github.com/kowainik/summoner/issues/442):+  Get current year with the respect to the current timezone.+* [#446](https://github.com/kowainik/summoner/issues/446):+  Add README link in the `.cabal` file's description field.+* [#453](https://github.com/kowainik/summoner/issues/453):+  Drop support of `GHC-7.10` in the generated projects.+* [#482](https://github.com/kowainik/summoner/issues/482):+  Include `.hie` related GHC options to the generated files:+  `-fwrite-ide-info` and `-hiedir=.hie` for GHC >= 8.8.+  Also add `.hie` folder in the `.gitignore`.+* [#484](https://github.com/kowainik/summoner/issues/484):+  Improve generated files content.+* [#491](https://github.com/kowainik/summoner/issues/491):+  Support GHC-8.8.4 in the project.+* [#517](https://github.com/kowainik/summoner/issues/517):+  Switch to `main` initial branch when creating project.+* Require `git >= 2.28` for `--initial-branch=main` option.+* [#340](https://github.com/kowainik/summoner/issues/340):+  Use `cabal` version `3.0`.+* [#495](https://github.com/kowainik/summoner/issues/495):+  Generate `dependabot.yml` to update GitHub Actions automatically.+* __#TUI__ Upgrade `brick` allowed version. Bump up lower+  bound to `0.56` due to the new field `formFieldUpdate`+  addition to the `FormFieldState` data type.+ ## 2.0.1.1 — May 29, 2020  * [#467](https://github.com/kowainik/summoner/issues/467):
README.md view
@@ -1,11 +1,13 @@ # 🔮 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)-[![MPL-2.0 license](https://img.shields.io/badge/license-MPL--2.0-blue.svg)](https://github.com/kowainik/summoner/blob/master/LICENSE)+[![Stackage Lts](http://stackage.org/package/summoner/badge/lts)](http://stackage.org/lts/package/summoner)+[![Stackage Nightly](http://stackage.org/package/summoner/badge/nightly)](http://stackage.org/nightly/package/summoner)+[![MPL-2.0 license](https://img.shields.io/badge/license-MPL--2.0-blue.svg)](https://github.com/kowainik/summoner/blob/main/LICENSE)  > _So many of our dreams at first seem impossible, then they seem improbable, and > then, when we summon the will, they soon become inevitable._@@ -35,13 +37,13 @@           + [TUI: download binary](#tui-download-binary)           + [TUI: Homebrew](#tui-homebrew)           + [TUI: Ubuntu](#tui-ubuntu)-          + [TUI: from Hackage/Stackage](#tui-from-hackagestackage)+          + [TUI: from Hackage](#tui-from-hackage)           + [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 Hackage](#cli-from-hackage)           + [CLI: from source](#cli-from-source)     + [Setup](#setup) * [Usage](#usage)@@ -78,18 +80,18 @@  You can also see complete examples in the following folder: -* [`summon-cli/examples/`: Examples of scaffolded projects](https://github.com/kowainik/summoner/tree/master/summoner-cli/examples/)+* [`summon-cli/examples/`: Examples of scaffolded projects](https://github.com/kowainik/summoner/tree/main/summoner-cli/examples/)  The directory contains the following examples: -* [`cabal-minimal`](https://github.com/kowainik/summoner/tree/master/summoner-cli/examples/cabal-minimal):+* [`cabal-minimal`](https://github.com/kowainik/summoner/tree/main/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-full`](https://github.com/kowainik/summoner/tree/main/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-full`](https://github.com/kowainik/summoner/tree/main/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):+* [`full-batteries`](https://github.com/kowainik/summoner/tree/main/summoner-cli/examples/full-batteries):   All batteries-included project which supports both build tools and   shows every Summoner feature. @@ -130,11 +132,20 @@   -Widentities   -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)+  -Wredundant-constraints+  -Wnoncanonical-monad-instances+  -fhide-source-paths              (GHC ⩾ 8.2)+  -Wmissing-export-lists           (GHC ⩾ 8.4)+  -Wpartial-fields                 (GHC ⩾ 8.4)+  -Wmissing-deriving-strategies    (GHC ⩾ 8.8)+  -fwrite-ide-info                 (GHC ⩾ 8.8)+  -hiedir=.hie                     (GHC ⩾ 8.8)+  -Wunused-packages                (GHC ⩾ 8.10)+  -Wincomplete-record-selectors    (GHC ⩾ 9.10)+  -Wdeprecated-type-abstractions   (GHC ⩾ 9.10)+  -Wdata-kinds-tc                  (GHC ⩾ 9.10)+  -Wdefaulted-exception-context    (GHC ⩾ 9.10)+  -Wview-pattern-signatures        (GHC ⩾ 9.12)   ```    Besides, the following GHC options are added to the executable, tests and benchmark stanzas:@@ -223,13 +234,13 @@  To start using Summoner make sure that you have the following tools installed on your machine: -* [`git`](https://git-scm.com) – to initialize the GitHub repo.+* [`git`](https://git-scm.com) ⩾ 2.28 – to initialize the GitHub repo. * [`hub`](https://github.com/github/hub) – to upload the project to GitHub. * [`curl`](https://curl.haxx.se) – to download licenses.  We also have minimal version requirements for build tools: -* [Cabal ⩾ 2.4](https://www.haskell.org/cabal/)+* [Cabal ⩾ 3.0](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.@@ -290,21 +301,15 @@ $ sudo apt install summoner-tui ``` -##### TUI: from Hackage/Stackage+##### TUI: from Hackage  [[Back to the Table of Contents] ↑](#structure)  Using `cabal`:  ```shell-cabal v2-update-cabal v2-install summoner-tui-```--Using `stack`:--```shell-stack install summoner-tui+cabal update+cabal install summoner-tui ```  ##### TUI: from source@@ -332,7 +337,7 @@ Build and install using `cabal`:  ```shell-cabal v2-install summoner-tui:exe:summon-tui+cabal install summoner-tui:exe:summon-tui ```  Build and install using `stack`:@@ -384,21 +389,15 @@ $ sudo apt install summoner-cli ``` -##### CLI: from Hackage/Stackage+##### CLI: from Hackage  [[Back to the Table of Contents] ↑](#structure)  Using `cabal`:  ```shell-cabal v2-update-cabal v2-install summoner-```--Using `stack`:--```shell-stack install summoner+cabal update+cabal install summoner ```  ##### CLI: from source@@ -426,7 +425,7 @@ Build and install using `cabal`:  ```shell-cabal v2-install summoner-cli:exe:summon+cabal install summoner-cli:exe:summon ```  Build and install using `stack`:@@ -476,7 +475,7 @@ | `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.3`. 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-9.12.3`. However, additionally you can specify other versions. For each version `x.y.z` the `stack-x.y.z.yaml` will be created. Use `summon show ghc` to see all supported GHC versions. | | `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`)                                                              |@@ -498,7 +497,7 @@ 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).+For a real-life example of the configuration, see [the configuration for projects of the `Kowainik` organization](https://github.com/kowainik/org/blob/main/.summoner.toml).  ### Command line arguments @@ -631,7 +630,7 @@ 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.+to uncomment the corresponding lines. See [the default content here](summoner-cli/test/golden/summoner-default.toml).  Possible command usages:@@ -716,7 +715,7 @@ #!/usr/bin/env cabal {- cabal: build-depends:-  , base ^>= 4.13.0.0+  , base ^>= 4.21.1.0 -}  main :: IO ()@@ -728,7 +727,7 @@ ```haskell #!/usr/bin/env stack {- stack-  --resolver lts-15.5+  --resolver nightly-2026-01-04   script   --package base -}@@ -793,8 +792,8 @@  * Summoner is a multi-package project which has two packages inside: `summoner-cli` and `summoner-tui`. We are supporting the same functionality in both of them, so, if it's possible, you should add/change the code in both of the packages. * Summoner uses the custom prelude [`relude`](https://github.com/kowainik/relude).-* We are using the [Kowainik style guide](https://github.com/kowainik/org/blob/master/style-guide.md#haskell-style-guide).-* To sum up, [here is the Contributing guide](https://github.com/kowainik/.github/blob/master/CONTRIBUTING.md#contributing-to-the-kowainik-repositories) we use across the repositories.+* We are using the [Kowainik style guide](https://kowainik.github.io/posts/2019-02-06-style-guide).+* To sum up, [here is the Contributing guide](https://github.com/kowainik/.github/blob/main/CONTRIBUTING.md#contributing-to-the-kowainik-repositories) we use across the repositories. * This project is contributor-friendly, so be kind to other people working on the project.  ### Dependencies@@ -810,7 +809,7 @@ To build the project you can use the following commands:  ```shell=-cabal v2-build all+cabal build all ```  for Cabal and@@ -825,12 +824,12 @@  [[Back to the Table of Contents] ↑](#structure) -Summoner uses the golden tests technique for assuring the correctness of the generated files. For this purpose, we have [the `golden` folder](https://github.com/kowainik/summoner/tree/master/summoner-cli/test/golden) with two sample projects to test against.+Summoner uses the golden tests technique for assuring the correctness of the generated files. For this purpose, we have [the `golden` folder](https://github.com/kowainik/summoner/tree/main/summoner-cli/test/golden) with two sample projects to test against.  To actually run tests you need to run:  ```shell-cabal v2-test all+cabal test all ```  or, if using Stack@@ -846,8 +845,8 @@ 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 v2-exec summon -- SOME_COMMAND-cabal v2-exec summon-tui -- SOME_COMMAND+cabal exec summon -- SOME_COMMAND+cabal exec summon-tui -- SOME_COMMAND ```  or, if using Stack@@ -855,6 +854,14 @@ ```shell stack exec summon -- SOME_COMMAND stack exec summon-tui -- SOME_COMMAND+```++### Generate golden tests++To regenerate the content of all projects on disk, use the following command:++```shell+cabal run gg ```  ## Acknowledgments
examples/cabal-full/.github/workflows/ci.yml view
@@ -1,44 +1,113 @@ name: CI -# Trigger the workflow on push or pull request, but only for the master branch on:   pull_request:+    types: [synchronize, opened, reopened]   push:-    branches: [master]+    branches: [main]+  schedule:+    # additionally run once per week (At 00:00 on Sunday) to maintain cache+    - cron: '0 0 * * 0'  jobs:-  build:-    name: ghc ${{ matrix.ghc }}-    runs-on: ubuntu-16.04+  cabal:+    name: ${{ matrix.os }} / ghc ${{ matrix.ghc }}+    runs-on: ${{ matrix.os }}     strategy:       matrix:-        cabal: ["2.4"]+        os: [ubuntu-latest, macOS-latest, windows-latest]+        cabal: ["3.14.2.0"]         ghc:           - "8.4.4"           - "8.6.5"-          - "8.8.3"+          - "8.8.4"+          - "8.10.7"+          - "9.0.2"+          - "9.2.8"+          - "9.4.8"+          - "9.6.7"+          - "9.8.4"+          - "9.10.3"+          - "9.12.3"+        exclude:+          - os: macOS-latest+            ghc: 9.10.3+          - os: macOS-latest+            ghc: 9.8.4+          - os: macOS-latest+            ghc: 9.6.7+          - os: macOS-latest+            ghc: 9.4.8+          - os: macOS-latest+            ghc: 9.2.8+          - os: macOS-latest+            ghc: 9.0.2+          - os: macOS-latest+            ghc: 8.10.7+          - os: macOS-latest+            ghc: 8.8.4+          - os: macOS-latest+            ghc: 8.6.5+          - os: macOS-latest+            ghc: 8.4.4+          - os: windows-latest+            ghc: 9.10.3+          - os: windows-latest+            ghc: 9.8.4+          - os: windows-latest+            ghc: 9.6.7+          - os: windows-latest+            ghc: 9.4.8+          - os: windows-latest+            ghc: 9.2.8+          - os: windows-latest+            ghc: 9.0.2+          - os: windows-latest+            ghc: 8.10.7+          - os: windows-latest+            ghc: 8.8.4+          - os: windows-latest+            ghc: 8.6.5+          - os: windows-latest+            ghc: 8.4.4      steps:-    - uses: actions/checkout@v2-      if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/master'+    - uses: actions/checkout@v4 -    - uses: actions/setup-haskell@v1+    - uses: haskell-actions/setup@v2+      id: setup-haskell-cabal       name: Setup Haskell       with:         ghc-version: ${{ matrix.ghc }}         cabal-version: ${{ matrix.cabal }} -    - uses: actions/cache@v1+    - name: Configure+      run: |+        cabal configure --enable-tests --enable-benchmarks --enable-documentation --test-show-details=direct --write-ghc-environment-files=always++    - name: Freeze+      run: |+        cabal freeze++    - uses: actions/cache@v4       name: Cache ~/.cabal/store       with:-        path: ~/.cabal/store-        key: ${{ runner.os }}-${{ matrix.ghc }}-cabal+        path: ${{ steps.setup-haskell-cabal.outputs.cabal-store }}+        key: ${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('cabal.project.freeze') }} +    - name: Install dependencies+      run: |+        cabal build all --only-dependencies+     - name: Build       run: |-        cabal v2-update-        cabal v2-build --enable-tests --enable-benchmarks+        cabal build all      - name: Test       run: |-        cabal v2-test --enable-tests+        cabal test all++    - name: Documentation+      run: |+        cabal haddock+
examples/cabal-full/.gitignore view
@@ -21,6 +21,7 @@ cabal.project.local .ghc.environment.* .HTF/+.hie/ # Stack .stack-work/ stack.yaml.lock
examples/cabal-full/.travis.yml view
@@ -1,33 +1,38 @@-sudo: true language: haskell  git:   depth: 5 -cabal: "2.4"+cabal: "3.14.2.0"  cache:   directories:   - "$HOME/.cabal/store"-   -matrix:+jobs:   include:   - ghc: 8.4.4   - ghc: 8.6.5-  - ghc: 8.8.3-  -  +  - ghc: 8.8.4+  - ghc: 8.10.7+  - ghc: 9.0.2+  - ghc: 9.2.8+  - ghc: 9.4.8+  - ghc: 9.6.7+  - ghc: 9.8.4+  - ghc: 9.10.3+  - ghc: 9.12.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+  - cabal update+  - cabal configure --enable-tests --enable-benchmarks --enable-documentation --test-show-details=direct --write-ghc-environment-files=always+  - cabal build all  script:-  - cabal v2-test --enable-tests+  - cabal test all  notifications:   email: false
examples/cabal-full/LICENSE view
@@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2020, Kowainik+Copyright (c) 2022, Kowainik All rights reserved.  Redistribution and use in source and binary forms, with or without
examples/cabal-full/README.md view
@@ -1,8 +1,8 @@ # 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)+[![Build status](https://img.shields.io/travis/kowainik/cabal-full.svg?logo=travis)](https://travis-ci.com/kowainik/cabal-full)+[![Windows build status](https://ci.appveyor.com/api/projects/status/github/kowainik/cabal-full?branch=main&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) 
examples/cabal-full/app/Main.hs view
@@ -1,7 +1,7 @@ module Main (main) where -import CabalFull (someFunc)+import CabalFull (projectName)   main :: IO ()-main = someFunc+main = putStrLn ("Executable for " ++ projectName)
examples/cabal-full/appveyor.yml view
@@ -4,6 +4,11 @@ # Do not build feature branch with open Pull Requests skip_branch_with_pr: true +# build only main branch+branches:+  only:+    - main+ platform:   - x86_64 @@ -16,19 +21,20 @@     CABOPTS: --store-dir=C:\\SR    matrix:-    - GHCVER: 8.8.3+    - GHCVER: 9.12.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+  - choco install -y cabal --version 3.6.2.0+  - choco install -y ghc   --version 9.12.3   - refreshenv  before_build:   - cabal --version   - ghc   --version-  - cabal %CABOPTS% v2-update+  - cabal %CABOPTS% update  build_script:-  - cabal %CABOPTS% v2-build --enable-tests-  - cabal %CABOPTS% v2-test  --enable-tests+  - cabal %CABOPTS% configure --enable-tests --enable-benchmarks --enable-documentation --test-show-details=direct --write-ghc-environment-files=always+  - cabal %CABOPTS% build all+  - cabal %CABOPTS% test  all
examples/cabal-full/benchmark/Main.hs view
@@ -1,7 +1,7 @@ module Main (main) where -import Gauge.Main+import CabalFull (projectName)   main :: IO ()-main = defaultMain [bench "const" (whnf const ())]+main = putStrLn ("Benchmarks for " ++ projectName)
examples/cabal-full/cabal-full.cabal view
@@ -1,41 +1,51 @@-cabal-version:       2.4+cabal-version:       3.0 name:                cabal-full version:             0.0.0.0 synopsis:            Cabal-only example with all integrations-description:         Cabal-only example with all integrations+description:+    Cabal-only example with all integrations.+    See [README.md](https://github.com/kowainik/cabal-full#cabal-full) for more details. 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+copyright:           2022 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+                     GHC == 8.8.4+                     GHC == 8.10.7+                     GHC == 9.0.2+                     GHC == 9.2.8+                     GHC == 9.4.8+                     GHC == 9.6.7+                     GHC == 9.8.4+                     GHC == 9.10.3+                     GHC == 9.12.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+  build-depends:       base >= 4.11.1.0 && < 4.22                      , 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+                       -Wredundant-constraints+                       -Wnoncanonical-monad-instances   if impl(ghc >= 8.2)     ghc-options:       -fhide-source-paths   if impl(ghc >= 8.4)@@ -43,6 +53,29 @@                        -Wpartial-fields   if impl(ghc >= 8.8)     ghc-options:       -Wmissing-deriving-strategies+                       -fwrite-ide-info+                       -hiedir=.hie+  if impl(ghc >= 8.10)+    ghc-options:       -Wunused-packages+  if impl(ghc >= 9.0)+    ghc-options:       -Winvalid-haddock+  if impl(ghc >= 9.2)+    ghc-options:       -Wredundant-bang-patterns+                       -Woperator-whitespace+  if impl(ghc >= 9.4  && < 9.10)+    ghc-options:       -Wforall-identifier+  if impl(ghc >= 9.4)+    ghc-options:       -Wredundant-strictness-flags+  if impl(ghc >= 9.8)+    ghc-options:       -Wterm-variable-capture+                       -Winconsistent-flags+  if impl(ghc >= 9.10)+    ghc-options:       -Wincomplete-record-selectors+                       -Wdeprecated-type-abstractions+                       -Wdata-kinds-tc+                       -Wdefaulted-exception-context+  if impl(ghc >= 9.12)+    ghc-options:       -Wview-pattern-signatures    default-language:    Haskell2010   default-extensions:  DeriveGeneric@@ -77,8 +110,7 @@   type:                exitcode-stdio-1.0   hs-source-dirs:      benchmark   main-is:             Main.hs-  build-depends:       gauge-                     , cabal-full+  build-depends:       cabal-full   ghc-options:         -threaded                        -rtsopts                        -with-rtsopts=-N
examples/cabal-full/src/CabalFull.hs view
@@ -1,5 +1,5 @@ {- |-Copyright: (c) 2020 Kowainik+Copyright: (c) 2022 Kowainik SPDX-License-Identifier: BSD-3-Clause Maintainer: Kowainik <xrom.xkov@gmail.com> @@ -7,9 +7,9 @@ -}  module CabalFull-       ( someFunc-       ) where+    ( projectName+    ) where  -someFunc :: IO ()-someFunc = putStrLn ("someFunc" :: String)+projectName :: String+projectName = "cabal-full"
examples/cabal-full/test/Spec.hs view
@@ -1,5 +1,7 @@ module Main (main) where +import CabalFull (projectName) + main :: IO ()-main = putStrLn ("Test suite is not implemented" :: String)+main = putStrLn ("Tests for " ++ projectName)
examples/cabal-minimal/app/Main.hs view
@@ -2,4 +2,4 @@   main :: IO ()-main = putStrLn ("Hello, world!" :: String)+main = putStrLn ("Executable not implemented" :: String)
examples/cabal-minimal/cabal-minimal.cabal view
@@ -1,27 +1,29 @@-cabal-version:       2.4+cabal-version:       3.0 name:                cabal-minimal version:             0.0.0.0 synopsis:            Minimal cabal-only test project-description:         Minimal cabal-only test project+description:+    Minimal cabal-only test project.+    See README.md for more details. license:             NONE author:              Kowainik maintainer:          Kowainik <xrom.xkov@gmail.com>-copyright:           2020 Kowainik+copyright:           2022 Kowainik build-type:          Simple extra-doc-files:     README.md                      CHANGELOG.md-tested-with:         GHC == 8.8.3+tested-with:         GHC == 9.12.3  common common-options-  build-depends:       base ^>= 4.13.0.0-  +  build-depends:       base ^>= 4.21.1.0+   ghc-options:         -Wall                        -Wcompat                        -Widentities                        -Wincomplete-uni-patterns                        -Wincomplete-record-updates-  if impl(ghc >= 8.0)-    ghc-options:       -Wredundant-constraints+                       -Wredundant-constraints+                       -Wnoncanonical-monad-instances   if impl(ghc >= 8.2)     ghc-options:       -fhide-source-paths   if impl(ghc >= 8.4)@@ -29,6 +31,29 @@                        -Wpartial-fields   if impl(ghc >= 8.8)     ghc-options:       -Wmissing-deriving-strategies+                       -fwrite-ide-info+                       -hiedir=.hie+  if impl(ghc >= 8.10)+    ghc-options:       -Wunused-packages+  if impl(ghc >= 9.0)+    ghc-options:       -Winvalid-haddock+  if impl(ghc >= 9.2)+    ghc-options:       -Wredundant-bang-patterns+                       -Woperator-whitespace+  if impl(ghc >= 9.4  && < 9.10)+    ghc-options:       -Wforall-identifier+  if impl(ghc >= 9.4)+    ghc-options:       -Wredundant-strictness-flags+  if impl(ghc >= 9.8)+    ghc-options:       -Wterm-variable-capture+                       -Winconsistent-flags+  if impl(ghc >= 9.10)+    ghc-options:       -Wincomplete-record-selectors+                       -Wdeprecated-type-abstractions+                       -Wdata-kinds-tc+                       -Wdefaulted-exception-context+  if impl(ghc >= 9.12)+    ghc-options:       -Wview-pattern-signatures    default-language:    Haskell2010 @@ -36,7 +61,6 @@   import:              common-options   hs-source-dirs:      app   main-is:             Main.hs-     ghc-options:         -threaded                        -rtsopts                        -with-rtsopts=-N
examples/full-batteries/.github/CODEOWNERS view
@@ -1,1 +1,1 @@-*  @chshersh @vrom911+*  @vrom911
examples/full-batteries/.github/workflows/ci.yml view
@@ -1,46 +1,168 @@ name: CI -# Trigger the workflow on push or pull request, but only for the master branch on:   pull_request:+    types: [synchronize, opened, reopened]   push:-    branches: [master]+    branches: [main]+  schedule:+    # additionally run once per week (At 00:00 on Sunday) to maintain cache+    - cron: '0 0 * * 0'  jobs:-  build:-    name: ghc ${{ matrix.ghc }}-    runs-on: ubuntu-16.04+  cabal:+    name: ${{ matrix.os }} / ghc ${{ matrix.ghc }}+    runs-on: ${{ matrix.os }}     strategy:       matrix:-        cabal: ["2.4"]+        os: [ubuntu-latest, macOS-latest, windows-latest]+        cabal: ["3.14.2.0"]         ghc:           - "8.0.2"           - "8.2.2"           - "8.4.4"           - "8.6.5"-          - "8.8.3"+          - "8.8.4"+          - "8.10.7"+          - "9.0.2"+          - "9.2.8"+          - "9.4.8"+          - "9.6.7"+          - "9.8.4"+          - "9.10.3"+          - "9.12.3"+        exclude:+          - os: macOS-latest+            ghc: 9.10.3+          - os: macOS-latest+            ghc: 9.8.4+          - os: macOS-latest+            ghc: 9.6.7+          - os: macOS-latest+            ghc: 9.4.8+          - os: macOS-latest+            ghc: 9.2.8+          - os: macOS-latest+            ghc: 9.0.2+          - os: macOS-latest+            ghc: 8.10.7+          - os: macOS-latest+            ghc: 8.8.4+          - os: macOS-latest+            ghc: 8.6.5+          - os: macOS-latest+            ghc: 8.4.4+          - os: macOS-latest+            ghc: 8.2.2+          - os: macOS-latest+            ghc: 8.0.2+          - os: windows-latest+            ghc: 9.10.3+          - os: windows-latest+            ghc: 9.8.4+          - os: windows-latest+            ghc: 9.6.7+          - os: windows-latest+            ghc: 9.4.8+          - os: windows-latest+            ghc: 9.2.8+          - os: windows-latest+            ghc: 9.0.2+          - os: windows-latest+            ghc: 8.10.7+          - os: windows-latest+            ghc: 8.8.4+          - os: windows-latest+            ghc: 8.6.5+          - os: windows-latest+            ghc: 8.4.4+          - os: windows-latest+            ghc: 8.2.2+          - os: windows-latest+            ghc: 8.0.2      steps:-    - uses: actions/checkout@v2-      if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/master'+    - uses: actions/checkout@v4 -    - uses: actions/setup-haskell@v1+    - uses: haskell-actions/setup@v2+      id: setup-haskell-cabal       name: Setup Haskell       with:         ghc-version: ${{ matrix.ghc }}         cabal-version: ${{ matrix.cabal }} -    - uses: actions/cache@v1+    - name: Configure+      run: |+        cabal configure --enable-tests --enable-benchmarks --enable-documentation --test-show-details=direct --write-ghc-environment-files=always++    - name: Freeze+      run: |+        cabal freeze++    - uses: actions/cache@v4       name: Cache ~/.cabal/store       with:-        path: ~/.cabal/store-        key: ${{ runner.os }}-${{ matrix.ghc }}-cabal+        path: ${{ steps.setup-haskell-cabal.outputs.cabal-store }}+        key: ${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('cabal.project.freeze') }} +    - name: Install dependencies+      run: |+        cabal build all --only-dependencies+     - name: Build       run: |-        cabal v2-update-        cabal v2-build --enable-tests --enable-benchmarks+        cabal build all      - name: Test       run: |-        cabal v2-test --enable-tests+        cabal test all++    - name: Documentation+      run: |+        cabal haddock+++  stack:+    name: stack / ghc ${{ matrix.ghc }}+    runs-on: ubuntu-latest+    strategy:+      matrix:+        stack: ["3.3.1"]+        ghc:+          - "8.0.2"+          - "8.2.2"+          - "8.4.4"+          - "8.6.5"+          - "8.8.4"+          - "8.10.7"+          - "9.0.2"+          - "9.2.8"+          - "9.4.8"+          - "9.6.7"+          - "9.8.4"+          - "9.10.3"+          - "9.12.3"++    steps:+    - uses: actions/checkout@v4+      if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/main'++    - uses: haskell-actions/setup@v2+      name: Setup Haskell Stack+      with:+        ghc-version: ${{ matrix.ghc }}+        stack-version: ${{ matrix.stack }}++    - uses: actions/cache@v4+      name: Cache ~/.stack+      with:+        path: ~/.stack+        key: ${{ runner.os }}-${{ matrix.ghc }}-stack++    - name: Build+      run: |+        stack build --system-ghc --test --bench --no-run-tests --no-run-benchmarks --ghc-options=-Werror++    - name: Test+      run: |+        stack test --system-ghc
examples/full-batteries/.gitignore view
@@ -21,6 +21,7 @@ cabal.project.local .ghc.environment.* .HTF/+.hie/ # Stack .stack-work/ stack.yaml.lock
examples/full-batteries/.travis.yml view
@@ -1,10 +1,9 @@-sudo: true language: haskell  git:   depth: 5 -cabal: "2.4"+cabal: "3.14.2.0"  cache:   directories:@@ -12,37 +11,69 @@   - "$HOME/.stack"   - "$TRAVIS_BUILD_DIR/.stack-work" -matrix:+jobs:   include:   - ghc: 8.0.2   - ghc: 8.2.2   - ghc: 8.4.4   - ghc: 8.6.5-  - ghc: 8.8.3-  +  - ghc: 8.8.4+  - ghc: 8.10.7+  - ghc: 9.0.2+  - ghc: 9.2.8+  - ghc: 9.4.8+  - ghc: 9.6.7+  - ghc: 9.8.4+  - ghc: 9.10.3+  - ghc: 9.12.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++  - ghc: 8.8.4+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.8.4.yaml"++  - ghc: 8.10.7+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.10.7.yaml"++  - ghc: 9.0.2+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-9.0.2.yaml"++  - ghc: 9.2.8+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-9.2.8.yaml"++  - ghc: 9.4.8+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-9.4.8.yaml"++  - ghc: 9.6.7+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-9.6.7.yaml"++  - ghc: 9.8.4+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-9.8.4.yaml"++  - ghc: 9.10.3+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-9.10.3.yaml"++  - ghc: 9.12.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" @@ -52,8 +83,9 @@    - |     if [ -z "$STACK_YAML" ]; then-      cabal v2-update-      cabal v2-build --enable-tests --enable-benchmarks+      cabal update+      cabal configure --enable-tests --enable-benchmarks --enable-documentation --test-show-details=direct --write-ghc-environment-files=always+      cabal build all     else       curl -sSL https://get.haskellstack.org/ | sh       stack --version@@ -63,7 +95,7 @@ script:   - |     if [ -z "$STACK_YAML" ]; then-      cabal v2-test --enable-tests+      cabal test all     else       stack test --system-ghc     fi
examples/full-batteries/LICENSE view
@@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 Kowainik+Copyright (c) 2022 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
examples/full-batteries/README.md view
@@ -1,8 +1,8 @@ # 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)+[![Build status](https://img.shields.io/travis/kowainik/full-batteries.svg?logo=travis)](https://travis-ci.com/kowainik/full-batteries)+[![Windows build status](https://ci.appveyor.com/api/projects/status/github/kowainik/full-batteries?branch=main&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)
examples/full-batteries/app/Main.hs view
@@ -1,7 +1,7 @@ module Main (main) where -import FullBatteries (someFunc)+import FullBatteries (projectName)   main :: IO ()-main = someFunc+main = putStrLn ("Executable for " ++ projectName)
examples/full-batteries/appveyor.yml view
@@ -4,6 +4,11 @@ # Do not build feature branch with open Pull Requests skip_branch_with_pr: true +# build only main branch+branches:+  only:+    - main+ platform:   - x86_64 @@ -16,19 +21,20 @@     CABOPTS: --store-dir=C:\\SR    matrix:-    - GHCVER: 8.8.3+    - GHCVER: 9.12.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+  - choco install -y cabal --version 3.6.2.0+  - choco install -y ghc   --version 9.12.3   - refreshenv  before_build:   - cabal --version   - ghc   --version-  - cabal %CABOPTS% v2-update+  - cabal %CABOPTS% update  build_script:-  - cabal %CABOPTS% v2-build --enable-tests-  - cabal %CABOPTS% v2-test  --enable-tests+  - cabal %CABOPTS% configure --enable-tests --enable-benchmarks --enable-documentation --test-show-details=direct --write-ghc-environment-files=always+  - cabal %CABOPTS% build all+  - cabal %CABOPTS% test  all
examples/full-batteries/benchmark/Main.hs view
@@ -1,7 +1,7 @@ module Main (main) where -import Gauge.Main+import FullBatteries (projectName)   main :: IO ()-main = defaultMain [bench "const" (whnf const ())]+main = putStrLn ("Benchmarks for " ++ projectName)
examples/full-batteries/full-batteries.cabal view
@@ -1,15 +1,17 @@-cabal-version:       2.4+cabal-version:       3.0 name:                full-batteries version:             0.0.0.0 synopsis:            Full-featured test project-description:         Full-featured test project+description:+    Full-featured test project.+    See [README.md](https://github.com/kowainik/full-batteries#full-batteries) for more details. 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+copyright:           2022 Kowainik category:            Testing build-type:          Simple extra-doc-files:     README.md@@ -18,19 +20,27 @@                      GHC == 8.2.2                      GHC == 8.4.4                      GHC == 8.6.5-                     GHC == 8.8.3+                     GHC == 8.8.4+                     GHC == 8.10.7+                     GHC == 9.0.2+                     GHC == 9.2.8+                     GHC == 9.4.8+                     GHC == 9.6.7+                     GHC == 9.8.4+                     GHC == 9.10.3+                     GHC == 9.12.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+  build-depends:       base >= 4.9.1.0 && < 4.22                      , relude-  +   mixins:              base hiding (Prelude)                      , relude (Relude as Prelude)-  +   ghc-options:         -Wcompat                        -Widentities @@ -68,8 +78,7 @@   type:                exitcode-stdio-1.0   hs-source-dirs:      benchmark   main-is:             Main.hs-  build-depends:       gauge-                     , full-batteries+  build-depends:       full-batteries   ghc-options:         -threaded                        -rtsopts                        -with-rtsopts=-N
examples/full-batteries/src/FullBatteries.hs view
@@ -1,5 +1,5 @@ {- |-Copyright: (c) 2020 Kowainik+Copyright: (c) 2022 Kowainik SPDX-License-Identifier: MIT Maintainer: Kowainik <xrom.xkov@gmail.com> @@ -7,9 +7,9 @@ -}  module FullBatteries-       ( someFunc-       ) where+    ( projectName+    ) where  -someFunc :: IO ()-someFunc = putStrLn ("someFunc" :: String)+projectName :: String+projectName = "full-batteries"
+ examples/full-batteries/stack-8.10.7.yaml view
@@ -0,0 +1,1 @@+resolver: lts-18.28
+ examples/full-batteries/stack-8.8.4.yaml view
@@ -0,0 +1,1 @@+resolver: lts-16.31
+ examples/full-batteries/stack-9.0.2.yaml view
@@ -0,0 +1,1 @@+resolver: lts-19.33
+ examples/full-batteries/stack-9.10.3.yaml view
@@ -0,0 +1,1 @@+resolver: lts-24.26
+ examples/full-batteries/stack-9.2.8.yaml view
@@ -0,0 +1,1 @@+resolver: lts-20.26
+ examples/full-batteries/stack-9.4.8.yaml view
@@ -0,0 +1,1 @@+resolver: lts-21.25
+ examples/full-batteries/stack-9.6.7.yaml view
@@ -0,0 +1,1 @@+resolver: lts-22.44
+ examples/full-batteries/stack-9.8.4.yaml view
@@ -0,0 +1,1 @@+resolver: lts-23.28
examples/full-batteries/stack.yaml view
@@ -1,1 +1,1 @@-resolver: lts-15.5+resolver: nightly-2026-01-04
examples/full-batteries/test/Spec.hs view
@@ -1,5 +1,7 @@ module Main (main) where +import FullBatteries (projectName) + main :: IO ()-main = putStrLn ("Test suite is not implemented" :: String)+main = putStrLn ("Tests for " ++ projectName)
examples/stack-full/.gitignore view
@@ -21,6 +21,7 @@ cabal.project.local .ghc.environment.* .HTF/+.hie/ # Stack .stack-work/ stack.yaml.lock
examples/stack-full/.travis.yml view
@@ -1,32 +1,53 @@-sudo: true language: haskell  git:   depth: 5 -cabal: "2.4"+cabal: "3.14.2.0"  cache:   directories:-     - "$HOME/.stack"   - "$TRAVIS_BUILD_DIR/.stack-work" -matrix:+jobs:   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++  - ghc: 8.8.4+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.8.4.yaml"++  - ghc: 8.10.7+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.10.7.yaml"++  - ghc: 9.0.2+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-9.0.2.yaml"++  - ghc: 9.2.8+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-9.2.8.yaml"++  - ghc: 9.4.8+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-9.4.8.yaml"++  - ghc: 9.6.7+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-9.6.7.yaml"++  - ghc: 9.8.4+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-9.8.4.yaml"++  - ghc: 9.10.3+    env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-9.10.3.yaml"++  - ghc: 9.12.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" 
examples/stack-full/LICENSE view
@@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2020, Kowainik+Copyright (c) 2022, Kowainik All rights reserved.  Redistribution and use in source and binary forms, with or without
examples/stack-full/README.md view
@@ -1,7 +1,8 @@ # 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)+[![GitHub CI](https://github.com/kowainik/stack-full/workflows/CI/badge.svg)](https://github.com/kowainik/stack-full/actions)+[![Build status](https://img.shields.io/travis/kowainik/stack-full.svg?logo=travis)](https://travis-ci.com/kowainik/stack-full)+[![Windows build status](https://ci.appveyor.com/api/projects/status/github/kowainik/stack-full?branch=main&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)
examples/stack-full/app/Main.hs view
@@ -1,7 +1,7 @@ module Main (main) where -import StackFull (someFunc)+import StackFull (projectName)   main :: IO ()-main = someFunc+main = putStrLn ("Executable for " ++ projectName)
examples/stack-full/appveyor.yml view
@@ -3,9 +3,14 @@ # Do not build feature branch with open Pull Requests skip_branch_with_pr: true +# build only main branch+branches:+  only:+    - main+ environment:   STACK_ROOT: C:\sr-  STACK_VERSION: 2.1.1+  STACK_VERSION: 3.3.1    # Workaround a gnarly bug https://github.com/haskell/cabal/issues/5386   # See: https://www.fpcomplete.com/blog/2018/06/sed-a-debugging-story
examples/stack-full/benchmark/Main.hs view
@@ -1,7 +1,7 @@ module Main (main) where -import Gauge.Main+import StackFull (projectName)   main :: IO ()-main = defaultMain [bench "const" (whnf const ())]+main = putStrLn ("Benchmarks for " ++ projectName)
examples/stack-full/src/StackFull.hs view
@@ -1,5 +1,5 @@ {- |-Copyright: (c) 2020 Kowainik+Copyright: (c) 2022 Kowainik SPDX-License-Identifier: BSD-3-Clause Maintainer: Kowainik <xrom.xkov@gmail.com> @@ -7,9 +7,9 @@ -}  module StackFull-       ( someFunc-       ) where+    ( projectName+    ) where  -someFunc :: IO ()-someFunc = putStrLn ("someFunc" :: String)+projectName :: String+projectName = "stack-full"
+ examples/stack-full/stack-8.10.7.yaml view
@@ -0,0 +1,1 @@+resolver: lts-18.28
+ examples/stack-full/stack-8.8.4.yaml view
@@ -0,0 +1,1 @@+resolver: lts-16.31
+ examples/stack-full/stack-9.0.2.yaml view
@@ -0,0 +1,1 @@+resolver: lts-19.33
+ examples/stack-full/stack-9.10.3.yaml view
@@ -0,0 +1,1 @@+resolver: lts-24.26
+ examples/stack-full/stack-9.2.8.yaml view
@@ -0,0 +1,1 @@+resolver: lts-20.26
+ examples/stack-full/stack-9.4.8.yaml view
@@ -0,0 +1,1 @@+resolver: lts-21.25
+ examples/stack-full/stack-9.6.7.yaml view
@@ -0,0 +1,1 @@+resolver: lts-22.44
+ examples/stack-full/stack-9.8.4.yaml view
@@ -0,0 +1,1 @@+resolver: lts-23.28
examples/stack-full/stack-full.cabal view
@@ -1,41 +1,51 @@-cabal-version:       2.4+cabal-version:       3.0 name:                stack-full version:             0.0.0.0 synopsis:            Stack-only example with all integrations-description:         Stack-only example with all integrations+description:+    Stack-only example with all integrations.+    See [README.md](https://github.com/kowainik/stack-full#stack-full) for more details. 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+copyright:           2022 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+                     GHC == 8.8.4+                     GHC == 8.10.7+                     GHC == 9.0.2+                     GHC == 9.2.8+                     GHC == 9.4.8+                     GHC == 9.6.7+                     GHC == 9.8.4+                     GHC == 9.10.3+                     GHC == 9.12.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+  build-depends:       base >= 4.11.1.0 && < 4.22                      , 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+                       -Wredundant-constraints+                       -Wnoncanonical-monad-instances   if impl(ghc >= 8.2)     ghc-options:       -fhide-source-paths   if impl(ghc >= 8.4)@@ -43,6 +53,29 @@                        -Wpartial-fields   if impl(ghc >= 8.8)     ghc-options:       -Wmissing-deriving-strategies+                       -fwrite-ide-info+                       -hiedir=.hie+  if impl(ghc >= 8.10)+    ghc-options:       -Wunused-packages+  if impl(ghc >= 9.0)+    ghc-options:       -Winvalid-haddock+  if impl(ghc >= 9.2)+    ghc-options:       -Wredundant-bang-patterns+                       -Woperator-whitespace+  if impl(ghc >= 9.4  && < 9.10)+    ghc-options:       -Wforall-identifier+  if impl(ghc >= 9.4)+    ghc-options:       -Wredundant-strictness-flags+  if impl(ghc >= 9.8)+    ghc-options:       -Wterm-variable-capture+                       -Winconsistent-flags+  if impl(ghc >= 9.10)+    ghc-options:       -Wincomplete-record-selectors+                       -Wdeprecated-type-abstractions+                       -Wdata-kinds-tc+                       -Wdefaulted-exception-context+  if impl(ghc >= 9.12)+    ghc-options:       -Wview-pattern-signatures    default-language:    Haskell2010   default-extensions:  DeriveGeneric@@ -77,8 +110,7 @@   type:                exitcode-stdio-1.0   hs-source-dirs:      benchmark   main-is:             Main.hs-  build-depends:       gauge-                     , stack-full+  build-depends:       stack-full   ghc-options:         -threaded                        -rtsopts                        -with-rtsopts=-N
examples/stack-full/stack.yaml view
@@ -1,1 +1,1 @@-resolver: lts-15.5+resolver: nightly-2026-01-04
examples/stack-full/test/Spec.hs view
@@ -1,5 +1,7 @@ module Main (main) where +import StackFull (projectName) + main :: IO ()-main = putStrLn ("Test suite is not implemented" :: String)+main = putStrLn ("Tests for " ++ projectName)
examples/summoner-default.toml view
@@ -48,9 +48,9 @@ # travis = true         # Travis CI # appveyor = true       # AppVeyor CI -# List of additional GHC versions to support besides 8.8.3.+# List of additional GHC versions to support besides 9.12.3. # Run the 'summon show ghc' command to see the list of all supported GHC versions.-# ghcVersions = ["8.4.4", "8.6.5"]+# ghcVersions = ["9.8.4", "9.10.3"]  # List of default-extensions in the .cabal file # extensions = [ "ConstraintKinds"@@ -71,7 +71,7 @@ # 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"+#       , url  = "https://raw.githubusercontent.com/kowainik/org/main/.stylish-haskell.yaml" #       } #     , { path = ".github/CODEOWNERS" #       , raw  = "*  @kowainik"
+ golden/Main.hs view
@@ -0,0 +1,9 @@+module Main (main) where++import Summoner.Golden (generateProjects, generateScripts, generateTomlConfig)++main :: IO ()+main = do+    generateScripts+    generateTomlConfig+    generateProjects
src/Summoner.hs view
@@ -1,7 +1,10 @@ {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  Main module that reexports all library components of the @summoner@. -}
src/Summoner/CLI.hs view
@@ -1,47 +1,47 @@ {-# LANGUAGE ApplicativeDo   #-}-{-# LANGUAGE QuasiQuotes     #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TupleSections   #-}  {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.CLI+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  This module contains functions and data types to parse CLI inputs. -}  module Summoner.CLI-       ( -- * CLI data types-         Command (..)-       , NewOpts (..)-       , ShowOpts (..)+    ( -- * CLI data types+      Command (..)+    , NewOpts (..)+    , ShowOpts (..) -         -- * Functions to parse CLI arguments and run @summoner@-       , summon-       , summonCli+      -- * Functions to parse CLI arguments and run @summoner@+    , summon+    , summonCli -         -- * Runners-       , runConfig-       , runScript+      -- * Runners+    , runConfig+    , runScript -         -- * Common helper functions-       , getFinalConfig-       , getCustomLicenseText-       ) where+      -- * Common helper functions+    , getFinalConfig+    , getCustomLicenseText+    ) where  import Colourista (blue, bold, errorMessage, formatWith, infoMessage, successMessage,                    warningMessage) import Data.Version (Version, showVersion) 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, prefs,                             progDesc, short, showDefault, showHelpOnEmpty, strArgument, strOption,                             subparser, subparserInline, switch, value) import Options.Applicative.Help.Chunk (stringChunk)-import Relude.Extra.Enum (universe) import System.Directory (doesFileExist) import System.Info (os) import Validation (Validation (..))@@ -58,7 +58,6 @@ import Summoner.Project (generateProject) import Summoner.Settings (Tool, parseTool) import Summoner.Template.Script (scriptFile)-import Summoner.Text (endLine)  import qualified Data.Text as T import qualified Paths_summoner as Meta (version)@@ -84,10 +83,10 @@ -- | Run 'summoner' with @CLI@ command runCliCommand :: Command -> IO () runCliCommand = \case-    New opts -> runNew opts-    Script opts -> runScript opts+    New opts      -> runNew opts+    Script opts   -> runScript opts     ShowInfo opts -> runShow opts-    Config opts -> runConfig opts+    Config opts   -> runConfig opts   {- | Runs @config@ command@@ -254,13 +253,13 @@ -- | Represent all available commands data Command     -- | @new@ command creates a new project-    = New NewOpts+    = New !NewOpts     -- | @script@ command creates Haskell script-    | Script ScriptOpts+    | Script !ScriptOpts     -- | @show@ command shows supported licenses or GHC versions-    | ShowInfo ShowOpts+    | ShowInfo !ShowOpts     -- | @config@ command creates the TOML configuration file-    | Config ConfigOpts+    | Config !ConfigOpts  -- | Options parsed with the @new@ command data NewOpts = NewOpts@@ -282,7 +281,7 @@ -- | Commands parsed with @show@ command data ShowOpts     = GhcList-    | LicenseList (Maybe String)+    | LicenseList !(Maybe String)  -- | Options parsed with the @config@ command newtype ConfigOpts = ConfigOpts@@ -424,7 +423,7 @@     cExe       <- execP      d     cTest      <- testP      d     cBench     <- benchmarkP d-    pure mempty+    pure (mempty :: PartialConfig)         { cGitHub    = cGitHub         , cGhActions = cGhActions         , cTravis    = cTravis@@ -583,39 +582,39 @@ modifyFooter p = p {infoFooter = stringChunk $ toString artFooter}  artHeader :: Text-artHeader = [text|-$endLine-                                                   ___-                                                 ╱  .  ╲-                                                │╲_/│   │-                                                │   │  ╱│-  ___________________________________________________-' │- ╱                                                      │-╱   .-.                                                 │-│  ╱   ╲                                                │-│ │\_.  │ Summoner — tool for creating Haskell projects │-│\│  │ ╱│                                               │-│ `-_-' │                                              ╱-│       │_____________________________________________╱-│       │- ╲     ╱-  `-_-'-|]+artHeader = unlines+    [ ""+    , "                                                   ___"+    , "                                                 ╱  .  ╲"+    , "                                                │╲_/│   │"+    , "                                                │   │  ╱│"+    , "  ___________________________________________________-' │"+    , " ╱                                                      │"+    , "╱   .-.                                                 │"+    , "│  ╱   ╲                                                │"+    , "│ │\\_.  │ Summoner — tool for creating Haskell projects │"+    , "│\\│  │ ╱│                                               │"+    , "│ `-_-' │                                              ╱"+    , "│       │_____________________________________________╱"+    , "│       │"+    , " ╲     ╱"+    , "  `-_-'"+    ]  artFooter :: Text-artFooter = [text|-$endLine-              , *   +-           +      o   *             ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓-            * @ ╭─╮  .      ________┃                                 ┃_______-           ╱| . │λ│ @   '   ╲       ┃   λ Haskell's summon scroll λ   ┃      ╱-         _╱ ╰─  ╰╥╯    O     ╲      ┃                                 ┃     ╱-        .─╲"╱. * ║  +        ╱      ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛     ╲-       ╱  ( ) ╲_ ║          ╱__________)                           (_________╲-       ╲ ╲(')╲__(╱-       ╱╱`)╱ `╮  ║- `╲.  ╱╱  (   │  ║-  ╲.╲╱        │  ║-  `╰══════════╯-$endLine-|]+artFooter = unlines+    [ ""+    , "              , *   +"+    , "           +      o   *             ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓"+    , "            * @ ╭─╮  .      ________┃                                 ┃_______"+    , "           ╱| . │λ│ @   '   ╲       ┃   λ Haskell's summon scroll λ   ┃      ╱"+    , "         _╱ ╰─  ╰╥╯    O     ╲      ┃                                 ┃     ╱"+    , "        .─╲\"╱. * ║  +        ╱      ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛     ╲"+    , "       ╱  ( ) ╲_ ║          ╱__________)                           (_________╲"+    , "       ╲ ╲(')╲__(╱"+    , "       ╱╱`)╱ `╮  ║"+    , " `╲.  ╱╱  (   │  ║"+    , "  ╲.╲╱        │  ║"+    , "  `╰══════════╯"+    , ""+    ]
src/Summoner/Config.hs view
@@ -7,9 +7,12 @@ {-# LANGUAGE UndecidableInstances #-}  {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.Config+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  Summoner configurations. -}@@ -29,6 +32,7 @@  import Data.List (lookup) import Generic.Data (gmappend, gmempty)+import Generic.Data.Orphans () import Shellmet (($?), ($|)) import Toml (Key, TomlBiMap, TomlCodec, (.=)) import Validation (Validation (..))
src/Summoner/CustomPrelude.hs view
@@ -1,7 +1,10 @@ {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.CustomPrelude+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  This module implements data type for representing custom alternative preludes. -}
src/Summoner/Decision.hs view
@@ -1,7 +1,10 @@ {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.Decision+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  Decision data type. -}
src/Summoner/Default.hs view
@@ -1,9 +1,10 @@-{-# LANGUAGE QuasiQuotes #-}- {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.Default+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  This module contains some default values to use. -}@@ -11,6 +12,8 @@ module Summoner.Default        ( defaultGHC        , defaultCabal+       , defaultCabalVersion+       , defaultStack        , defaultLicenseName        , defaultOwner        , defaultFullName@@ -20,15 +23,22 @@        , defaultConfigFileContent        , defaultDescription        , currentYear++         -- * GitHub Actions defaults+       , ghcActionsCacheVersion+       , ghcActionsCheckoutVersion+       , ghcActionsSetupHaskellVersion        ) where -import Data.Time (getCurrentTime, toGregorian, utctDay)-import NeatInterpolation (text)+import Relude.Extra.Enum (prev)++import Data.Time (getCurrentTime, getCurrentTimeZone, localDay, toGregorian, utcToLocalTime) import System.Directory (getHomeDirectory) import System.FilePath ((</>))  import Summoner.GhcVer (GhcVer, showGhcVer) import Summoner.License (LicenseName (MIT))+import Summoner.Text (quote)   -- | Default GHC version is the latest available.@@ -37,8 +47,16 @@  -- | Default version of the Cabal. defaultCabal :: Text-defaultCabal = "2.4"+defaultCabal = "3.14.2.0" +-- | Default version of the Cabal specified in the *.cabal* file.+defaultCabalVersion :: Text+defaultCabalVersion = "3.0"++-- | Default version of the Stack.+defaultStack :: Text+defaultStack = "3.3.1"+ defaultLicenseName :: LicenseName defaultLicenseName = MIT @@ -60,108 +78,121 @@ defaultDescription :: Text defaultDescription = "See README for more info" +ghcActionsCheckoutVersion :: Text+ghcActionsCheckoutVersion = "@v4"++ghcActionsSetupHaskellVersion :: Text+ghcActionsSetupHaskellVersion = "@v2"++ghcActionsCacheVersion :: Text+ghcActionsCacheVersion = "@v4"+ currentYear :: IO Text currentYear = do     now <- getCurrentTime-    let (year, _, _) = toGregorian $ utctDay now+    zone <- getCurrentTimeZone+    let localNow = utcToLocalTime zone now+    let (year, _, _) = toGregorian $ localDay localNow     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"-|]+defaultConfigFileContent = unlines+    [ "# 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 = " <> quote defaultOwner+    , ""+    , "# First and last name"+    , "fullName = " <> quote defaultFullName+    , ""+    , "# Email used at GitHub"+    , "email = " <> quote defaultEmail+    , ""+    , "# Default OSS license for your projects."+    , "# Run the 'summon show license' command to see the list of supported licenses."+    , "license = " <> quote 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"+    , "#     [ " <> quote "build"+    , "#     , " <> quote "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 = [" <> quote defaultGhcPrevPrev <> ", " <> quote defaultGhcPrev <> "]"+    , ""+    , "# List of default-extensions in the .cabal file"+    , "# extensions = [ " <> quote "ConstraintKinds"+    , "#              , " <> quote "DeriveGeneric"+    , "#              , " <> quote "GeneralizedNewtypeDeriving"+    , "#              , " <> quote "InstanceSigs"+    , "#              , " <> quote "KindSignatures"+    , "#              , " <> quote "LambdaCase"+    , "#              , " <> quote "OverloadedStrings"+    , "#              , " <> quote "RecordWildCards"+    , "#              , " <> quote "ScopedTypeVariables"+    , "#              , " <> quote "StandaloneDeriving"+    , "#              , " <> quote "TupleSections"+    , "#              , " <> quote "TypeApplications"+    , "#              , " <> quote "ViewPatterns"+    , "#              ]"+    , ""+    , "# List of additional files to add after creating the project"+    , "# files ="+    , "#     [ { path = " <> quote ".stylish-haskell.yaml"+    , "#       , url  = " <> quote "https://raw.githubusercontent.com/kowainik/org/main/.stylish-haskell.yaml"+    , "#       }"+    , "#     , { path = " <> quote ".github/CODEOWNERS"+    , "#       , raw  = " <> quote ("*  @" <> defaultOwner)+    , "#       }"+    , "#     , { path  = " <> quote "src/Foo.hs"+    , "#       , local = " <> quote "/home/user/.default/Foo.hs"+    , "#       }"+    , "#     ]"+    , ""+    , "# Alternative Prelude to be used instead of the default one if you prefer"+    , "# [prelude]"+    , "#     package = " <> quote "relude"+    , "#     module  = " <> quote "Relude"+    ]   where     licenseName :: Text     licenseName = show defaultLicenseName -    defaultGhcVer :: Text+    defaultGhcVer, defaultGhcPrev, defaultGhcPrevPrev :: Text     defaultGhcVer = showGhcVer defaultGHC+    defaultGhcPrev = showGhcVer $ prev defaultGHC+    defaultGhcPrevPrev = showGhcVer $ prev $ prev defaultGHC
src/Summoner/GhcVer.hs view
@@ -1,28 +1,28 @@ {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.GhcVer+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  Contains data type for GHC versions supported by Summoner and some useful functions for manipulation with them. -}  module Summoner.GhcVer-       ( GhcVer (..)-       , GhcMeta (..)-       , Pvp (..)-       , showGhcVer-       , parseGhcVer-       , latestLts-       , baseVer-       , cabalBaseVersions-       , ghcTable--       , oldGhcs-       ) where+    ( GhcVer (..)+    , GhcMeta (..)+    , Pvp (..)+    , showGhcVer+    , parseGhcVer+    , latestLts+    , baseVer+    , cabalBaseVersions+    , ghcTable -import Data.List (maximum, minimum)-import Relude.Extra.Enum (inverseMap, universe)+    , oldGhcs+    ) where  import qualified Data.Text as T import qualified Text.Show as Show@@ -30,23 +30,37 @@  -- | Represents some selected set of GHC versions. data GhcVer-    = Ghc7103-    | Ghc802+    = Ghc802     | Ghc822     | Ghc844     | Ghc865-    | Ghc883+    | Ghc884+    | Ghc8107+    | Ghc902+    | Ghc928+    | Ghc948+    | Ghc967+    | Ghc984+    | Ghc9103+    | Ghc9123     deriving stock (Eq, Ord, Show, Enum, Bounded)  -- | Converts 'GhcVer' into dot-separated string. showGhcVer :: GhcVer -> Text showGhcVer = \case-    Ghc7103 -> "7.10.3"     Ghc802  -> "8.0.2"     Ghc822  -> "8.2.2"     Ghc844  -> "8.4.4"     Ghc865  -> "8.6.5"-    Ghc883  -> "8.8.3"+    Ghc884  -> "8.8.4"+    Ghc8107 -> "8.10.7"+    Ghc902  -> "9.0.2"+    Ghc928  -> "9.2.8"+    Ghc948  -> "9.4.8"+    Ghc967  -> "9.6.7"+    Ghc984  -> "9.8.4"+    Ghc9103 -> "9.10.3"+    Ghc9123 -> "9.12.3"  {- | These are old GHC versions that are not working with default GHC versions when using Stack.@@ -60,19 +74,26 @@ -- | Returns latest known LTS resolver for all GHC versions except default one. latestLts :: GhcVer -> Text latestLts = \case-    Ghc7103 -> "lts-6.35"     Ghc802  -> "lts-9.21"     Ghc822  -> "lts-11.22"     Ghc844  -> "lts-12.26"     Ghc865  -> "lts-14.27"-    Ghc883  -> "lts-15.5"+    Ghc884  -> "lts-16.31"+    Ghc8107 -> "lts-18.28"+    Ghc902  -> "lts-19.33"+    Ghc928  -> "lts-20.26"+    Ghc948  -> "lts-21.25"+    Ghc967  -> "lts-22.44"+    Ghc984  -> "lts-23.28"+    Ghc9103 -> "lts-24.26"+    Ghc9123 -> "nightly-2026-01-04"  -- | Represents PVP versioning (4 numbers). data Pvp = Pvp-    { pvpFirst  :: Int-    , pvpSecond :: Int-    , pvpThird  :: Int-    , pvpFourth :: Int+    { pvpFirst  :: !Int+    , pvpSecond :: !Int+    , pvpThird  :: !Int+    , pvpFourth :: !Int     }  -- | Show PVP version in a standard way: @1.2.3.4@@@ -82,12 +103,19 @@ -- | Returns base version by 'GhcVer' as 'Pvp'. baseVerPvp :: GhcVer -> Pvp baseVerPvp = \case-    Ghc7103 -> Pvp 4 8 0 2     Ghc802  -> Pvp 4 9 1 0     Ghc822  -> Pvp 4 10 1 0     Ghc844  -> Pvp 4 11 1 0     Ghc865  -> Pvp 4 12 0 0-    Ghc883  -> Pvp 4 13 0 0+    Ghc884  -> Pvp 4 13 0 0+    Ghc8107 -> Pvp 4 14 3 0+    Ghc902  -> Pvp 4 15 1 0+    Ghc928  -> Pvp 4 16 4 0+    Ghc948  -> Pvp 4 17 2 1+    Ghc967  -> Pvp 4 18 3 1+    Ghc984  -> Pvp 4 19 2 0+    Ghc9103 -> Pvp 4 20 2 0+    Ghc9123 -> Pvp 4 21 1 0  -- | Returns corresponding @base@ version of the given GHC version. baseVer :: GhcVer -> Text@@ -103,12 +131,13 @@  -} cabalBaseVersions :: [GhcVer] -> Text-cabalBaseVersions []   = ""-cabalBaseVersions [v]  = "^>= " <> baseVer v-cabalBaseVersions ghcs = ">= " <> baseVer (minimum ghcs) <> " && < " <> upperBound+cabalBaseVersions ghcVers = case sort ghcVers of+    []          -> ""+    [v]         -> "^>= " <> baseVer v+    minGhc:x:xs -> ">= " <> baseVer minGhc <> " && < " <> upperBound (x :| xs)   where-    upperBound :: Text-    upperBound = let Pvp{..} = baseVerPvp $ maximum ghcs in+    upperBound :: NonEmpty GhcVer -> Text+    upperBound ghcs = let Pvp{..} = baseVerPvp $ last ghcs in         show pvpFirst <> "." <> show (pvpSecond + 1)  -- | Data type to keep meta information for every 'GhcVer'.
+ src/Summoner/Golden.hs view
@@ -0,0 +1,270 @@+{- |+Module                  : Summoner.Golden+Copyright               : (c) 2021-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable++This module contains test data for golden examples.+It is used for both purposes:++  * To test new implementation against the old one+  * In the @gg@ executable to generate new golden examples boilerplate+-}++module Summoner.Golden+    ( -- * Executable scripts+      generateScripts+      -- * Default TOML config+    , generateTomlConfig+      -- * Projects+      -- ** Generator+    , generateProjects+      -- ** Project settings+    , cabalMinimal+    , cabalFull+    , stackFull+    , fullBatteries+    ) where++import Colourista (infoMessage)+import Colourista.Short (b)+import System.Directory (withCurrentDirectory)++import Summoner.CustomPrelude (CustomPrelude (..))+import Summoner.Default (defaultConfigFileContent, defaultGHC)+import Summoner.GhcVer (GhcVer (..))+import Summoner.License (License (..), LicenseName (..))+import Summoner.Settings (Settings (..), Tool (..))+import Summoner.Template (createProjectTemplate)+import Summoner.Template.Script (scriptFile)+import Summoner.Text (quote)+import Summoner.Tree (TreeFs (..), traverseTree)+++generateScripts :: IO ()+generateScripts = do+    generateCabalScript+    generateStackScript++generateCabalScript :: IO ()+generateCabalScript = do+    let path = "summoner-cli/examples/cabalScript.hs"+    infoMessage $ "Writing Cabal script to: " <> toText path+    writeFileText path $ scriptFile defaultGHC Cabal++generateStackScript :: IO ()+generateStackScript = do+    let path = "summoner-cli/examples/stackScript.hs"+    infoMessage $ "Writing Stack script to: " <> toText path+    writeFileText path $ scriptFile defaultGHC Stack++generateTomlConfig :: IO ()+generateTomlConfig = do+    let path = "summoner-cli/examples/summoner-default.toml"+    infoMessage $ "Writing default TOML config to: " <> toText path+    writeFileText path defaultConfigFileContent++----------------------------------------------------------------------------+-- Entire projects+----------------------------------------------------------------------------++generateProjects :: IO ()+generateProjects = withCurrentDirectory "summoner-cli/examples" $ do+    mkProject cabalMinimal+    mkProject cabalFull+    mkProject stackFull+    mkProject fullBatteries++mkProject :: Settings -> IO ()+mkProject settings = do+    infoMessage $ "Creating project: " <> b (settingsRepo settings)+    traverseTree $ createProjectTemplate settings++cabalMinimal :: Settings+cabalMinimal = Settings+    { settingsRepo           = "cabal-minimal"+    , settingsOwner          = "kowainik"+    , settingsDescription    = "Minimal cabal-only test project"+    , settingsFullName       = "Kowainik"+    , settingsEmail          = "xrom.xkov@gmail.com"+    , settingsYear           = "2022"+    , settingsCategories     = ""+    , settingsLicenseName    = NONE+    , settingsLicenseText    = ""+    , settingsGitHub         = False+    , settingsGhActions      = False+    , settingsPrivate        = False+    , settingsTravis         = False+    , settingsAppVeyor       = False+    , settingsIsLib          = False+    , settingsIsExe          = True+    , settingsTest           = False+    , settingsBench          = False+    , settingsTestedVersions = [defaultGHC]+    , settingsPrelude        = Nothing+    , settingsExtensions     = []+    , settingsGhcOptions     = []+    , settingsGitignore      = []+    , settingsCabal          = True+    , settingsStack          = False+    , settingsNoUpload       = True+    , settingsFiles          = mempty+    }++cabalFull :: Settings+cabalFull = Settings+    { settingsRepo           = "cabal-full"+    , settingsOwner          = "kowainik"+    , settingsDescription    = "Cabal-only example with all integrations"+    , settingsFullName       = "Kowainik"+    , settingsEmail          = "xrom.xkov@gmail.com"+    , settingsYear           = "2022"+    , 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          = []+    }++stackFull :: Settings+stackFull = Settings+    { settingsRepo           = "stack-full"+    , settingsOwner          = "kowainik"+    , settingsDescription    = "Stack-only example with all integrations"+    , settingsFullName       = "Kowainik"+    , settingsEmail          = "xrom.xkov@gmail.com"+    , settingsYear           = "2022"+    , 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          = False+    , settingsStack          = True+    , settingsNoUpload       = False+    , settingsFiles          = []+    }++fullBatteries :: Settings+fullBatteries = Settings+    { settingsRepo           = "full-batteries"+    , settingsOwner          = "kowainik"+    , settingsDescription    = "Full-featured test project"+    , settingsFullName       = "Kowainik"+    , settingsEmail          = "xrom.xkov@gmail.com"+    , settingsYear           = "2022"+    , settingsCategories     = "Testing"+    , settingsLicenseName    = MIT+    , settingsLicenseText    = mitLicense+    , settingsGitHub         = True+    , settingsGhActions      = True+    , settingsPrivate        = True+    , settingsTravis         = True+    , settingsAppVeyor       = True+    , settingsIsLib          = True+    , settingsIsExe          = True+    , settingsTest           = True+    , settingsBench          = True+    , settingsTestedVersions = [minBound .. defaultGHC]+    , settingsPrelude        = Just $ CustomPrelude "relude" "Relude"+    , settingsExtensions     = ["ConstraintKinds", "LambdaCase", "OverloadedStrings"]+    , settingsGitignore      = [".secret"]+    , settingsGhcOptions     = ["-Wcompat", "-Widentities"]+    , settingsCabal          = True+    , settingsStack          = True+    , settingsNoUpload       = True+    , settingsFiles          =+        [ File "extra.txt" "See full content of the file [here](@github)\n"+        , Dir ".github" [File "CODEOWNERS" "*  @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  $ unlines+        [ "MIT License"+        , ""+        , "Copyright (c) 2022 Kowainik"+        , ""+        , "Permission is hereby granted, free of charge, to any person obtaining a copy"+        , "of this software and associated documentation files (the " <> quote "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 " <> quote "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."+        ]++bsd3License :: License+bsd3License = License $ unlines+    [ "BSD 3-Clause License"+    , ""+    , "Copyright (c) 2022, 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 " <> quote "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."+    ]
src/Summoner/License.hs view
@@ -1,27 +1,29 @@ {- |-Copyright: (c) 2017-2020 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.License+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  Data types that represent license names and license content and functions to work with them. -}  module Summoner.License-       ( LicenseName(..)-       , License(..)-       , customizeLicense-       , githubLicenseQueryNames-       , parseLicenseName-       , fetchLicense-       , fetchLicenseCustom-       , licenseShortDesc-       , showLicenseWithDesc-       ) where+    ( LicenseName (..)+    , License (..)+    , customizeLicense+    , githubLicenseQueryNames+    , parseLicenseName+    , fetchLicense+    , fetchLicenseCustom+    , licenseShortDesc+    , showLicenseWithDesc+    ) where  import Colourista (errorMessage)-import Data.Aeson (FromJSON (..), decodeStrict, withObject, (.:))-import Relude.Extra.Enum (inverseMap)+import Data.Aeson.Micro (FromJSON (..), decodeStrict, withObject, (.:)) import Shellmet (($|))  import qualified Data.Text as T
src/Summoner/Mode.hs view
@@ -1,7 +1,10 @@ {- |-Copyright: (c) 2020 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.Mode+Copyright               : (c) 2020-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  This module introduces different modes in which the command-line interface could be.
src/Summoner/Project.hs view
@@ -1,15 +1,16 @@-{-# LANGUAGE QuasiQuotes #-}--{- HLINT ignore "Reduce duplication" -}- {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.Project+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  This module introduces functions for the project creation. -} +{- HLINT ignore "Reduce duplication" -}+ module Summoner.Project        ( generateProject        , generateProjectInteractive@@ -20,8 +21,6 @@ import Colourista (bold, errorMessage, formattedMessage, green, infoMessage, skipMessage,                    successMessage, warningMessage) import Data.List.NonEmpty ((<|))-import NeatInterpolation (text)-import Relude.Extra.Enum (universe, universeNonEmpty) import Shellmet (($?)) import System.Directory (findExecutable, setCurrentDirectory) @@ -98,7 +97,7 @@         (settingsGitHub && not settingsNoUpload)         (YesNoPrompt "private repository" "Create as a private repository (Requires a GitHub private repo plan)?")         cPrivate-    settingsGhActions <- decisionIf (settingsCabal && settingsGitHub) (mkDefaultYesNoPrompt "GitHub Actions CI integration") cGhActions+    settingsGhActions <- decisionIf 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")@@ -137,24 +136,23 @@         else falseMessage (yesNoTarget ynPrompt)      categoryText :: Text-    categoryText =-        [text|-        List of categories to choose from:--          * Control                    * Concurrency-          * Codec                      * Graphics-          * Data                       * Sound-          * Math                       * System-          * Parsing                    * Network-          * Text--          * Application                * Development-          * Compilers/Interpreters     * Testing-          * Web-          * Game-          * Utility--        |]+    categoryText = unlines+        [ "List of categories to choose from:"+        , ""+        , "  * Control                    * Concurrency"+        , "  * Codec                      * Graphics"+        , "  * Data                       * Sound"+        , "  * Math                       * System"+        , "  * Parsing                    * Network"+        , "  * Text"+        , ""+        , "  * Application                * Development"+        , "  * Compilers/Interpreters     * Testing"+        , "  * Web"+        , "  * Game"+        , "  * Utility"+        , ""+        ]      licenseText :: Text     licenseText = "List of licenses to choose from:\n\n"@@ -287,7 +285,7 @@ doGithubCommands :: Settings -> IO () doGithubCommands Settings{..} = do     -- Create git repostitory and do a commit.-    "git" ["init"]+    "git" ["init", "--initial-branch=main"]     "git" ["add", "."]     "git" ["commit", "-m", "Create the project"]     unless settingsNoUpload $ do@@ -297,7 +295,11 @@             Just _ -> do                 isHubSuccess <- runHub repo                 if isHubSuccess-                then "git" ["push", "-u", "origin", "master"]+                then do+                    "git" ["push", "-u", "origin", "main"]+                    "git" ["remote", "set-head", "origin", "-a"]+                    successMessage "Project created:"+                    infoMessage $ "    https://github.com/" <> repo                 else do                     warningMessage "Error running 'hub'. Possible reason: incorrect password."                     hubHelp repo
src/Summoner/Question.hs view
@@ -3,9 +3,12 @@ {-# LANGUAGE ViewPatterns #-}  {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.Question+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  This module contains function to proper questioning in terminal. -}@@ -40,7 +43,6 @@                    warningMessage) import System.Directory (doesPathExist, getCurrentDirectory) import System.FilePath ((</>))-import System.IO (hFlush)  import Summoner.Text (headToUpper, intercalateMap) 
src/Summoner/Settings.hs view
@@ -1,7 +1,10 @@ {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.Settings+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  Complete settings required for the project creation. -}@@ -13,8 +16,6 @@        , showTool        , parseTool        ) where--import Relude.Extra.Enum (inverseMap)  import Summoner.CustomPrelude (CustomPrelude) import Summoner.GhcVer (GhcVer)
src/Summoner/Source.hs view
@@ -1,7 +1,10 @@ {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.Source+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  This module contains the 'Source' data that describes how to fetch custom files. -}@@ -89,7 +92,7 @@ -} fetchSource :: ConnectMode -> Source -> IO (Maybe Text) fetchSource connectMode = \case-    Local path -> catch (Just <$> readFileText path) (localError path)+    Local path -> catch (Just . decodeUtf8 <$> readFileBS path) (localError path)     Url url -> if isOffline connectMode         then Nothing <$ infoMessage ("Ignoring fetching from URL in offline mode from source: " <> url)         else fetchUrl url `catch` urlError url
src/Summoner/Template.hs view
@@ -1,7 +1,10 @@ {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.Template+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  This module contains functions for the Haskell project template creation. -}
src/Summoner/Template/Cabal.hs view
@@ -1,9 +1,10 @@-{-# LANGUAGE QuasiQuotes #-}- {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.Template.Cabal+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  @.cabal@ file template. -}@@ -12,14 +13,14 @@        ( cabalFile        ) where -import NeatInterpolation (text)+import Colourista (indent)  import Summoner.CustomPrelude (CustomPrelude (..))-import Summoner.Default (defaultCabal)+import Summoner.Default (defaultCabalVersion) import Summoner.GhcVer (cabalBaseVersions, showGhcVer) import Summoner.License (LicenseName (..)) import Summoner.Settings (Settings (..))-import Summoner.Text (endLine, intercalateMap, packageToModule)+import Summoner.Text (intercalateMap, packageToModule) import Summoner.Tree (TreeFs (..))  import qualified Data.Text as T@@ -37,17 +38,17 @@         , memptyIfFalse settingsIsLib libraryStanza         , memptyIfFalse settingsIsExe executableStanza         , memptyIfFalse settingsTest  testSuiteStanza-        , memptyIfFalse settingsBench $ benchmarkStanza $ memptyIfFalse settingsIsLib $ ", " <> settingsRepo+        , memptyIfFalse settingsBench benchmarkStanza         ] -    -- TODO: do something to not have empty lines     cabalHeader :: Text     cabalHeader = unlines $-        [ "cabal-version:       " <> defaultCabal+        [ "cabal-version:       " <> defaultCabalVersion         , "name:                " <> settingsRepo         , "version:             0.0.0.0"         , "synopsis:            " <> settingsDescription-        , "description:         " <> settingsDescription ] +++        , "description:"+        ] <> fullDescription <>         [ "homepage:            " <> githubUrl        | settingsGitHub ] ++         [ "bug-reports:         " <> githubBugReports | settingsGitHub ] ++         ( "license:             " <> licenseName) :@@ -62,6 +63,23 @@         , "tested-with:         " <> testedGhcs         ] +    fullDescription :: [Text]+    fullDescription =+        [ "    " <> addDot settingsDescription+        , "    See " <> readme <> " for more details."+        ]+      where+        readme :: Text+        readme = if settingsGitHub+           then "[README.md](" <> githubUrl <> "#" <> settingsRepo <> ")"+           else "README.md"++        addDot :: Text -> Text+        addDot "" = ""+        addDot txt = case T.last txt of+            '.'        -> txt+            _otherChar -> txt <> "."+     githubUrl, githubBugReports :: Text     githubUrl        = "https://github.com/" <> settingsOwner <> "/" <> settingsRepo     githubBugReports = githubUrl <> "/issues"@@ -77,136 +95,145 @@         settingsTestedVersions      sourceRepository :: Text-    sourceRepository =-        [text|-        $endLine-        source-repository head-          type:                git-          location:            ${githubUrl}.git-        |]+    sourceRepository = unlines+        [ ""+        , "source-repository head"+        , "  type:                git"+        , "  location:            " <> githubUrl <> ".git"+        ]      commonStanza :: Text-    commonStanza =-        [text|-        $endLine-        common common-options-          build-depends:       base $baseBounds-          $customPrelude-          $ghcOptions--          default-language:    Haskell2010-    |] <> defaultExtensions+    commonStanza = unlines $+        [ ""+        , "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-            |]+    ghcOptions :: [Text]+    ghcOptions = "" : case settingsGhcOptions of+        []   -> defaultGhcOptions+        x:xs -> "  ghc-options:         " <> x : map (indent 23 <>) xs -    defaultGhcOptions :: Text+    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-        |]+        [ "  ghc-options:         -Wall"+        , "                       -Wcompat"+        , "                       -Widentities"+        , "                       -Wincomplete-uni-patterns"+        , "                       -Wincomplete-record-updates"+        , "                       -Wredundant-constraints"+        , "                       -Wnoncanonical-monad-instances"+        , "  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"+        , "                       -fwrite-ide-info"+        , "                       -hiedir=.hie"+        , "  if impl(ghc >= 8.10)"+        , "    ghc-options:       -Wunused-packages"+        , "  if impl(ghc >= 9.0)"+        , "    ghc-options:       -Winvalid-haddock"+        , "  if impl(ghc >= 9.2)"+        , "    ghc-options:       -Wredundant-bang-patterns"+        , "                       -Woperator-whitespace"+        , "  if impl(ghc >= 9.4  && < 9.10)"+        , "    ghc-options:       -Wforall-identifier"+        , "  if impl(ghc >= 9.4)"+        , "    ghc-options:       -Wredundant-strictness-flags"+        , "  if impl(ghc >= 9.8)"+        , "    ghc-options:       -Wterm-variable-capture"+        , "                       -Winconsistent-flags"+        , "  if impl(ghc >= 9.10)"+        , "    ghc-options:       -Wincomplete-record-selectors"+        , "                       -Wdeprecated-type-abstractions"+        , "                       -Wdata-kinds-tc"+        , "                       -Wdefaulted-exception-context"+        , "  if impl(ghc >= 9.12)"+        , "    ghc-options:       -Wview-pattern-signatures"+        ]      libraryStanza :: Text-    libraryStanza =-        [text|-        $endLine-        library-          import:              common-options-          hs-source-dirs:      src-          exposed-modules:     $libModuleName-        |]+    libraryStanza = unlines+        [ ""+        , "library"+        , "  import:              common-options"+        , "  hs-source-dirs:      src"+        , "  exposed-modules:     " <> libModuleName+        ]      executableStanza :: Text-    executableStanza =-        [text|-        $endLine-        executable $settingsRepo-          import:              common-options-          hs-source-dirs:      app-          main-is:             Main.hs-          $buildDepends-          $rtsOptions-        |]+    executableStanza = unlines $+        [ ""+        , "executable " <> settingsRepo+        , "  import:              common-options"+        , "  hs-source-dirs:      app"+        , "  main-is:             Main.hs"+        ]+        <> buildDepends+        <> rtsOptions      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-          $buildDepends-          $rtsOptions-        |]+    testSuiteStanza = unlines $+        [ ""+        , "test-suite " <> settingsRepo <> "-test"+        , "  import:              common-options"+        , "  type:                exitcode-stdio-1.0"+        , "  hs-source-dirs:      test"+        , "  main-is:             Spec.hs"+        ]+        <> 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:       gauge-                             $commaRepo-          $rtsOptions-          |]+    benchmarkStanza :: Text+    benchmarkStanza = unlines $+        [ ""+        , "benchmark " <> settingsRepo <> "-benchmark"+        , "  import:              common-options"+        , "  type:                exitcode-stdio-1.0"+        , "  hs-source-dirs:      benchmark"+        , "  main-is:             Main.hs"+        ]+        <> buildDepends+        <> rtsOptions      -- | @build-depends@ for the repo, only if the library is on.-    buildDepends :: Text-    buildDepends =-        if settingsIsLib-        then "build-depends:       " <> settingsRepo-        else ""+    buildDepends :: [Text]+    buildDepends = memptyIfFalse settingsIsLib+        ["  build-depends:       " <> settingsRepo] -    rtsOptions :: Text+    rtsOptions :: [Text]     rtsOptions =-        [text|-        ghc-options:         -threaded-                             -rtsopts-                             -with-rtsopts=-N-        |]+        [ "  ghc-options:         -threaded"+        , "                       -rtsopts"+        , "                       -with-rtsopts=-N"+        ] -    customPrelude :: Text+    customPrelude :: [Text]     customPrelude = case settingsPrelude of-        Nothing -> ""+        Nothing -> []         Just CustomPrelude{..} ->-            "                   , " <> cpPackage <> "\n" <>-            [text|-            $endLine-            mixins:              base hiding (Prelude)-                               , $cpPackage ($cpModule as Prelude)-            $endLine-            |]+            [ "                     , " <> cpPackage+            , ""+            , "  mixins:              base hiding (Prelude)"+            , "                     , " <> cpPackage <> " (" <> cpModule <> " as Prelude)"+            ] -    defaultExtensions :: Text+    defaultExtensions :: [Text]     defaultExtensions = case settingsExtensions of-        [] -> ""-        xs -> "  default-extensions:  "-           <> T.intercalate "\n                       " xs-           <> "\n"+        [] -> []+        x:xs ->+             "  default-extensions:  " <> x+           : map (indent 23 <>) xs
src/Summoner/Template/Doc.hs view
@@ -1,7 +1,10 @@ {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.Template.Doc+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  Templates for various documentation files: @@ -79,12 +82,12 @@          travisShield, travisLink, travisBadge :: Text         travisShield = shieldsIo <> "travis/" <> ownerRepo <> ".svg?logo=travis"-        travisLink   = "https://travis-ci.org/" <> ownerRepo+        travisLink   = "https://travis-ci.com/" <> 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"+        appVeyorShield = appVeyorCom <> "api/projects/status/github/" <> ownerRepo <> "?branch=main&svg=true"         appVeyorLink   = appVeyorCom <> "project/" <> ownerRepo         appVeyorBadge  = makeBadge "Windows build status" appVeyorShield appVeyorLink 
src/Summoner/Template/GitHub.hs view
@@ -1,10 +1,12 @@-{-# LANGUAGE QuasiQuotes  #-} {-# LANGUAGE ViewPatterns #-} -{-|-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+{- |+Module                  : Summoner.Template.GitHub+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  This module contains template for GitHub related docs: @@ -21,86 +23,92 @@ -}  module Summoner.Template.GitHub-       ( gitHubFiles-       ) where+    ( gitHubFiles+    ) where +import Colourista (indent) import Data.List (delete, intersect)-import NeatInterpolation (text) -import Summoner.Default (defaultCabal, defaultGHC)+import Summoner.Default (defaultCabal, defaultGHC, defaultStack, ghcActionsCacheVersion,+                         ghcActionsCheckoutVersion, ghcActionsSetupHaskellVersion) import Summoner.GhcVer (GhcVer (..), oldGhcs, showGhcVer) import Summoner.Settings (Settings (..))-import Summoner.Text (endLine, intercalateMap, tconcatMap)+import Summoner.Text (quote) import Summoner.Tree (TreeFs (..))   gitHubFiles :: Settings -> [TreeFs] gitHubFiles Settings{..} = concat     [ [File ".gitignore" (gitignoreDefault <> gitignoreCustom) | settingsGitHub]-    , [Dir ".github" [ Dir "workflows" [ File "ci.yml" ghActionsYml ]] | settingsGhActions ]+    , [ Dir ".github"+          [ Dir "workflows" [ File "ci.yml" ghActionsYml ]+          , File "dependabot.yml" dependabotYml+          ]+      | settingsGhActions+      ]     , [File ".travis.yml" travisYml    | settingsTravis]     , [File "appveyor.yml" appVeyorYml | settingsAppVeyor]     ]   where     -- default .gitignore template     gitignoreDefault :: Text-    gitignoreDefault =-        [text|-        ### 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-        |]+    gitignoreDefault = unlines+        [ "### 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/"+        , ".hie/"+        , "# 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"+        ]      -- additional .gitignore     gitignoreCustom :: Text@@ -109,303 +117,395 @@         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+    ghActionsYml = unlines $+        [ "name: CI"+        , ""+        , "on:"+        , "  pull_request:"+        , "    types: [synchronize, opened, reopened]"+        , "  push:"+        , "    branches: [main]"+        , "  schedule:"+        , "    # additionally run once per week (At 00:00 on Sunday) to maintain cache"+        , "    - cron: '0 0 * * 0'"+        , ""+        , "jobs:" -            - name: Build-              run: |-                $cabalUpdate-                $cabalBuild+        ]+        <> memptyIfFalse settingsCabal ghActionsCabal+        <> memptyIfFalse (settingsCabal && settingsStack) [""]+        <> memptyIfFalse settingsStack ghActionsStack -            - name: Test-              run: |-                ${cabalTest}-        |]+    ghActionsCabal :: [Text]+    ghActionsCabal =+        [ "  cabal:"+        , "    name: ${{ matrix.os }} / ghc ${{ matrix.ghc }}"+        , "    runs-on: ${{ matrix.os }}"+        , "    strategy:"+        , "      matrix:"+        , "        os: [ubuntu-latest, macOS-latest, windows-latest]"+        , "        cabal: [" <> quote defaultCabal <> "]"+        , "        ghc:"+        ]+        <> map (indent 10 <>) ghActionsVersions+        <> ghActionsExcludes+        <>+        [ ""+        , "    steps:"+        , "    - uses: actions/checkout" <> ghcActionsCheckoutVersion+        , ""+        , "    - uses: haskell-actions/setup" <> ghcActionsSetupHaskellVersion+        , "      id: setup-haskell-cabal"+        , "      name: Setup Haskell"+        , "      with:"+        , "        ghc-version: ${{ matrix.ghc }}"+        , "        cabal-version: ${{ matrix.cabal }}"+        , ""+        , "    - name: Configure"+        , "      run: |"+        , "        " <> cabalConfigure+        , ""+        , "    - name: Freeze"+        , "      run: |"+        , "        cabal freeze"+        , ""+        , "    - uses: actions/cache" <> ghcActionsCacheVersion+        , "      name: Cache ~/.cabal/store"+        , "      with:"+        , "        path: ${{ steps.setup-haskell-cabal.outputs.cabal-store }}"+        , "        key: ${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('cabal.project.freeze') }}"+        , ""+        , "    - name: Install dependencies"+        , "      run: |"+        , "        " <> cabalBuild <> " --only-dependencies"+        , ""+        , "    - name: Build"+        , "      run: |"+        , "        " <> cabalBuild+        , ""+        , "    - name: Test"+        , "      run: |"+        , "        " <> cabalTest+        , ""+        , "    - name: Documentation"+        , "      run: |"+        , "        " <> cabalDocumentation+        , ""+        ] +    ghActionsStack :: [Text]+    ghActionsStack =+        [ "  stack:"+        , "    name: stack / ghc ${{ matrix.ghc }}"+        , "    runs-on: ubuntu-latest"+        , "    strategy:"+        , "      matrix:"+        , "        stack: [" <> quote defaultStack <> "]"+        , "        ghc:"+        ]+        <> map (indent 10 <>) ghActionsVersions+        <>+        [ ""+        , "    steps:"+        , "    - uses: actions/checkout" <> ghcActionsCheckoutVersion+        , "      if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/main'"+        , ""+        , "    - uses: haskell-actions/setup" <> ghcActionsSetupHaskellVersion+        , "      name: Setup Haskell Stack"+        , "      with:"+        , "        ghc-version: ${{ matrix.ghc }}"+        , "        stack-version: ${{ matrix.stack }}"+        , ""+        , "    - uses: actions/cache" <> ghcActionsCacheVersion+        , "      name: Cache ~/.stack"+        , "      with:"+        , "        path: ~/.stack"+        , "        key: ${{ runner.os }}-${{ matrix.ghc }}-stack"+        , ""+        , "    - name: Build"+        , "      run: |"+        , "        " <> stackBuild+        , ""+        , "    - name: Test"+        , "      run: |"+        , "        " <> stackTest+        ] -    ghActionsVersions :: Text-    ghActionsVersions = intercalateMap-        "\n"-        (\ghc -> "- " <> ghActionsMatrixItem ghc)+    ghActionsVersions :: [Text]+    ghActionsVersions = map+        (\ghc -> "- " <> quote (showGhcVer ghc))         settingsTestedVersions -    ghActionsMatrixItem :: GhcVer -> Text-    ghActionsMatrixItem v = "\"" <> showGhcVer v <> "\""+    ghActionsExcludes :: [Text]+    ghActionsExcludes =+        let versionsToExclude = -- all but the latest version+                drop 1 $ sortWith Down settingsTestedVersions+            osesToExclude = ["macOS-latest", "windows-latest"]+            excludes = do+                os <- osesToExclude+                version <- versionsToExclude+                [  "- os: " <> os+                 , "  ghc: " <> showGhcVer version+                 ]+        in case excludes of+            [] -> []+            xs ->+                "        exclude:"+                : map (indent 10 <>) xs +    dependabotYml :: Text+    dependabotYml = unlines+        [ "updates:"+        , "  - package-ecosystem: \"github-actions\""+        , "    directory: \"/\""+        , "    schedule:"+        , "      interval: \"daily\""+        , "    commit-message:"+        , "      prefix: \"GA\""+        , "      include: \"scope\""+        , "    labels:"+        , "      - \"CI\""+        , "      - \"dependencies\""+        ]+     -- create travis.yml template     travisYml :: Text-    travisYml =-        [text|-        sudo: true-        language: haskell--        git:-          depth: 5--        cabal: "${defaultCabal}"--        cache:-          directories:-          $travisCabalCache-          $travisStackCache--        matrix:-          include:-          $travisCabalMtr-          $travisStackMtr-          $travisStackAllowFailuresMtr--        $installAndScript--        notifications:-          email: false-        |]+    travisYml = unlines $+        [ "language: haskell"+        , ""+        , "git:"+        , "  depth: 5"+        , ""+        , "cabal: " <> quote defaultCabal+        , ""+        , "cache:"+        , "  directories:"+        ]+        <> travisCabalCache+        <> travisStackCache+        <>+        [ ""+        , "jobs:"+        , "  include:"+        ]+        <> travisCabalMtr+        <> travisStackMtr+        <> travisStackAllowFailuresMtr+        <> installAndScript+        <>+        [ ""+        , "notifications:"+        , "  email: false"+        ] -    travisCabalCache, travisStackCache :: Text-    travisCabalCache = memptyIfFalse settingsCabal "- \"$HOME/.cabal/store\""+    travisCabalCache, travisStackCache :: [Text]+    travisCabalCache = memptyIfFalse settingsCabal ["  - " <> quote "$HOME/.cabal/store"]     travisStackCache = memptyIfFalse settingsStack-        [text|-        - "$$HOME/.stack"-        - "$$TRAVIS_BUILD_DIR/.stack-work"-        |]+        [ "  - " <> quote "$HOME/.stack"+        , "  - " <> quote "$TRAVIS_BUILD_DIR/.stack-work"+        ] -    travisCabalMtr :: Text+    travisCabalMtr :: [Text]     travisCabalMtr = memptyIfFalse settingsCabal $-        tconcatMap travisCabalMatrixItem settingsTestedVersions+        map travisCabalMatrixItem settingsTestedVersions      travisCabalMatrixItem :: GhcVer -> Text-    travisCabalMatrixItem (showGhcVer -> ghcV) = [text|- ghc: $ghcV|]+    travisCabalMatrixItem (showGhcVer -> ghcV) = "  - ghc: " <> ghcV      -- 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 (delete defaultGHC settingsTestedVersions)+    travisStackMtr :: [Text]+    travisStackMtr = memptyIfFalse settingsStack $+        concatMap travisStackMatrixItem (delete defaultGHC settingsTestedVersions)         <> travisStackMatrixDefaultItem -    travisStackAllowFailuresMtr :: Text-    travisStackAllowFailuresMtr = memptyIfFalse (settingsStack && not (null old))-        [text|-        $endLine-        allow_failures:-        $matrix-        |]+    travisStackAllowFailuresMtr :: [Text]+    travisStackAllowFailuresMtr = memptyIfFalse (settingsStack && not (null old)) $+        [ ""+        , "  allow_failures:"+        ]+        <> concatMap travisStackMatrixItem old       where         old :: [GhcVer]         old = settingsTestedVersions `intersect` oldGhcs -        matrix :: Text-        matrix = tconcatMap travisStackMatrixItem old--    travisStackMatrixItem :: GhcVer -> Text+    travisStackMatrixItem :: GhcVer -> [Text]     travisStackMatrixItem (showGhcVer -> ghcV) =-        [text|-        $endLine-        - ghc: ${ghcV}-          env: STACK_YAML="$$TRAVIS_BUILD_DIR/stack-$ghcV.yaml"-        |]+        [ ""+        , "  - ghc: " <> ghcV+        , "    env: STACK_YAML=" <> quote ("$TRAVIS_BUILD_DIR/stack-" <> ghcV <> ".yaml")+        ] -    travisStackMatrixDefaultItem :: Text-    travisStackMatrixDefaultItem = let defGhc = showGhcVer defaultGHC in-        [text|-        $endLine-        - ghc: ${defGhc}-          env: STACK_YAML="$$TRAVIS_BUILD_DIR/stack.yaml"-        |]+    travisStackMatrixDefaultItem :: [Text]+    travisStackMatrixDefaultItem =+        [ ""+        , "  - ghc: " <> showGhcVer defaultGHC+        , "    env: STACK_YAML=" <> quote "$TRAVIS_BUILD_DIR/stack.yaml"+        ] -    installAndScript :: Text+    installAndScript :: [Text]     installAndScript =+        ""+        : "install:"+        : hlintCheck+        <>         if settingsCabal         then if settingsStack              then installScriptBoth              else installScriptCabal         else installScriptStack -    installScriptBoth :: Text+    installScriptBoth :: [Text]     installScriptBoth =-        [text|-        install:-          $hlintCheck--          - |-            if [ -z "$$STACK_YAML" ]; then-              $cabalUpdate-              $cabalBuild-            else-              curl -sSL https://get.haskellstack.org/ | sh-              stack --version-              $stackBuild-            fi--        script:-          - |-            if [ -z "$$STACK_YAML" ]; then-              ${cabalTest}-            else-              $stackTest-            fi-        |]+        [ "  - |"+        , "    if [ -z " <> quote "$STACK_YAML" <> " ]; then"+        , "      " <> cabalUpdate+        , "      " <> cabalConfigure+        , "      " <> cabalBuild+        , "    else"+        , "      curl -sSL https://get.haskellstack.org/ | sh"+        , "      stack --version"+        , "      " <> stackBuild+        , "    fi"+        , ""+        , "script:"+        , "  - |"+        , "    if [ -z " <> quote "$STACK_YAML" <> " ]; then"+        , "      " <> cabalTest+        , "    else"+        , "      " <> stackTest+        , "    fi"+        ] -    installScriptCabal :: Text+    installScriptCabal :: [Text]     installScriptCabal =-        [text|-        install:-          $hlintCheck--          - $cabalUpdate-          - $cabalBuild--        script:-          - ${cabalTest}-        |]+        [ "  - " <> cabalUpdate+        , "  - " <> cabalConfigure+        , "  - " <> cabalBuild+        , ""+        , "script:"+        , "  - " <> cabalTest+        ] -    installScriptStack :: Text+    installScriptStack :: [Text]     installScriptStack =-        [text|-        install:-          $hlintCheck--          - curl -sSL https://get.haskellstack.org/ | sh-          - stack --version-          - $stackBuild--        script:-          - $stackTest-        |]+        [ "  - curl -sSL https://get.haskellstack.org/ | sh"+        , "  - stack --version"+        , "  - " <> stackBuild+        , ""+        , "script:"+        , "  - " <> stackTest+        ]      cabalUpdate :: Text-    cabalUpdate = "cabal v2-update"+    cabalUpdate = "cabal update" +    cabalConfigure :: Text+    cabalConfigure = "cabal configure --enable-tests --enable-benchmarks --enable-documentation --test-show-details=direct --write-ghc-environment-files=always"+     cabalBuild :: Text-    cabalBuild = "cabal v2-build --enable-tests --enable-benchmarks"+    cabalBuild = "cabal build all"      cabalTest :: Text-    cabalTest = if settingsTest-        then "cabal v2-test --enable-tests"-        else "echo 'No tests'"+    cabalTest = "cabal test all" +    cabalDocumentation :: Text+    cabalDocumentation = "cabal haddock"+     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]     hlintCheck =-        [text|-        # HLint check-        - curl -sSL https://raw.github.com/ndmitchell/neil/master/misc/travis.sh | sh -s -- hlint .-        |]+        [ "  # HLint check"+        , "  - curl -sSL https://raw.github.com/ndmitchell/neil/master/misc/travis.sh | sh -s -- hlint ."+        , ""+        ]      appVeyorYml :: Text-    appVeyorYml =+    appVeyorYml = unlines $         if settingsCabal         then appVeyorYmlCabal         else appVeyorYmlStack -    appVeyorYmlCabal :: Text-    appVeyorYmlCabal = let defGhc = showGhcVer defaultGHC in-        [text|-        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: $defGhc--        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 $defGhc-          - refreshenv--        before_build:-          - cabal --version-          - ghc   --version-          - cabal %CABOPTS% v2-update+    appVeyorYmlCommon :: [Text]+    appVeyorYmlCommon =+        [ "clone_depth: 5"+        , ""+        , "# Do not build feature branch with open Pull Requests"+        , "skip_branch_with_pr: true"+        , ""+        , "# build only main branch"+        , "branches:"+        , "  only:"+        , "    - main"+        , ""+        ] -        build_script:-          - cabal %CABOPTS% v2-build --enable-tests-          - cabal %CABOPTS% v2-test  --enable-tests-        |]+    appVeyorYmlCabal :: [Text]+    appVeyorYmlCabal = let defGhc = showGhcVer defaultGHC in+        ( "clone_folder: " <> quote "c:\\\\WORK" )+        : appVeyorYmlCommon +++        [ "platform:"+        , "  - x86_64"+        , ""+        , "cache:"+        , "  - " <> quote "C:\\\\SR"+        , "  - dist-newstyle"+        , ""+        , "environment:"+        , "  global:"+        , "    CABOPTS: --store-dir=C:\\\\SR"+        , ""+        , "  matrix:"+        , "    - GHCVER: " <> defGhc+        , ""+        , "install:"+        , "  - choco source add -n mistuke -s https://www.myget.org/F/mistuke/api/v2"+        , "  - choco install -y cabal --version 3.6.2.0"+        , "  - choco install -y ghc   --version " <> defGhc+        , "  - refreshenv"+        , ""+        , "before_build:"+        , "  - cabal --version"+        , "  - ghc   --version"+        , "  - cabal %CABOPTS% update"+        , ""+        , "build_script:"+        , "  - cabal %CABOPTS% configure --enable-tests --enable-benchmarks --enable-documentation --test-show-details=direct --write-ghc-environment-files=always"+        , "  - cabal %CABOPTS% build all"+        , "  - cabal %CABOPTS% test  all"+        ]      -- create appveyor.yml template-    appVeyorYmlStack :: Text-    appVeyorYmlStack =-        [text|-        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-        |]+    appVeyorYmlStack :: [Text]+    appVeyorYmlStack = appVeyorYmlCommon +++        [ "environment:"+        , "  STACK_ROOT: C:\\sr"+        , "  STACK_VERSION: " <> defaultStack+        , ""+        , "  # 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: " <> quote "c:\\\\tmp"+        , ""+        , "  matrix:"+        , "    - STACK_YAML: stack.yaml"+        , ""+        , "cache:"+        , "  - " <> quote "%STACK_ROOT% -> %STACK_YAML%, appveyor.yml"+        , "  - " <> quote ".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"+        ]
src/Summoner/Template/Haskell.hs view
@@ -1,9 +1,10 @@-{-# LANGUAGE QuasiQuotes #-}- {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.Template.Haskell+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  Templates for generated Haskell source code files. -}@@ -12,10 +13,8 @@        ( haskellFiles        ) where -import NeatInterpolation (text)- import Summoner.Settings (Settings (..))-import Summoner.Text (packageToModule)+import Summoner.Text (packageToModule, quote) import Summoner.Tree (TreeFs (..))  @@ -28,24 +27,23 @@     ]   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)-        |]+    libFile = File (toString libModuleName <> ".hs") $ unlines+        [ "{- |"+        , "Copyright: (c) " <> settingsYear <> " " <> settingsFullName+        , "SPDX-License-Identifier: " <> licenseName+        , "Maintainer: " <> settingsFullName <> " <" <> settingsEmail <> ">"+        , ""+        , settingsDescription+        , "-}"+        , ""+        , "module " <> libModuleName+        , "    ( projectName"+        , "    ) where"+        , ""+        , ""+        , "projectName :: String"+        , "projectName = " <> quote settingsRepo+        ]      libModuleName :: Text     libModuleName = packageToModule settingsRepo@@ -54,48 +52,29 @@     licenseName = show settingsLicenseName      exeFile :: TreeFs-    exeFile = File "Main.hs" $ if settingsIsLib then createExe else createOnlyExe--    createOnlyExe :: Text-    createOnlyExe =-        [text|-        module Main (main) where---        main :: IO ()-        main = putStrLn ("Hello, world!" :: String)-        |]--    createExe :: Text-    createExe =-        [text|-        module Main (main) where--        import $libModuleName (someFunc)---        main :: IO ()-        main = someFunc-        |]+    exeFile = File "Main.hs" $ stanza "Executable"      testFile :: TreeFs-    testFile = File "Spec.hs"-        [text|-        module Main (main) where---        main :: IO ()-        main = putStrLn ("Test suite is not implemented" :: String)-        |]+    testFile = File "Spec.hs" $ stanza "Tests"      benchmarkFile :: TreeFs-    benchmarkFile = File "Main.hs"-        [text|-        module Main (main) where--        import Gauge.Main-+    benchmarkFile = File "Main.hs" $ stanza "Benchmarks" -        main :: IO ()-        main = defaultMain [bench "const" (whnf const ())]-        |]+    stanza :: Text -> Text+    stanza st = unlines $+          "module Main (main) where"+        : memptyIfFalse settingsIsLib+            [ ""+            , "import " <> libModuleName <> " (projectName)"+            ]+        <>+        [ ""+        , ""+        , "main :: IO ()"+        , mainContent+        ]+      where+        mainContent :: Text+        mainContent = if settingsIsLib+            then "main = putStrLn (" <> quote (st <> " for ") <> " ++ projectName)"+            else "main = putStrLn (" <> quote (st <> " not implemented") <> " :: String)"
src/Summoner/Template/Script.hs view
@@ -1,9 +1,10 @@-{-# LANGUAGE QuasiQuotes #-}- {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.Template.Script+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  File templates for @cabal@ and @stack@ scripts. -}@@ -12,38 +13,35 @@        ( scriptFile        ) where -import NeatInterpolation (text)- import Summoner.GhcVer (GhcVer, baseVer, latestLts) import Summoner.Settings (Tool (..))+import Summoner.Text (quote)   -- | 'Text' content for a single script file. scriptFile :: GhcVer -> Tool -> Text scriptFile ghcVer = \case-    Cabal ->-        [text|-        #!/usr/bin/env cabal-        {- cabal:-        build-depends:-          , base ^>= $baseVersion-        -}--        main :: IO ()-        main = putStrLn "Hello, World!"-        |]-    Stack ->-        [text|-        #!/usr/bin/env stack-        {- stack-          --resolver ${ltsVersion}-          script-          --package base-        -}--        main :: IO ()-        main = putStrLn "Hello, World!"-        |]+    Cabal -> unlines+        [ "#!/usr/bin/env cabal"+        , "{- cabal:"+        , "build-depends:"+        , "  , base ^>= " <> baseVersion+        , "-}"+        , ""+        , "main :: IO ()"+        , "main = putStrLn " <> quote "Hello, World!"+        ]+    Stack -> unlines+        [ "#!/usr/bin/env stack"+        , "{- stack"+        , "  --resolver " <> ltsVersion+        , "  script"+        , "  --package base"+        , "-}"+        , ""+        , "main :: IO ()"+        , "main = putStrLn " <> quote "Hello, World!"+        ]   where     baseVersion, ltsVersion :: Text     baseVersion = baseVer ghcVer
src/Summoner/Template/Stack.hs view
@@ -1,7 +1,10 @@ {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.Template.Stack+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  Templates for @stack.yaml@ files. -}
src/Summoner/Text.hs view
@@ -1,29 +1,27 @@ {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.Text+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  Various helpful functions to work with 'Text' -}  module Summoner.Text-       ( endLine-       , packageToModule+       ( packageToModule        , packageNameValid        , moduleNameValid        , intercalateMap        , headToUpper-       , tconcatMap+       , quote        ) where  import qualified Data.Char as C import qualified Data.Text as T  --- | Endline symbol to use with @neat-interpolation@.-endLine :: Text-endLine = "\n"- -- | Creates module name from the name of the package -- Ex: @my-lovely-project@ — @MyLovelyProject@ packageToModule :: Text -> Text@@ -63,3 +61,7 @@ -- | Convert every element of a list into text, and squash the results tconcatMap :: (a -> Text) -> [a] -> Text tconcatMap f = T.concat . map f++-- | Wrap the given text into quotes.+quote :: Text -> Text+quote t = "\"" <> t <> "\""
src/Summoner/Tree.hs view
@@ -1,23 +1,26 @@ {-# LANGUAGE ViewPatterns #-}  {- |-Copyright: (c) 2017-2019 Kowainik-SPDX-License-Identifier: MPL-2.0-Maintainer: Kowainik <xrom.xkov@gmail.com>+Module                  : Summoner.Tree+Copyright               : (c) 2017-2026 Kowainik+SPDX-License-Identifier : MPL-2.0+Maintainer              : Kowainik <xrom.xkov@gmail.com>+Stability               : Stable+Portability             : Portable  Data type for representing filesystem structure via tree. -}  module Summoner.Tree-       ( TreeFs (..)-       , traverseTree-       , pathToTree-       , insertTree-       , showBoldTree-       , showTree-       ) where+    ( TreeFs (..)+    , traverseTree+    , pathToTree+    , insertTree+    , showBoldTree+    , showTree+    ) where -import Colourista (bold, reset)+import Colourista.Short (b) import System.Directory (createDirectoryIfMissing, withCurrentDirectory) import System.FilePath (splitDirectories) @@ -25,9 +28,9 @@ -- | Describes simple structure of filesystem tree. data TreeFs       -- | Name of directory (relative) and its containing entries-    = Dir FilePath [TreeFs]+    = Dir !FilePath ![TreeFs]       -- | File name (relative) and file content-    | File FilePath Text+    | File !FilePath !Text     deriving stock (Generic, Show, Eq, Ord)  -- | Walks through directory tree and write file contents, creating all@@ -100,10 +103,7 @@         nodeRep = leader <> arm <> tie <> boldDir (fp <> "/")           where             boldDir :: FilePath -> Text-            boldDir str = toText $-                if isBold-                then bold <> str <> reset-                else str+            boldDir str = toText $ if isBold then b str else str          extension :: Text         extension = case arm of ""  -> ""; "└" -> "    "; _   -> "│   "
summoner.cabal view
@@ -1,6 +1,6 @@-cabal-version:       2.4+cabal-version:       3.4 name:                summoner-version:             2.0.1.1+version:             2.1.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.@@ -10,7 +10,7 @@ license-file:        LICENSE author:              Veronika Romashkina, Dmitrii Kovanikov maintainer:          Kowainik <xrom.xkov@gmail.com>-copyright:           2018-2020 Kowainik+copyright:           2018-2026 Kowainik category:            CLI, CLI Tool, Development build-type:          Simple stability:           stable@@ -18,8 +18,15 @@                      CHANGELOG.md tested-with:         GHC == 8.4.4                      GHC == 8.6.5-                     GHC == 8.8.3-                     GHC == 8.10.1+                     GHC == 8.8.4+                     GHC == 8.10.7+                     GHC == 9.0.2+                     GHC == 9.2.8+                     GHC == 9.4.7+                     GHC == 9.6.7+                     GHC == 9.8.4+                     GHC == 9.10.3+                     GHC == 9.12.3 extra-source-files:     examples/summoner-default.toml @@ -72,31 +79,49 @@   location: git@github.com:kowainik/summoner.git  common common-options-  build-depends:       base >= 4.11 && < 4.15-                     , relude ^>= 0.7.0.0+  build-depends:       base >= 4.11 && < 4.22+                     , relude >= 1.0.0.0 && < 1.3    mixins:              base hiding (Prelude)-                     , relude (Relude as Prelude-                              , Relude.Extra.Enum-                              )+                     , relude (Relude as Prelude)+                     , relude    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+                       -Wredundant-constraints+                       -Wnoncanonical-monad-instances+                       -fhide-source-paths+                       -Wmissing-export-lists                        -Wpartial-fields   if impl(ghc >= 8.8)     ghc-options:       -Wmissing-deriving-strategies                        -Werror=missing-deriving-strategies+                       -fwrite-ide-info+                       -hiedir=../.hie   if impl(ghc >= 8.10)     ghc-options:       -Wunused-packages+  if impl(ghc >= 9.0)+    ghc-options:       -Winvalid-haddock+  if impl(ghc >= 9.2)+    ghc-options:       -Wredundant-bang-patterns+                       -Woperator-whitespace+  if impl(ghc >= 9.4  && < 9.10)+    ghc-options:       -Wforall-identifier+  if impl(ghc >= 9.4)+    ghc-options:       -Wredundant-strictness-flags+  if impl(ghc >= 9.8)+    ghc-options:       -Wterm-variable-capture+                       -Winconsistent-flags+  if impl(ghc >= 9.10)+    ghc-options:       -Wincomplete-record-selectors+                       -Wdeprecated-type-abstractions+                       -Wdata-kinds-tc+                       -Wdefaulted-exception-context+  if impl(ghc >= 9.12)+    ghc-options:       -Wview-pattern-signatures    default-extensions:  DeriveGeneric                        DerivingStrategies@@ -110,6 +135,11 @@    default-language:    Haskell2010 +common exe-options+  ghc-options:         -threaded+                       -rtsopts+                       -with-rtsopts=-N+ library   import:              common-options   hs-source-dirs:      src@@ -120,6 +150,7 @@                          Summoner.Decision                          Summoner.Default                          Summoner.GhcVer+                         Summoner.Golden                          Summoner.License                          Summoner.Mode                          Summoner.Project@@ -139,34 +170,34 @@   autogen-modules:     Paths_summoner   other-modules:       Paths_summoner -  build-depends:       aeson >= 1.2.4.0 && < 1.6-                     , colourista ^>= 0.1-                     , containers ^>= 0.6+  build-depends:       colourista ^>= 0.1.0.1                      , directory ^>= 1.3.0.2-                     , filepath ^>= 1.4.1.2-                     , generic-data ^>= 0.8.0.0+                     , filepath >= 1.4.1.2 && < 1.6+                     , generic-data >= 0.8.0.0 && < 1.2                      , gitrev ^>= 1.3.1-                     , neat-interpolation ^>= 0.3.2.2-                     , optparse-applicative ^>= 0.15+                     , microaeson ^>= 0.1.0.0+                     , optparse-applicative >= 0.16 && < 0.20                      , process ^>= 1.6.1.0-                     , shellmet ^>= 0.0.3.0-                     , text ^>= 1.2.3.0-                     , time >= 1.8 && < 1.11+                     , shellmet >= 0.0.3.0 && < 0.0.7+                     , time >= 1.8 && < 1.16                      , tomland ^>= 1.3.0.0-                     , validation-selective >= 0.0.0.0 && < 0.2+                     , validation-selective >= 0.1.0.0 && < 0.3  executable summon-  import:              common-options+  import:              common-options, exe-options   hs-source-dirs:      app   main-is:             Cli.hs   build-depends:       summoner -  ghc-options:         -threaded-                       -rtsopts-                       -with-rtsopts=-N+executable gg+  import:              common-options, exe-options+  hs-source-dirs:      golden+  main-is:             Main.hs+  build-depends:       summoner + test-suite summoner-test-  import:              common-options+  import:              common-options, exe-options   type:                exitcode-stdio-1.0   hs-source-dirs:      test @@ -181,16 +212,10 @@    build-depends:       directory                      , filepath-                     , hedgehog >= 0.5.3 && < 1.1+                     , hedgehog >= 0.5.3 && < 1.8                      , hspec >= 2.4.8-                     , hspec-hedgehog ^>= 0.0.1.1-                     , neat-interpolation-                     , text+                     , hspec-hedgehog >= 0.0.1.1 && < 0.4                      , tomland-                     , tree-diff >= 0.0.2 && < 0.2+                     , tree-diff >= 0.0.2 && < 0.4                      , summoner                      , validation-selective--  ghc-options:         -threaded-                       -rtsopts-                       -with-rtsopts=-N
test/Test/Golden.hs view
@@ -1,7 +1,5 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} -{-# LANGUAGE QuasiQuotes #-}- {- | Golden tests for @summoner@.  In the @test/golden@ folder we now have two projects that are created by@@ -20,17 +18,18 @@        ) where  import Data.TreeDiff (ToExpr, ansiWlEditExprCompact, ediff)-import NeatInterpolation (text) import System.Directory (doesDirectoryExist, listDirectory) import System.FilePath (takeFileName, (</>)) import Test.Hspec (Spec, describe, expectationFailure, it) -import Summoner (CustomPrelude (..), GhcVer (..), License (..), LicenseName (..), Settings (..),-                 defaultGHC)+import Summoner (Settings)+import Summoner.Golden (cabalFull, cabalMinimal, fullBatteries, stackFull) import Summoner.Template (createProjectTemplate) import Summoner.Tree (TreeFs (..)) +import qualified Data.Text as T + goldenSpec :: Spec goldenSpec = describe "golden tests" $ do     it "correctly scaffolds the 'cabal-minimal' project" $@@ -56,201 +55,14 @@         dirs <- listDirectory filePath         Dir (takeFileName filePath) <$> traverse (\dir -> readTreeFs $ filePath </> dir) dirs     False -> do-        content <- readFileText filePath+        -- Normalize line endings (CRLF -> LF) for cross-platform compatibility+        content <- T.filter (/= '\r') . decodeUtf8 <$> readFileBS filePath         pure $ File (takeFileName filePath) content  sortTree :: TreeFs -> TreeFs sortTree = \case     file@(File _ _) -> file-    Dir path fs -> Dir path $ sort $ map sortTree fs---fullBatteries :: Settings-fullBatteries = Settings-    { settingsRepo           = "full-batteries"-    , settingsOwner          = "kowainik"-    , settingsDescription    = "Full-featured test project"-    , settingsFullName       = "Kowainik"-    , settingsEmail          = "xrom.xkov@gmail.com"-    , settingsYear           = "2020"-    , settingsCategories     = "Testing"-    , settingsLicenseName    = MIT-    , settingsLicenseText    = mitLicense-    , settingsGitHub         = True-    , settingsGhActions      = True-    , settingsPrivate        = True-    , settingsTravis         = True-    , settingsAppVeyor       = True-    , settingsIsLib          = True-    , settingsIsExe          = True-    , settingsTest           = True-    , settingsBench          = True-    , settingsTestedVersions = [Ghc802 .. defaultGHC]-    , settingsPrelude        = Just $ CustomPrelude "relude" "Relude"-    , settingsExtensions     = ["ConstraintKinds", "LambdaCase", "OverloadedStrings"]-    , settingsGitignore      = [".secret"]-    , settingsGhcOptions     = ["-Wcompat", "-Widentities"]-    , settingsCabal          = True-    , settingsStack          = True-    , 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--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.-|]--stackFull :: Settings-stackFull = Settings-    { settingsRepo           = "stack-full"-    , settingsOwner          = "kowainik"-    , settingsDescription    = "Stack-only example with all integrations"-    , settingsFullName       = "Kowainik"-    , settingsEmail          = "xrom.xkov@gmail.com"-    , 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-    , settingsLicenseText    = ""-    , settingsGitHub         = False-    , settingsGhActions      = False-    , settingsPrivate        = False-    , settingsTravis         = False-    , settingsAppVeyor       = False-    , settingsIsLib          = False-    , settingsIsExe          = True-    , settingsTest           = False-    , settingsBench          = False-    , settingsTestedVersions = [defaultGHC]-    , settingsPrelude        = Nothing-    , settingsExtensions     = []-    , settingsGhcOptions     = []-    , settingsGitignore      = []-    , settingsCabal          = True-    , settingsStack          = False-    , 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.-|]+    Dir path fs     -> Dir path $ sort $ map sortTree fs  -- Orphan instances 
test/Test/Script.hs view
@@ -1,45 +1,22 @@-{-# LANGUAGE QuasiQuotes #-}- module Test.Script-       ( scriptSpec-       ) where+    ( scriptSpec+    ) where -import NeatInterpolation (text)-import Test.Hspec (Spec, describe, it, shouldBe)+import Test.Hspec (Spec, describe, it, shouldReturn) -import Summoner.GhcVer (GhcVer (..))+import Summoner.Default (defaultGHC) import Summoner.Settings (Tool (..)) import Summoner.Template.Script (scriptFile) +import qualified Data.Text as T  scriptSpec :: Spec scriptSpec = describe "script golden tests" $ do     it "correctly creates cabal script" $-        scriptFile Ghc844 Cabal `shouldBe` cabalScript+        readScript "examples/cabalScript.hs" `shouldReturn` scriptFile defaultGHC Cabal     it "correctly creates stack script" $-        scriptFile Ghc865 Stack `shouldBe` stackScript--cabalScript :: Text-cabalScript = [text|-#!/usr/bin/env cabal-{- cabal:-build-depends:-  , base ^>= 4.11.1.0--}--main :: IO ()-main = putStrLn "Hello, World!"-|]--stackScript :: Text-stackScript = [text|-#!/usr/bin/env stack-{- stack-  --resolver lts-14.27-  script-  --package base--}+        readScript "examples/stackScript.hs" `shouldReturn` scriptFile defaultGHC Stack -main :: IO ()-main = putStrLn "Hello, World!"-|]+-- | Read a script file, normalizing line endings (CRLF -> LF) for cross-platform compatibility+readScript :: FilePath -> IO Text+readScript path = T.filter (/= '\r') . decodeUtf8 <$> readFileBS path
test/Test/Show.hs view
@@ -14,10 +14,17 @@  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.27"-  , "GHC-8.8.3     base-4.13.0.0   lts-15.5"-  ]+    [ "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.4     base-4.13.0.0   lts-16.31"+    , "GHC-8.10.7    base-4.14.3.0   lts-18.28"+    , "GHC-9.0.2     base-4.15.1.0   lts-19.33"+    , "GHC-9.2.8     base-4.16.4.0   lts-20.26"+    , "GHC-9.4.8     base-4.17.2.1   lts-21.25"+    , "GHC-9.6.7     base-4.18.3.1   lts-22.44"+    , "GHC-9.8.4     base-4.19.2.0   lts-23.28"+    , "GHC-9.10.3    base-4.20.2.0   lts-24.26"+    , "GHC-9.12.3    base-4.21.1.0   nightly-2026-01-04"+    ]
test/Test/TomlSpec.hs view
@@ -3,11 +3,10 @@        ) where  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.Codec.Code (decode, encode)-import Validation (Validation (..))+import Validation (isSuccess)  import Summoner.Config (ConfigP (..), PartialConfig, configCodec, defaultConfig, finalise) import Summoner.CustomPrelude (CustomPrelude (..))@@ -34,11 +33,9 @@     it "parses default configuration" $         decode configCodec defaultConfigFileContent `shouldSatisfy` isRight     it "default configuration is up-to-date" $-        readFileText "examples/summoner-default.toml"+        -- Normalize line endings (CRLF -> LF) for cross-platform compatibility+        T.filter (/= '\r') . decodeUtf8 <$> readFileBS "examples/summoner-default.toml"             `shouldReturn` defaultConfigFileContent-  where-    isSuccess :: Validation e a -> Bool-    isSuccess = \case { Success _ -> True; _ -> False }  tomlProp :: Spec tomlProp = describe "TOML property tests" $