Commit c806e646 authored by locallycompact's avatar locallycompact
Browse files

Make everything monomorphic in `Path`, move within variants and FileLike...

Make everything monomorphic in `Path`, move within variants and FileLike polymorphism to shake-plus-extended.
parent 3bbaf072
Pipeline #168251920 passed with stages
in 24 minutes and 17 seconds
# Changelog for shake-plus
## v0.3.0.0
* Drop dependency on path-like.
* Drop dependency on within.
* Drop `Development.Shake.Plus.Loaders` module.
* Restore monomorphic `Path` variants of everything.
* Move `within` style combinators to [shake-plus-extended](https://hackage.haskell.org/package/shake-plus-extended).
## v0.2.0.0
* Add dependency on [path-like](https://hackage.haskell.org/package/path-like).
......
......@@ -4,18 +4,12 @@ Attempt at a batteries included Shake. We reexport replacements for the main
utility functions of Shake with the following adjustments whereever possible.
* Well-typed paths using the [path](https://hackage.haskell.org/package/path)
library.
* New type classes `MonadAction`, `MonadUnliftAction` and `MonadRules` with
concrete `ReaderT` transformers:
* `RAction r a = RAction (ReaderT r Action a)` and
* `ShakePlus r a = ShakePlus (ReaderT r Rules a)`
* `Text` instead of `String` wherever it is appropriate.
* `within` style variants of the standard file and directory operations that
in some cases return or accept `Within b (Path Rel File)` values to keep tags
of parent directories.
This is an early release and some things may be missing or broken, but so
far the conveniences have been worth it. Some notes on the approach are
detailed below.
## Paths
......@@ -43,68 +37,6 @@ similarly. In fact, you can reuse the logging functions from `RIO` within any
which is also a `MonadReader`. If you need to reuse an existing shake
`Action` in an `RAction`, use `liftAction`.
## Using Within
One common complaint about Shake is having to keep track of source and output
directories and translating `FilePath`s when using the input to an `Action`,
leading to lots of repetition of the form `(sourceFolder </>) . (-<.> ".ext") .
dropDirectory1` which is prone to breakage. Using `Path` helps this to some
degree, but in some cases is even more annoying because lots of `Path`
functions use `MonadThrow`, leading to lots of monadic steps inside an
`RAction`.
To alleviate this somewhat, we use `Within b (Path Rel File)` as a standard
pattern for representing a file within a directory. `Within` is a type
available in the [within](https://hackage.haskell.org/package/within) package
that is simply a newtype wrapper over an `Env` comonad with the environment
specialized to `Path b Dir`. We provide variants of the file operations and
rules that typically accept or return `Path`s or contain callbacks that expect
paths and change these to `Within` values. These functions are generally
suffixed `within`. Here is the variant of `getDirectoryFiles` that
produces `Within` values.
```{.haskell}
getDirectoryFilesWithin' :: MonadAction m => Within Rel [FilePattern] -> m [Within b (Path Rel File)]
```
You can convert to and from this within-style using `within` and `fromWithin`.
```{.haskell}
let x = $(mkRelFile "a.txt") `within` $(mkRelDir "foo") -- Within Rel (Path Rel File)
fromWithin x -- produces a `Path Rel File`
```
and you can assert that an existing path lies in a directory by using `asWithin`, which throws
if the directory is not a proper prefix of the `Path`.
```{.haskell}
$(mkRelFile "foo/a.txt") `asWithin` $(mkRelDir "foo") -- fine
$(mkRelFile "a.txt") `asWithin` $(mkRelDir "foo") -- throws error
```
Filerules such as `(%>)` have within-style variants that accept an ` (Path b
Dir) FilePattern` on the left and carry that env to the callback.
```{.haskell}
(%^>) :: (Partial, MonadReader r m, MonadRules m) => Within Rel FilePattern -> (Within Rel (Path Rel File) -> RAction r ()) -> m ()
```
You change the underlying filepath with `fmap` or `mapM`, whilst you can move
to a new parent directory by using `localDir`, or `localDirM` which is defined
in the `Within` library for when the map between parent directories may throw.
The `Within` library also contains more functions and instances for more
precise changes between output and source directories.
## PathLike, FileLike and DirLike
The [path-like](https://hackage.haskell.org/package/path-like) library provides
type classes for things which are at least as strict as the `Path` type itself.
All `Paths` are `PathLike`, a `Path b File` is `FileLike b` and a `Path b Dir`
is `DirLike b`. A `Within b (Path Rel File)` is `FileLike b` and a `Within b
(Path Rel Dir) is `DirLike b`. The `readFile` and `writeFile` variants in
`shake-plus` can take any `FileLike`, and `copyFile` allows you to copy between
any two `FileLike`.
## runShakePlus
The main entry point to this library is the `runShakePlus` function, which
......
name: shake-plus
version: 0.2.0.1
version: 0.3.0.0
license: MIT
author: "Daniel Firth"
maintainer: "dan.firth@homotopic.tech"
......@@ -12,7 +12,7 @@ extra-source-files:
category: development, shake
synopsis: Re-export of Shake using well-typed paths and ReaderT.
description: Re-export of Shake using well-typed paths and ReaderT. You can thread logging through your Shake Actions, and better keep track of source and output folders using the Within type.
description: Re-export of Shake using well-typed paths and ReaderT. You can thread logging through your Shake Actions.
default-extensions:
- BangPatterns
......@@ -61,15 +61,12 @@ ghc-options:
- -Wredundant-constraints
dependencies:
- aeson >= 1.4.7.1
- base >= 4.7 && < 5
- comonad
- extra
- path
- path-like >= 0.2.0.0
- rio
- shake
- within >= 0.2.0.0
library:
source-dirs: src
......@@ -4,12 +4,12 @@ cabal-version: 1.12
--
-- see: https://github.com/sol/hpack
--
-- hash: 8183d4e01e853857dc3ea488b0730d5384224154ee437cacc40efa2074ae6676
-- hash: ca3941017f20a754ecdc3ed8226a6e0019623770241a40a285aa584e6c7588f4
name: shake-plus
version: 0.2.0.1
version: 0.3.0.0
synopsis: Re-export of Shake using well-typed paths and ReaderT.
description: Re-export of Shake using well-typed paths and ReaderT. You can thread logging through your Shake Actions, and better keep track of source and output folders using the Within type.
description: Re-export of Shake using well-typed paths and ReaderT. You can thread logging through your Shake Actions.
category: development, shake
homepage: https://gitlab.com/shake-plus/shake-plus
author: Daniel Firth
......@@ -34,7 +34,6 @@ library
Development.Shake.Plus.Env
Development.Shake.Plus.File
Development.Shake.Plus.FileRules
Development.Shake.Plus.Loaders
Development.Shake.Plus.Oracle
Development.Shake.Plus.Temp
other-modules:
......@@ -44,13 +43,10 @@ library
default-extensions: BangPatterns BinaryLiterals ConstraintKinds DataKinds DefaultSignatures DeriveDataTypeable DeriveFoldable DeriveFunctor DeriveGeneric DeriveTraversable DoAndIfThenElse EmptyDataDecls ExistentialQuantification FlexibleContexts FlexibleInstances FunctionalDependencies GADTs GeneralizedNewtypeDeriving InstanceSigs KindSignatures LambdaCase MultiParamTypeClasses MultiWayIf NamedFieldPuns NoImplicitPrelude OverloadedStrings PartialTypeSignatures PatternGuards PolyKinds RankNTypes RecordWildCards ScopedTypeVariables StandaloneDeriving TupleSections TypeFamilies TypeSynonymInstances ViewPatterns
ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints
build-depends:
aeson >=1.4.7.1
, base >=4.7 && <5
base >=4.7 && <5
, comonad
, extra
, path
, path-like >=0.2.0.0
, rio
, shake
, within >=0.2.0.0
default-language: Haskell2010
{- |
Module : Development.Shake.Plus
Copyright : Copyright (C) 2020 Daniel Firth
Maintainer : Daniel Firth <dan.firth@homotopic.tech
Maintainer : Daniel Firth <dan.firth@homotopic.tech>
License : MIT
Stability : experimental
Module exports for Development.Shake.Plus. Re-exports everything in this package
as well as "Path", "Path.Like" and "Within".
as well as "Path",
-}
module Development.Shake.Plus (
module Development.Shake.Classes
......@@ -16,12 +16,9 @@ module Development.Shake.Plus (
, module Development.Shake.Plus.Directory
, module Development.Shake.Plus.File
, module Development.Shake.Plus.FileRules
, module Development.Shake.Plus.Loaders
, module Development.Shake.Plus.Oracle
, module Development.Shake.Plus.Temp
, module Path
, module Path.Like
, module Within
) where
import Development.Shake.Classes
......@@ -31,9 +28,6 @@ import Development.Shake.Plus.Core
import Development.Shake.Plus.Directory
import Development.Shake.Plus.File
import Development.Shake.Plus.FileRules
import Development.Shake.Plus.Loaders
import Development.Shake.Plus.Oracle
import Development.Shake.Plus.Temp
import Path
import Path.Like
import Within
{- |
Module : Development.Shake.Plus.Cache
Copyright : Copyright (C) 2020 Daniel Firth
Maintainer : Daniel Firth <dan.firth@homotopic.tech
Maintainer : Daniel Firth <dan.firth@homotopic.tech>
License : MIT
Stability : experimental
......
{- |
Module : Development.Shake.Plus.Command
Copyright : Copyright (C) 2020 Daniel Firth
Maintainer : Daniel Firth <dan.firth@homotopic.tech
Maintainer : Daniel Firth <dan.firth@homotopic.tech>
License : MIT
Stability : experimental
......
{- |
Module : Development.Shake.Plus.Config
Copyright : Copyright (C) 2020 Daniel Firth
Maintainer : Daniel Firth <dan.firth@homotopic.tech
Maintainer : Daniel Firth <dan.firth@homotopic.tech>
License : MIT
Stability : experimental
Utilities in "Development.Shake.Config" lifted to `MonadAction` and `FileLike`/`DirLike`.
Utilities in "Development.Shake.Config" lifted to `MonadAction` and well-typed `Path`s.
-}
module Development.Shake.Plus.Config (
readConfigFile
......@@ -20,20 +20,19 @@ import Development.Shake
import qualified Development.Shake.Config
import Development.Shake.Plus.Core
import Path
import Path.Like
import RIO
-- | Lifted `Development.Shake.Config.readConfigFile` with well-typed path.
readConfigFile :: (MonadIO m, FileLike b a) => a -> m (HashMap String String)
readConfigFile = liftIO . Development.Shake.Config.readConfigFile . toFilePath . toFile
readConfigFile :: MonadIO m => Path b File -> m (HashMap String String)
readConfigFile = liftIO . Development.Shake.Config.readConfigFile . toFilePath
-- | Lifted `Development.Shake.Config.readConfigFileWithEnv` with well-typed path.
readConfigFileWithEnv :: (MonadIO m, FileLike b a) => [(String, String)] -> a -> m (HashMap String String)
readConfigFileWithEnv vars file = liftIO $ Development.Shake.Config.readConfigFileWithEnv vars (toFilePath . toFile $ file)
readConfigFileWithEnv :: MonadIO m => [(String, String)] -> Path b File -> m (HashMap String String)
readConfigFileWithEnv vars file = liftIO $ Development.Shake.Config.readConfigFileWithEnv vars (toFilePath file)
-- | Lifted `Development.Shake.Config.usingConfigFile` with well-typed path.
usingConfigFile :: (MonadRules m, FileLike b a) => a -> m ()
usingConfigFile = liftRules . Development.Shake.Config.usingConfigFile . toFilePath . toFile
usingConfigFile :: MonadRules m => Path b File -> m ()
usingConfigFile = liftRules . Development.Shake.Config.usingConfigFile . toFilePath
-- | Lifted `Development.Shake.Config.usingConfig`.
usingConfig :: MonadRules m => HashMap String String -> m ()
......
{- |
Module : Development.Shake.Plus.Core
Copyright : Copyright (C) 2020 Daniel Firth
Maintainer : Daniel Firth <dan.firth@homotopic.tech
Maintainer : Daniel Firth <dan.firth@homotopic.tech>
License : MIT
Stability : experimental
......@@ -19,7 +19,6 @@ module Development.Shake.Plus.Core (
, ShakePlus
, runRAction
, runShakePlus
, runSimpleShakePlus
, parallel
, forP
, par
......@@ -108,14 +107,6 @@ instance MonadThrow (RAction r) where
instance MonadThrow (ShakePlus r) where
throwM = liftIO . Control.Exception.throwIO
-- | Run a `ShakePlus` with just a `LogFunc` in the environment that logs to stderr.
runSimpleShakePlus :: MonadIO m => ShakePlus LogFunc a -> m ()
runSimpleShakePlus m = do
lo <- logOptionsHandle stderr True
(lf, dlf) <- newLogFunc (setLogMinLevel LevelInfo lo)
liftIO $ Development.Shake.shakeArgs Development.Shake.shakeOptions $ void $ runShakePlus lf m
dlf
-- | Unlifted `Development.Shake.parallel`.
parallel :: MonadUnliftAction m => [m a] -> m [a]
parallel xs = withRunInAction $ \run -> Development.Shake.parallel $ fmap run xs
......
{- |
Module : Development.Shake.Plus.Database
Copyright : Copyright (C) 2020 Daniel Firth
Maintainer : Daniel Firth <dan.firth@homotopic.tech
Maintainer : Daniel Firth <dan.firth@homotopic.tech>
License : MIT
Stability : experimental
......
{- |
Module : Development.Shake.Plus.Directory
Copyright : Copyright (C) 2020 Daniel Firth
Maintainer : Daniel Firth <dan.firth@homotopic.tech
Maintainer : Daniel Firth <dan.firth@homotopic.tech>
License : MIT
Stability : experimental
Directory utilities in "Development.Shake" lifted to `MonadAction` and
`FileLike`/`DirLike`.
well-typed `Path`s.
-}
module Development.Shake.Plus.Directory (
doesFileExist
, doesDirectoryExist
, getDirectoryFiles
, getDirectoryFilesWithin
, getDirectoryFilesWithin'
, getDirectoryDirs
, getDirectoryFilesIO
, getDirectoryFilesWithinIO
, getDirectoryFilesWithinIO'
) where
import Control.Comonad.Env as E
import qualified Development.Shake
import Development.Shake.Plus.Core
import Path
import Path.Like
import RIO
import Within
-- | Lifted version of `Development.Shake.doesFileExist` using well-typed `Path`s.
doesFileExist :: (MonadAction m, FileLike b a) => a -> m Bool
doesFileExist = liftAction . Development.Shake.doesFileExist . toFilePath . toFile
doesFileExist :: MonadAction m => Path b File -> m Bool
doesFileExist = liftAction . Development.Shake.doesFileExist . toFilePath
-- | Lifted version of `Development.Shake.doesDirectoryExist` using well-typed `Path`s.
doesDirectoryExist :: (MonadAction m, DirLike b a) => a -> m Bool
doesDirectoryExist = liftAction . Development.Shake.doesDirectoryExist . toFilePath . toDir
doesDirectoryExist :: MonadAction m => Path b Dir -> m Bool
doesDirectoryExist = liftAction . Development.Shake.doesDirectoryExist . toFilePath
-- | Lifted version of `Development.Shake.getDirectoryFiles` using well-typed `Path`s.
getDirectoryFiles :: (MonadAction m, DirLike b a) => a -> [FilePattern] -> m [Path Rel File]
getDirectoryFiles x y = liftAction $ traverse (liftIO . parseRelFile) =<< Development.Shake.getDirectoryFiles (toFilePath . toDir $ x) y
-- | Like `getDirectoryFiles`, but accepts a `Within` value and returns a `Within` contaning a list of `Path`s
getDirectoryFilesWithin :: MonadAction m => Within b [FilePattern] -> m (Within b [Path Rel File])
getDirectoryFilesWithin x = do
xs <- getDirectoryFiles (E.ask x) (extract x)
return (xs <$ x)
-- | Like `getDirectoryFilesWithin`, but returns a list of `Within` values instead of a `Within`` of a list.
getDirectoryFilesWithin' :: MonadAction m => Within b [FilePattern] -> m [Within b (Path Rel File)]
getDirectoryFilesWithin' x = do
xs <- getDirectoryFiles (E.ask x) (extract x)
return ((<$ x) <$> xs)
getDirectoryFiles :: MonadAction m => Path b Dir -> [FilePattern] -> m [Path Rel File]
getDirectoryFiles x y = liftAction $ traverse (liftIO . parseRelFile) =<< Development.Shake.getDirectoryFiles (toFilePath x) y
-- | Lifted version of `Development.Shake.getDirectoryDirs` using well-typed `Path`s.
getDirectoryDirs :: (MonadAction m, DirLike b a) => a -> m [Path Rel Dir]
getDirectoryDirs x = liftAction $ traverse (liftIO . parseRelDir) =<< Development.Shake.getDirectoryDirs (toFilePath . toDir $ x)
getDirectoryDirs :: MonadAction m => Path b Dir -> m [Path Rel Dir]
getDirectoryDirs x = liftAction $ traverse (liftIO . parseRelDir) =<< Development.Shake.getDirectoryDirs (toFilePath x)
-- | Lifted version of `Development.Shake.getDirectoryFilesIO` using well-typed `Path`s.
getDirectoryFilesIO :: (MonadIO m, DirLike b a) => a -> [FilePattern] -> m [Path Rel File]
getDirectoryFilesIO x y = liftIO $ traverse (liftIO . parseRelFile) =<< Development.Shake.getDirectoryFilesIO (toFilePath . toDir $ x) y
-- | Like `getDirectoryFilesIO`, but accepts a `Within` value and returns a `Within` contaning a list of `Path`s
getDirectoryFilesWithinIO :: MonadIO m => Within b [FilePattern] -> m (Within b [Path Rel File])
getDirectoryFilesWithinIO x = do
xs <- getDirectoryFilesIO (E.ask x) (extract x)
return (xs <$ x)
-- | Like `getDirectoryFilesWithinIO`, but returns a list of `Within` values instead of a `Within`` of a list.
getDirectoryFilesWithinIO' :: MonadIO m => Within b [FilePattern] -> m [Within b (Path Rel File)]
getDirectoryFilesWithinIO' x = do
xs <- getDirectoryFilesIO (E.ask x) (extract x)
return ((<$ x) <$> xs)
getDirectoryFilesIO :: MonadIO m => Path b Dir -> [FilePattern] -> m [Path Rel File]
getDirectoryFilesIO x y = liftIO $ traverse (liftIO . parseRelFile) =<< Development.Shake.getDirectoryFilesIO (toFilePath x) y
{- |
Module : Development.Shake.Plus.Env
Copyright : Copyright (C) 2020 Daniel Firth
Maintainer : Daniel Firth <dan.firth@homotopic.tech
Maintainer : Daniel Firth <dan.firth@homotopic.tech>
License : MIT
Stability : experimental
......
{- |
Module : Development.Shake.Plus.File
Copyright : Copyright (C) 2020 Daniel Firth
Maintainer : Daniel Firth <dan.firth@homotopic.tech
Maintainer : Daniel Firth <dan.firth@homotopic.tech>
License : MIT
Stability : experimental
File utilities in "Development.Shake" lifted to `MonadAction` and
`FileLike`/`DirLike`.
well-typed `Path`s.
-}
module Development.Shake.Plus.File (
copyFile
, copyFile'
, copyFileChanged
, copyFileChanged'
, readFile'
, readFileLines
, readFileIn'
......@@ -23,9 +21,6 @@ module Development.Shake.Plus.File (
, writeFileChangedIn
, removeFiles
, removeFilesAfter
, FileLike(..)
, DirLike(..)
, (/>)
) where
import Control.Comonad.Env as E
......@@ -33,65 +28,56 @@ import Control.Exception.Extra
import qualified Development.Shake
import Development.Shake.Plus.Core
import Path
import Path.Like
import RIO
import qualified RIO.Text as T
-- | Lifted version of `Development.Shake.copyFile` that copies between any two `FileLike`.
copyFile :: (MonadAction m, FileLike b a, FileLike b' a', Partial) => a -> a' -> m ()
copyFile x y = liftAction $ Development.Shake.copyFile' (toFilePath . toFile $ x) (toFilePath . toFile $ y)
-- | Lifted version of `Development.Shake.copyFile` with well-typed filepaths.
copyFile :: (MonadAction m, Partial) => Path b File -> Path b' File -> m ()
copyFile x y = liftAction $ Development.Shake.copyFile' (toFilePath x) (toFilePath y)
-- | Like `copyFile` but for `FileLike`s that are of the same type, useful for type inference.
copyFile' :: (MonadAction m, FileLike b a, Partial) => a -> a -> m ()
copyFile' = copyFile
-- | Lifted version of `Development.Shake.copyFileChanged'` with well-typed filepaths.
copyFileChanged :: (MonadAction m, Partial) => Path b File -> Path b' File -> m ()
copyFileChanged x y = liftAction $ Development.Shake.copyFileChanged (toFilePath x) (toFilePath y)
-- | Lifted version of `Development.Shake.copyFileChanged'` that copies between two `FileLike'.
copyFileChanged :: (MonadAction m, FileLike b a, FileLike b' a', Partial) => a -> a' -> m ()
copyFileChanged x y = liftAction $ Development.Shake.copyFileChanged (toFilePath . toFile $ x) (toFilePath . toFile $ y)
-- | Lifted version of `Development.Shake.readFile'` with a well-typed filepath.
readFile' :: (MonadAction m, Partial) => Path b File -> m Text
readFile' = liftAction . fmap T.pack . Development.Shake.readFile' . toFilePath
-- | Like `copyFileChanged` but ensures the `FileLike`s are of the same type, useful for type inference.
copyFileChanged' :: (MonadAction m, FileLike b a, Partial) => a -> a -> m ()
copyFileChanged' = copyFileChanged
-- | Lifted version of `Development.Shake.readFile'` that reads any `FileLike`.
readFile' :: (MonadAction m, FileLike b a, Partial) => a -> m Text
readFile' = liftAction . fmap T.pack . Development.Shake.readFile' . toFilePath . toFile
-- | Lifted version of `Development.Shake.readFileLines` that reads any `FileLike`.
readFileLines :: (MonadAction m, FileLike b a, Partial) => a -> m [Text]
readFileLines = liftAction . fmap (fmap T.pack) . Development.Shake.readFileLines . toFilePath . toFile
-- | Lifted version of `Development.Shake.readFileLines` a well-typed filepath.
readFileLines :: (MonadAction m, Partial) => Path b File -> m [Text]
readFileLines = liftAction . fmap (fmap T.pack) . Development.Shake.readFileLines . toFilePath
-- | Like `readFile'`, but with an argument for the parent directory. Used for symmetry with
-- the way `Development.Shake.getDirectoryFiles` takes arguments.
readFileIn' :: (MonadAction m, DirLike b d, FileLike Rel a, Partial) => d -> a -> m Text
readFileIn' x y = readFile' $ x /> y
readFileIn' :: (MonadAction m, Partial) => Path b Dir -> Path Rel File -> m Text
readFileIn' x y = readFile' $ x </> y
-- | Lifted version of `Development.Shake.writeFile` that writes to any `FileLike`.
writeFile' :: (MonadAction m, FileLike b a, Partial) => a -> Text -> m ()
writeFile' x y = liftAction $ Development.Shake.writeFile' (toFilePath . toFile $ x) (T.unpack y)
-- | Lifted version of `Development.Shake.writeFile` a well-typed filepath.
writeFile' :: (MonadAction m, Partial) => Path b File -> Text -> m ()
writeFile' x y = liftAction $ Development.Shake.writeFile' (toFilePath x) (T.unpack y)
-- | Lifted version of `Development.Shake.writeFileLines` that writes to any `FileLike`.
writeFileLines :: (MonadAction m, FileLike b a, Partial) => a -> [Text] -> m ()
writeFileLines x y = liftAction $ Development.Shake.writeFileLines (toFilePath . toFile $ x) (fmap T.unpack y)
-- | Lifted version of `Development.Shake.writeFileLines` with a well-typed filepath..
writeFileLines :: (MonadAction m, Partial) => Path b File -> [Text] -> m ()
writeFileLines x y = liftAction $ Development.Shake.writeFileLines (toFilePath x) (fmap T.unpack y)
-- | Like `writeFile'`, but with an argument for the parent directory. Used for symmetry with
-- the way `Development.Shake.getDirectoryFiles` takes arguments.
writeFileIn' :: (MonadAction m, DirLike b d, FileLike Rel a, Partial) => d -> a -> Text -> m ()
writeFileIn' x y = writeFile' $ x /> y
writeFileIn' :: (MonadAction m, Partial) => Path b Dir -> Path Rel File -> Text -> m ()
writeFileIn' x y = writeFile' $ x </> y
-- | Lifted version of `Development.Shake.writeFileChanged` that writes to any `FileLike`.
writeFileChanged :: (MonadAction m, FileLike b a, Partial) => a -> Text -> m ()
writeFileChanged x y = liftAction $ Development.Shake.writeFileChanged (toFilePath . toFile $ x) (T.unpack y)
-- | Lifted version of `Development.Shake.writeFileChanged` with a well-typed filepath.
writeFileChanged :: (MonadAction m, Partial) => Path b File -> Text -> m ()
writeFileChanged x y = liftAction $ Development.Shake.writeFileChanged (toFilePath x) (T.unpack y)
-- | Like `writeFileChanged'`, but with an argument for the parent directory. Used for symmetry with
-- the way `Development.Shake.getDirectoryFiles` takes arguments.
writeFileChangedIn :: (MonadAction m, DirLike b d, FileLike Rel a, Partial) => d -> a -> Text -> m ()
writeFileChangedIn x y = writeFileChanged $ x /> y
writeFileChangedIn :: (MonadAction m, Partial) => Path b Dir -> Path Rel File -> Text -> m ()
writeFileChangedIn x y = writeFileChanged $ x </> y
-- | Lifted version of `Development.Shake.removeFiles` that accepts any `DirLike`.
removeFiles :: (MonadAction m, DirLike b d) => d -> [FilePattern] -> m ()
removeFiles x y = liftAction . liftIO $ Development.Shake.removeFiles (toFilePath . toDir $ x) y
-- | Lifted version of `Development.Shake.removeFiles` that accepts a well-typed directory.
removeFiles :: MonadAction m => Path b Dir -> [FilePattern] -> m ()
removeFiles x y = liftAction . liftIO $ Development.Shake.removeFiles (toFilePath x) y
-- | Lifted version of `Development.Shake.removeFilesAfter` that accepts any `DirLike`..
removeFilesAfter :: (MonadAction m, DirLike b d) => d -> [FilePattern] -> m ()
removeFilesAfter x y = liftAction $ Development.Shake.removeFilesAfter (toFilePath . toDir $ x) y
-- | Lifted version of `Development.Shake.removeFilesAfter` that accepts a well-typed directory.
removeFilesAfter :: MonadAction m => Path b Dir -> [FilePattern] -> m ()
removeFilesAfter x y = liftAction $ Development.Shake.removeFilesAfter (toFilePath x) y
{- |
Module : Development.Shake.Plus.FileRules
Copyright : Copyright (C) 2020 Daniel Firth
Maintainer : Daniel Firth <dan.firth@homotopic.tech
Maintainer : Daniel Firth <dan.firth@homotopic.tech>
License : MIT
Stability : experimental
Filerules in "Development.Shake" lifted to `MonadAction` and `FileLike`/`DirLike`.
Filerules in "Development.Shake" lifted to `MonadAction` and well-typed `Path`s.
-}
module Development.Shake.Plus.FileRules (
need
......@@ -14,24 +14,16 @@ module Development.Shake.Plus.FileRules (
, wantP
, needIn
, wantIn
, needWithin
, wantWithin
, (%>)
, (|%>)
, (%^>)
, (|%^>)
, phony
) where
import Control.Comonad.Env as E
import Control.Exception.Extra
import qualified Development.Shake
import qualified Development.Shake.FilePath
import Development.Shake.Plus.Core
import Path
import Path.Like
import RIO as R
import Within
-- | Lifted version of `Development.Shake.need`, This still uses `String`s
-- because it may refer to a phony rule. For the `Path` specific version
......@@ -46,28 +38,20 @@ want :: (Partial, MonadRules m, Foldable t) => t String -> m ()
want = liftRules . Development.Shake.want . toList
-- | Lifted version of `Development.Shake.need` using well-typed `Path`s
needP :: (Partial, MonadAction m, Traversable t, FileLike b a) => t a -> m ()
needP = need . fmap (toFilePath . toFile)
needP :: (Partial, MonadAction m, Traversable t) => t (Path b File) -> m ()
needP = need . fmap toFilePath
-- | Lifted version of `Development.Shake.want` using well-typed `Path`s