├── .github └── workflows │ └── main.yml ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── Setup.hs ├── package.yaml ├── src └── Main.hs ├── stack-templatizer.cabal ├── stack.yaml └── stack.yaml.lock /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # yamllint disable rule:line-length 3 | 4 | name: CI Build 5 | 6 | # yamllint disable-line rule:truthy 7 | on: 8 | # Run Daily 9 | schedule: 10 | - cron: '0 0 * * *' 11 | # Run on Push 12 | push: 13 | # Run on Tag Creation 14 | create: 15 | # Allow Running Manually 16 | workflow_dispatch: 17 | 18 | jobs: 19 | build-stack: 20 | name: Stack 21 | runs-on: ubuntu-latest 22 | steps: 23 | - uses: actions/checkout@v3 24 | - name: Cache Stack Artifacts 25 | uses: actions/cache@v2 26 | with: 27 | key: stack-build-lts-${{ github.ref }}-${{ github.sha }} 28 | path: | 29 | ~/.stack/ 30 | .stack-work/ 31 | restore-keys: | 32 | stack-build-lts-${{ github.ref }}- 33 | stack-build-lts- 34 | stack-build- 35 | - uses: haskell/actions/setup@v2 36 | with: 37 | enable-stack: true 38 | stack-no-global: true 39 | - run: stack test --fast --haddock --pedantic --resolver lts-20 40 | 41 | # Stackage Nightly - Failures Allowed 42 | build-nightly: 43 | name: Stackage Nightly 44 | runs-on: ubuntu-latest 45 | steps: 46 | - uses: actions/checkout@v3 47 | - name: Get Current Date 48 | id: date 49 | run: echo -e "::set-output name=year::$(date +%Y)\n::set-output name=month::$(date +%m)\n::set-output name=day::$(date +%d)" 50 | - name: Cache Stack Artifacts 51 | uses: actions/cache@v2 52 | with: 53 | key: stack-build-nightly-${{ steps.date.outputs.year }}-${{ steps.date.outputs.month }}-${{ steps.date.outputs.day }}-${{ github.ref }}-${{ github.sha }} 54 | path: | 55 | ~/.stack/ 56 | .stack-work/ 57 | restore-keys: | 58 | stack-build-nightly-${{ steps.date.outputs.year }}-${{ steps.date.outputs.month }}-${{ steps.date.outputs.day }}-${{ github.ref }}- 59 | stack-build-nightly-${{ steps.date.outputs.year }}-${{ steps.date.outputs.month }}-${{ steps.date.outputs.day }}- 60 | stack-build-nightly-${{ steps.date.outputs.year }}-${{ steps.date.outputs.month }}- 61 | stack-build-nightly-${{ steps.date.outputs.year }}- 62 | stack-build-nightly- 63 | - uses: haskell/actions/setup@v2 64 | with: 65 | enable-stack: true 66 | stack-no-global: true 67 | - run: stack test --fast --haddock --pedantic --resolver nightly 68 | continue-on-error: true 69 | 70 | # Cabal Builds w/ 3 Latest GHC Versions 71 | build-cabal: 72 | name: GHC / Cabal 73 | runs-on: ubuntu-latest 74 | strategy: 75 | matrix: 76 | ghc: ['8.10', '9.0', '9.2'] 77 | steps: 78 | - uses: actions/checkout@v3 79 | - name: Cache Cabal Artifacts 80 | uses: actions/cache@v2 81 | with: 82 | key: cabal-build-${{ matrix.ghc }}-${{ github.ref }}-${{ github.sha }} 83 | path: | 84 | ~/.cabal/packages/ 85 | ~/.cabal/store 86 | dist-newstyle/ 87 | restore-keys: | 88 | cabal-build-${{ matrix.ghc }}-${{ github.ref }}- 89 | cabal-build-${{ matrix.ghc }}- 90 | cabal-build- 91 | - uses: haskell/actions/setup@v2 92 | with: 93 | ghc-version: ${{ matrix.ghc }} 94 | cabal-version: latest 95 | enable-stack: true 96 | - run: cabal update 97 | - run: cabal new-test --enable-tests && cabal new-haddock 98 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # This is the complex Travis configuration, which is intended for use 2 | # on open source libraries which need compatibility across multiple GHC 3 | # versions, must work with cabal-install, and should be 4 | # cross-platform. For more information and other options, see: 5 | # 6 | # https://docs.haskellstack.org/en/stable/travis_ci/ 7 | # 8 | # Copy these contents into the root directory of your Github project in a file 9 | # named .travis.yml 10 | 11 | # Run jobs on Linux unless "os" is specified explicitly. 12 | os: linux 13 | 14 | # Do not choose a language; we provide our own build tools. 15 | language: generic 16 | 17 | # Caching so the next build will be fast too. 18 | cache: 19 | directories: 20 | - $HOME/.ghc 21 | - $HOME/.cabal 22 | - $HOME/.stack 23 | - $TRAVIS_BUILD_DIR/.stack-work 24 | 25 | # The different configurations we want to test. We have BUILD=cabal which uses 26 | # cabal-install, and BUILD=stack which uses Stack. More documentation on each 27 | # of those below. 28 | # 29 | # We set the compiler values here to tell Travis to use a different 30 | # cache file per set of arguments. 31 | # 32 | # If you need to have different apt packages for each combination in the 33 | # job matrix, you can use a line such as: 34 | # addons: {apt: {packages: [libfcgi-dev,libgmp-dev]}} 35 | jobs: 36 | include: 37 | # We grab the appropriate GHC and cabal-install versions from hvr's PPA. See: 38 | # https://github.com/hvr/multi-ghc-travis 39 | #- env: BUILD=cabal GHCVER=7.0.4 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7 40 | # compiler: ": #GHC 7.0.4" 41 | # addons: {apt: {packages: [cabal-install-1.16,ghc-7.0.4,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 42 | #- env: BUILD=cabal GHCVER=7.2.2 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7 43 | # compiler: ": #GHC 7.2.2" 44 | # addons: {apt: {packages: [cabal-install-1.16,ghc-7.2.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 45 | #- env: BUILD=cabal GHCVER=7.4.2 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7 46 | # compiler: ": #GHC 7.4.2" 47 | # addons: {apt: {packages: [cabal-install-1.16,ghc-7.4.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 48 | #- env: BUILD=cabal GHCVER=7.6.3 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7 49 | # compiler: ": #GHC 7.6.3" 50 | # addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 51 | #- env: BUILD=cabal GHCVER=7.8.4 CABALVER=1.18 HAPPYVER=1.19.5 ALEXVER=3.1.7 52 | # compiler: ": #GHC 7.8.4" 53 | # addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 54 | #- env: BUILD=cabal GHCVER=7.10.3 CABALVER=1.22 HAPPYVER=1.19.5 ALEXVER=3.1.7 55 | # compiler: ": #GHC 7.10.3" 56 | # addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 57 | #- env: BUILD=cabal GHCVER=8.0.2 CABALVER=1.24 HAPPYVER=1.19.5 ALEXVER=3.1.7 58 | # compiler: ": #GHC 8.0.2" 59 | # addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 60 | #- env: BUILD=cabal GHCVER=8.2.2 CABALVER=2.0 HAPPYVER=1.19.5 ALEXVER=3.1.7 61 | # compiler: ": #GHC 8.2.2" 62 | # addons: {apt: {packages: [cabal-install-2.0,ghc-8.2.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 63 | - env: BUILD=cabal GHCVER=8.4.4 CABALVER=2.2 HAPPYVER=1.19.5 ALEXVER=3.1.7 64 | compiler: ": #GHC 8.4.4" 65 | addons: {apt: {packages: [cabal-install-2.2,ghc-8.4.4,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 66 | - env: BUILD=cabal GHCVER=8.6.5 CABALVER=2.4 HAPPYVER=1.19.5 ALEXVER=3.1.7 67 | compiler: ": #GHC 8.6.5" 68 | addons: {apt: {packages: [cabal-install-2.4,ghc-8.6.5,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 69 | 70 | # Build with the newest GHC and cabal-install. This is an accepted failure, 71 | # see below. 72 | - env: BUILD=cabal GHCVER=head CABALVER=head HAPPYVER=1.19.5 ALEXVER=3.1.7 73 | compiler: ": #GHC HEAD" 74 | addons: {apt: {packages: [cabal-install-head,ghc-head,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 75 | 76 | # The Stack builds. We can pass in arbitrary Stack arguments via the ARGS 77 | # variable, such as using --stack-yaml to point to a different file. 78 | - env: BUILD=stack ARGS="" 79 | compiler: ": #stack default" 80 | addons: {apt: {packages: [libgmp-dev]}} 81 | 82 | #- env: BUILD=stack ARGS="--resolver lts-2" 83 | # compiler: ": #stack 7.8.4" 84 | # addons: {apt: {packages: [libgmp-dev]}} 85 | 86 | #- env: BUILD=stack ARGS="--resolver lts-3" 87 | # compiler: ": #stack 7.10.2" 88 | # addons: {apt: {packages: [libgmp-dev]}} 89 | 90 | #- env: BUILD=stack ARGS="--resolver lts-6" 91 | # compiler: ": #stack 7.10.3" 92 | # addons: {apt: {packages: [libgmp-dev]}} 93 | 94 | #- env: BUILD=stack ARGS="--resolver lts-7" 95 | # compiler: ": #stack 8.0.1" 96 | # addons: {apt: {packages: [libgmp-dev]}} 97 | 98 | #- env: BUILD=stack ARGS="--resolver lts-9" 99 | # compiler: ": #stack 8.0.2" 100 | # addons: {apt: {packages: [libgmp-dev]}} 101 | 102 | #- env: BUILD=stack ARGS="--resolver lts-11" 103 | # compiler: ": #stack 8.2.2" 104 | # addons: {apt: {packages: [libgmp-dev]}} 105 | 106 | - env: BUILD=stack ARGS="--resolver lts-12" 107 | compiler: ": #stack 8.4.4" 108 | addons: {apt: {packages: [libgmp-dev]}} 109 | 110 | - env: BUILD=stack ARGS="--resolver lts-14" 111 | compiler: ": #stack 8.6.5" 112 | addons: {apt: {packages: [libgmp-dev]}} 113 | 114 | # Nightly builds are allowed to fail 115 | - env: BUILD=stack ARGS="--resolver nightly" 116 | compiler: ": #stack nightly" 117 | addons: {apt: {packages: [libgmp-dev]}} 118 | 119 | # Build on macOS in addition to Linux 120 | - env: BUILD=stack ARGS="" 121 | compiler: ": #stack default osx" 122 | os: osx 123 | 124 | # Travis includes an macOS which is incompatible with GHC 7.8.4 125 | #- env: BUILD=stack ARGS="--resolver lts-2" 126 | # compiler: ": #stack 7.8.4 osx" 127 | # os: osx 128 | 129 | #- env: BUILD=stack ARGS="--resolver lts-3" 130 | # compiler: ": #stack 7.10.2 osx" 131 | # os: osx 132 | 133 | #- env: BUILD=stack ARGS="--resolver lts-6" 134 | # compiler: ": #stack 7.10.3 osx" 135 | # os: osx 136 | 137 | #- env: BUILD=stack ARGS="--resolver lts-7" 138 | # compiler: ": #stack 8.0.1 osx" 139 | # os: osx 140 | 141 | #- env: BUILD=stack ARGS="--resolver lts-9" 142 | # compiler: ": #stack 8.0.2 osx" 143 | # os: osx 144 | 145 | #- env: BUILD=stack ARGS="--resolver lts-11" 146 | # compiler: ": #stack 8.2.2 osx" 147 | # os: osx 148 | 149 | - env: BUILD=stack ARGS="--resolver lts-12" 150 | compiler: ": #stack 8.4.4 osx" 151 | os: osx 152 | 153 | - env: BUILD=stack ARGS="--resolver lts-14" 154 | compiler: ": #stack 8.6.5 osx" 155 | os: osx 156 | 157 | - env: BUILD=stack ARGS="--resolver nightly" 158 | compiler: ": #stack nightly osx" 159 | os: osx 160 | 161 | allow_failures: 162 | - env: BUILD=cabal GHCVER=head CABALVER=head HAPPYVER=1.19.5 ALEXVER=3.1.7 163 | - env: BUILD=stack ARGS="--resolver nightly" 164 | 165 | before_install: 166 | # Using compiler above sets CC to an invalid value, so unset it 167 | - unset CC 168 | 169 | # We want to always allow newer versions of packages when building on GHC HEAD 170 | - CABALARGS="" 171 | - if [ "x$GHCVER" = "xhead" ]; then CABALARGS=--allow-newer; fi 172 | 173 | # Download and unpack the stack executable 174 | - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$HOME/.local/bin:/opt/alex/$ALEXVER/bin:/opt/happy/$HAPPYVER/bin:$HOME/.cabal/bin:$PATH 175 | - mkdir -p ~/.local/bin 176 | - | 177 | if [ `uname` = "Darwin" ] 178 | then 179 | travis_retry curl --insecure -L https://get.haskellstack.org/stable/osx-x86_64.tar.gz | tar xz --strip-components=1 --include '*/stack' -C ~/.local/bin 180 | else 181 | travis_retry curl -L https://get.haskellstack.org/stable/linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack' 182 | fi 183 | 184 | # Use the more reliable S3 mirror of Hackage 185 | mkdir -p $HOME/.cabal 186 | echo 'remote-repo: hackage.haskell.org:http://hackage.fpcomplete.com/' > $HOME/.cabal/config 187 | echo 'remote-repo-cache: $HOME/.cabal/packages' >> $HOME/.cabal/config 188 | 189 | 190 | install: 191 | - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]" 192 | - if [ -f configure.ac ]; then autoreconf -i; fi 193 | - | 194 | set -ex 195 | case "$BUILD" in 196 | stack) 197 | # Add in extra-deps for older snapshots, as necessary 198 | # 199 | # This is disabled by default, as relying on the solver like this can 200 | # make builds unreliable. Instead, if you have this situation, it's 201 | # recommended that you maintain multiple stack-lts-X.yaml files. 202 | 203 | #stack --no-terminal --install-ghc $ARGS test --bench --dry-run || ( \ 204 | # stack --no-terminal $ARGS build cabal-install && \ 205 | # stack --no-terminal $ARGS solver --update-config) 206 | 207 | # Build the dependencies 208 | stack --no-terminal --install-ghc $ARGS test --bench --only-dependencies 209 | ;; 210 | cabal) 211 | cabal --version 212 | travis_retry cabal update 213 | 214 | # Get the list of packages from the stack.yaml file. Note that 215 | # this will also implicitly run hpack as necessary to generate 216 | # the .cabal files needed by cabal-install. 217 | PACKAGES=$(stack --install-ghc query locals | grep '^ *path' | sed 's@^ *path:@@') 218 | 219 | cabal install --only-dependencies --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES 220 | ;; 221 | esac 222 | set +ex 223 | 224 | script: 225 | - | 226 | set -ex 227 | case "$BUILD" in 228 | stack) 229 | stack --no-terminal $ARGS test --bench --no-run-benchmarks --haddock --no-haddock-deps 230 | ;; 231 | cabal) 232 | cabal install --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES 233 | 234 | ORIGDIR=$(pwd) 235 | for dir in $PACKAGES 236 | do 237 | cd $dir 238 | cabal check || [ "$CABALVER" == "1.16" ] 239 | cabal sdist 240 | PKGVER=$(cabal info . | awk '{print $2;exit}') 241 | SRC_TGZ=$PKGVER.tar.gz 242 | cd dist 243 | tar zxfv "$SRC_TGZ" 244 | cd "$PKGVER" 245 | cabal configure --enable-tests --ghc-options -O0 246 | cabal build 247 | if [ "$CABALVER" = "1.16" ] || [ "$CABALVER" = "1.18" ]; then 248 | cabal test 249 | else 250 | cabal test --show-details=streaming --log=/dev/stdout 251 | fi 252 | cd $ORIGDIR 253 | done 254 | ;; 255 | esac 256 | set +ex 257 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | ## master 4 | 5 | ## v0.1.1.0 6 | 7 | * Output files in sorted ordering. 8 | 9 | ## v0.1.0.2 10 | 11 | * Fix package category, from Web to Development. 12 | * Test with Stack LTS v15.0. 13 | * Add link in README to example repository. 14 | 15 | ## v0.1.0.1 16 | 17 | * Documentation fixes 18 | 19 | 20 | ## v0.1.0.0 21 | 22 | * Initial Release 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Pavan Rikhi (c) 2020 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | * Neither the name of Pavan Rikhi nor the names of other 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # stack-templatizer 2 | 3 | [![stack-templatizer Build Status](https://github.com/prikhi/stack-templatizer/actions/workflows/main.yml/badge.svg)](https://github.com/prikhi/stack-templatizer/actions/workflows/main.yml) 4 | 5 | 6 | Stack Templatizer is a small application that lets you generate stack template 7 | `hsfiles` from a folder. 8 | 9 | Install or clone & build the project using `stack`: 10 | 11 | ```sh 12 | # Install from Stack Nightly 13 | stack install stack-templatizer --resolver nightly 14 | 15 | # Or build and install from source 16 | git clone https://github.com/prikhi/stack-templatizer 17 | cd stack-templatizer 18 | stack install 19 | ``` 20 | 21 | Once installed, you can run `stack-templatizer my-template-folder` to generate 22 | a `my-template-folder.hsfiles` stack template. 23 | 24 | 25 | For an example repository that generates a stack template, see 26 | [hpack-template](https://github.com/prikhi/hpack-template). 27 | 28 | 29 | ## LICENSE 30 | 31 | BSD-3-Clause 32 | -------------------------------------------------------------------------------- /Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /package.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | name: 4 | stack-templatizer 5 | version: 6 | 0.1.1.0 7 | github: 8 | prikhi/stack-templatizer 9 | homepage: 10 | https://github.com/prikhi/stack-templatizer#readme 11 | license: 12 | BSD3 13 | license-file: 14 | LICENSE 15 | author: 16 | Pavan Rikhi 17 | maintainer: 18 | pavan.rikhi@gmail.com 19 | copyright: 20 | 2020-2023 Pavan Rikhi 21 | category: 22 | Development 23 | extra-source-files: 24 | - README.md 25 | - CHANGELOG.md 26 | 27 | synopsis: 28 | Generate a stack template from a folder. 29 | description: | 30 | @stack-templatizer@ is an application that generates a @.hsfiles@ stack 31 | template from a folder of template files. 32 | 33 | You can install the application using @stack install 34 | stack-templatizer --resolver nightly@ or by cloning the repository and 35 | running @stack install@. 36 | 37 | Then run @stack-templatizer my-folder@ to turn all the files in @my-folder@ 38 | into a @my-folder.hsfiles@ stack template. 39 | 40 | You can see an example folder & the generated @hs-files@ in the 41 | . 42 | 43 | dependencies: 44 | - base >= 4.7 && < 5 45 | - bytestring < 1 46 | - directory >= 1 && < 2 47 | - filepath >= 1 && < 2 48 | 49 | executables: 50 | stack-templatizer: 51 | source-dirs: 52 | src 53 | main: 54 | Main.hs 55 | -------------------------------------------------------------------------------- /src/Main.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE LambdaCase #-} 2 | {-# LANGUAGE OverloadedStrings #-} 3 | {-# LANGUAGE TupleSections #-} 4 | module Main where 5 | 6 | import Data.List ( sort ) 7 | import System.Directory ( listDirectory 8 | , doesDirectoryExist 9 | ) 10 | import System.Environment ( getArgs ) 11 | import System.Exit ( exitFailure ) 12 | import System.FilePath ( () ) 13 | 14 | import qualified Data.ByteString.Lazy as LBS 15 | import qualified Data.ByteString.Lazy.Char8 as LC 16 | 17 | main :: IO () 18 | main = getArgs >>= \case 19 | [folderName] -> 20 | templatize folderName >>= LBS.writeFile (folderName ++ ".hsfiles") 21 | _ -> printHelp >> exitFailure 22 | 23 | 24 | printHelp :: IO () 25 | printHelp = mapM_ 26 | putStrLn 27 | [ "stack-templatizer: Generate Stack Templates from a Folder" 28 | , "" 29 | , "Usage: stack-templatizer FOLDER_NAME" 30 | , "" 31 | , "The generated file will be named `.hsfiles`" 32 | ] 33 | 34 | 35 | templatize :: FilePath -> IO LBS.ByteString 36 | templatize folder = do 37 | fileNames <- getFilesInDirectory folder 38 | namesAndContents <- mapM 39 | (\file -> (file, ) <$> LBS.readFile (folder file)) 40 | fileNames 41 | return $ generateHFiles namesAndContents 42 | 43 | 44 | getFilesInDirectory :: FilePath -> IO [FilePath] 45 | getFilesInDirectory baseDirectory = do 46 | basePaths <- listDirSorted baseDirectory 47 | concat <$> mapM (recursiveList "") basePaths 48 | where 49 | listDirSorted :: FilePath -> IO [FilePath] 50 | listDirSorted = 51 | fmap sort . listDirectory 52 | recursiveList :: String -> FilePath -> IO [FilePath] 53 | recursiveList parentDir path = do 54 | let templatePath = parentDir path 55 | fullPath = baseDirectory templatePath 56 | isDirectory <- doesDirectoryExist fullPath 57 | if isDirectory 58 | then do 59 | files <- listDirSorted fullPath 60 | concat <$> mapM (recursiveList templatePath) files 61 | else return [templatePath] 62 | 63 | 64 | generateHFiles :: [(FilePath, LBS.ByteString)] -> LBS.ByteString 65 | generateHFiles = LBS.intercalate "\n" . map prefixName 66 | where 67 | prefixName :: (FilePath, LBS.ByteString) -> LBS.ByteString 68 | prefixName (file, contents) = 69 | "{-# START_FILE " <> LC.pack file <> " #-}\n" <> contents 70 | -------------------------------------------------------------------------------- /stack-templatizer.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: 1.12 2 | 3 | -- This file has been generated from package.yaml by hpack version 0.35.1. 4 | -- 5 | -- see: https://github.com/sol/hpack 6 | -- 7 | -- hash: c53e807db04e8b8ab72ceacd797c38f9885d39cd532a917e3f101bac72614b20 8 | 9 | name: stack-templatizer 10 | version: 0.1.1.0 11 | synopsis: Generate a stack template from a folder. 12 | description: @stack-templatizer@ is an application that generates a @.hsfiles@ stack 13 | template from a folder of template files. 14 | . 15 | You can install the application using @stack install 16 | stack-templatizer --resolver nightly@ or by cloning the repository and 17 | running @stack install@. 18 | . 19 | Then run @stack-templatizer my-folder@ to turn all the files in @my-folder@ 20 | into a @my-folder.hsfiles@ stack template. 21 | . 22 | You can see an example folder & the generated @hs-files@ in the 23 | . 24 | category: Development 25 | homepage: https://github.com/prikhi/stack-templatizer#readme 26 | bug-reports: https://github.com/prikhi/stack-templatizer/issues 27 | author: Pavan Rikhi 28 | maintainer: pavan.rikhi@gmail.com 29 | copyright: 2020-2023 Pavan Rikhi 30 | license: BSD3 31 | license-file: LICENSE 32 | build-type: Simple 33 | extra-source-files: 34 | README.md 35 | CHANGELOG.md 36 | 37 | source-repository head 38 | type: git 39 | location: https://github.com/prikhi/stack-templatizer 40 | 41 | executable stack-templatizer 42 | main-is: Main.hs 43 | other-modules: 44 | Paths_stack_templatizer 45 | hs-source-dirs: 46 | src 47 | build-depends: 48 | base >=4.7 && <5 49 | , bytestring <1 50 | , directory ==1.* 51 | , filepath ==1.* 52 | default-language: Haskell2010 53 | -------------------------------------------------------------------------------- /stack.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # This file was automatically generated by 'stack init' 4 | # 5 | # Some commonly used options have been documented as comments in this file. 6 | # For advanced use and comprehensive documentation of the format, please see: 7 | # https://docs.haskellstack.org/en/stable/yaml_configuration/ 8 | 9 | # Resolver to choose a 'specific' stackage snapshot or a compiler version. 10 | # A snapshot resolver dictates the compiler version and the set of packages 11 | # to be used for project dependencies. For example: 12 | # 13 | # resolver: lts-3.5 14 | # resolver: nightly-2015-09-21 15 | # resolver: ghc-7.10.2 16 | # 17 | # The location of a snapshot can be provided as a file or url. Stack assumes 18 | # a snapshot provided as a file might change, whereas a url resource does not. 19 | # 20 | # resolver: ./custom-snapshot.yaml 21 | # resolver: https://example.com/snapshots/2018-01-01.yaml 22 | resolver: lts-20.20 23 | 24 | # User packages to be built. 25 | # Various formats can be used as shown in the example below. 26 | # 27 | # packages: 28 | # - some-directory 29 | # - https://example.com/foo/bar/baz-0.0.2.tar.gz 30 | # subdirs: 31 | # - auto-update 32 | # - wai 33 | packages: 34 | - . 35 | # Dependency packages to be pulled from upstream that are not in the resolver. 36 | # These entries can reference officially published versions as well as 37 | # forks / in-progress versions pinned to a git hash. For example: 38 | # 39 | # extra-deps: 40 | # - acme-missiles-0.3 41 | # - git: https://github.com/commercialhaskell/stack.git 42 | # commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a 43 | # 44 | # extra-deps: [] 45 | 46 | # Override default flag values for local packages and extra-deps 47 | # flags: {} 48 | 49 | # Extra package databases containing global packages 50 | # extra-package-dbs: [] 51 | 52 | # Control whether we use the GHC we find on the path 53 | # system-ghc: true 54 | # 55 | # Require a specific version of stack, using version ranges 56 | # require-stack-version: -any # Default 57 | # require-stack-version: ">=2.1" 58 | # 59 | # Override the architecture used by stack, especially useful on Windows 60 | # arch: i386 61 | # arch: x86_64 62 | # 63 | # Extra directories used by stack for building 64 | # extra-include-dirs: [/path/to/dir] 65 | # extra-lib-dirs: [/path/to/dir] 66 | # 67 | # Allow a newer minor version of GHC than the snapshot specifies 68 | # compiler-check: newer-minor 69 | -------------------------------------------------------------------------------- /stack.yaml.lock: -------------------------------------------------------------------------------- 1 | # This file was autogenerated by Stack. 2 | # You should not edit this file by hand. 3 | # For more information, please see the documentation at: 4 | # https://docs.haskellstack.org/en/stable/lock_files 5 | 6 | packages: [] 7 | snapshots: 8 | - completed: 9 | sha256: 126fa33ceb11f5e85ceb4e86d434756bd9a8439e2e5776d306a15fbc63b01e89 10 | size: 650041 11 | url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/20/20.yaml 12 | original: lts-20.20 13 | --------------------------------------------------------------------------------