shake-plus 0.0.3.0 → 0.1.0.0
raw patch · 15 files changed
+239/−129 lines, 15 filesdep +comonaddep +hashable
Dependencies added: comonad, hashable
Files
- ChangeLog.md +6/−2
- README.md +103/−13
- shake-plus.cabal +6/−3
- src/Development/Shake/Plus.hs +2/−0
- src/Development/Shake/Plus/Cache.hs +2/−2
- src/Development/Shake/Plus/Config.hs +6/−6
- src/Development/Shake/Plus/Core.hs +7/−8
- src/Development/Shake/Plus/Database.hs +4/−4
- src/Development/Shake/Plus/Directory.hs +13/−6
- src/Development/Shake/Plus/Env.hs +4/−4
- src/Development/Shake/Plus/File.hs +13/−13
- src/Development/Shake/Plus/FileRules.hs +27/−26
- src/Development/Shake/Plus/Loaders.hs +38/−34
- src/Development/Shake/Plus/Oracle.hs +5/−5
- src/Development/Shake/Plus/Temp.hs +3/−3
ChangeLog.md view
@@ -1,8 +1,12 @@ # Changelog for shake-plus -## v0.0.3.0+## v0.1.0.0 -* Re-export shakeArgs.+* Update to `within-0.1.1.0` which changes the data type to an `Env` comonad.+* Drop the `loadSortFilterApply` loader functions in favour of a simpler+ `batchLoad` set of functions which accepts a loading function which can be+ cached.+* Add enough documentation to get started. ## v0.0.2.1
README.md view
@@ -4,21 +4,111 @@ utility functions of Shake with the following adjustments whereever possible. * Well-typed paths using the [path](https://hackage.haskell.org/package/path)-* New type classes `MonadAction`,`MonadUnliftAction` and `MonadRules` with- stock `ReaderT` transformers.+* 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. -Unlifting `Action`s is a challenge when we cross monad boundaries (from-`Action` to `Rules`), and so some functions are hard coded against the-`RAction` type, which is a hardcoded newtype `ReaderT r Action a`. This is-annoying, but it's sufficient to add your own logging and reader lenses. It-may be possible to generalize this with some unlifting contortion but so far I-haven't been able to figure it out.+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. -The main entry point ot this library is the `runShakePlus` function, which+## Paths++Using the [path](https://hackage.haskell.org/package/path) library is kind of a+no brainer. I lose a lot of time to problems that could be avoided by using+this library, so it's everywhere. The names for these functions shadow the+existing names, so you may want to `import qualified Development.Shake` while+this library progresses if you have other `FilePath` based Shake rules that+you want to mix into your build.++The standard `Development.Shake.FilePath` functions for directory manipulation+are not re-exported in full, and you should use the functions in the path+library (such as `replaceExtension`) and other path-based libraries. This will+probably change.++`FilePattern`s are kept as-is, as `Path` is strongly normalizing it makes+sense to keep these as `Strings`.++## RAction++The `ReaderT r Action a` transformer (called `RAction`) is similar to the+[RIO](https://hackage.haskell.org/package/rio) type and should be used+similarly. In fact, you can reuse the logging functions from `RIO` within any+`RAction` block, which is one of the main motivators for having an `Action`+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` variant which+produces `Within` values.++```{.haskell}+getDirectoryFilesWithin :: MonadAction m => Path b Dir -> [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.++## runShakePlus++The main entry point to this library is the `runShakePlus` function, which collapses a `ReaderT r Rules ()` to a `Rules ()` and passes the environment to-each underlying `RAction`.+each underlying `RAction`. The `r`s in `ShakePlus` and the underlying+`RAction`s have to match. A typical setup might look like this. -This is an early release and a lot of things may be missing or broken, but so-far the conveniences have been worth it. Until it's stable/complete you probaly-want to `import qualified Development.Shake` to deal with any missing parts.+```{.haskell}+let r = --setup env here+shake shakeOptions $ do++ -- include some regular shake rules.++ runShakePlus r $ do++ -- some shake-plus rules.+```
shake-plus.cabal view
@@ -4,12 +4,12 @@ -- -- see: https://github.com/sol/hpack ----- hash: 3d153076b9dc6ddb4d8c870b17bc10ec15c0ca46176a2fd19330435cd8f222d2+-- hash: 14f0a4521bb0093a57163d38df976c873956b39dc67b54f37780fa37c75cf0b7 name: shake-plus-version: 0.0.3.0+version: 0.1.0.0 synopsis: Re-export of Shake using well-typed paths and ReaderT.-description: Re-export of Shake using well-typed paths and ReaderT. This is an early release so some things may be missing or broken but so far the conveniences have been worth it.+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. category: development, shake author: Daniel Firth maintainer: dan.firth@homotopic.tech@@ -40,9 +40,12 @@ hs-source-dirs: src 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: base >=4.7 && <5+ , comonad , extra+ , hashable , path , rio , shake
src/Development/Shake/Plus.hs view
@@ -6,6 +6,7 @@ , module Development.Shake.Plus.FileRules , module Development.Shake.Plus.Loaders , module Development.Shake.Plus.Oracle+, module Development.Shake.Plus.Temp ) where import Development.Shake.Plus.Cache@@ -15,3 +16,4 @@ import Development.Shake.Plus.FileRules import Development.Shake.Plus.Loaders import Development.Shake.Plus.Oracle+import Development.Shake.Plus.Temp
src/Development/Shake/Plus/Cache.hs view
@@ -4,8 +4,8 @@ ) where import qualified Development.Shake-import RIO-import Development.Shake.Plus.Core+import Development.Shake.Plus.Core+import RIO -- | Lifted version of `Development.Shake.newCache` using `RAction`. newCache :: (MonadRules m, MonadReader r m, Eq k, Hashable k)
src/Development/Shake/Plus/Config.hs view
@@ -7,11 +7,11 @@ , getConfigKeys ) where -import Development.Shake+import Development.Shake import qualified Development.Shake.Config-import Development.Shake.Plus.Core-import Path-import RIO+import Development.Shake.Plus.Core+import Path+import RIO -- | Lifted `Development.Shake.Config.readConfigFile` with well-typed path. readConfigFile :: MonadIO m => Path a File -> m (HashMap String String)@@ -34,5 +34,5 @@ getConfig = liftAction . Development.Shake.Config.getConfig -- | Lifted `Development.Shake.Config.getConfigKeys`.-getConfigKeys :: MonadAction m => m [String]-getConfigKeys = liftAction $ Development.Shake.Config.getConfigKeys+getConfigKeys :: MonadAction m => m [String]+getConfigKeys = liftAction Development.Shake.Config.getConfigKeys
src/Development/Shake/Plus/Core.hs view
@@ -14,13 +14,13 @@ , Development.Shake.Rules , Development.Shake.FilePattern , Development.Shake.shake-, Development.Shake.shakeArgs , Development.Shake.shakeOptions ) where -import Control.Exception-import Development.Shake (Action, Rules, FilePattern, shake, shakeOptions)-import RIO+import Control.Exception+import Development.Shake (Action, FilePattern, Rules, shake,+ shakeOptions)+import RIO -- | Monads in which `Action`s may be embedded. class MonadIO m => MonadAction m where@@ -82,15 +82,14 @@ -- | Run an `RAction` with an environment, consuming it for a result. runRAction :: MonadAction m => env -> RAction env a -> m a-runRAction env (RAction (ReaderT f)) = liftAction (f env)+runRAction r (RAction (ReaderT f)) = liftAction (f r) -- | Run a `ShakePlus` with an environment, consuming it for some Shake `Rules`.-runShakePlus :: MonadRules m => env -> ShakePlus env a -> m a -runShakePlus env (ShakePlus (ReaderT f)) = liftRules (f env)+runShakePlus :: MonadRules m => env -> ShakePlus env a -> m a+runShakePlus r (ShakePlus (ReaderT f)) = liftRules (f r) instance MonadThrow (RAction r) where throwM = liftIO . Control.Exception.throwIO instance MonadThrow (ShakePlus r) where throwM = liftIO . Control.Exception.throwIO-
src/Development/Shake/Plus/Database.hs view
@@ -10,11 +10,11 @@ , shakeRunAfter ) where -import Development.Shake (ShakeOptions, Action, Rules)-import Development.Shake.Database (ShakeDatabase)+import Development.Shake (Action, Rules, ShakeOptions)+import Development.Shake.Database (ShakeDatabase) import qualified Development.Shake.Database-import Path-import RIO+import Path+import RIO -- | Lifted `Development.Shake.Database.shakeOpenDatabase` shakeOpenDatabase :: MonadIO m => ShakeOptions -> Rules () -> m (IO ShakeDatabase, IO ())
src/Development/Shake/Plus/Directory.hs view
@@ -3,15 +3,16 @@ , doesDirectoryExist , getDirectoryFiles , getDirectoryFilesWithin+, getDirectoryFilesWithin' , getDirectoryDirs , getDirectoryFilesIO ) where -import Development.Shake.Plus.Core import qualified Development.Shake-import RIO-import Path-import Within+import Development.Shake.Plus.Core+import Path+import RIO+import Within -- | Lifted version of `Development.Shake.doesFileExist` using well-typed `Path`s. doesFileExist :: MonadAction m => Path b File -> m Bool@@ -25,9 +26,15 @@ getDirectoryFiles :: MonadAction m => Path b Dir -> [FilePattern] -> m [Path Rel File] getDirectoryFiles x y = liftAction $ traverse (liftIO . parseRelFile) =<< Development.Shake.getDirectoryFiles (toFilePath x) y --- | Like `getDirectoryFiles`, but returns `Within` values.-getDirectoryFilesWithin :: MonadAction m => Path Rel Dir -> [FilePattern] -> m [Within Rel File]+-- | Like `getDirectoryFiles`, but returns a `Within` contaning a list of `Path`s.+getDirectoryFilesWithin :: MonadAction m => Path b Dir -> [FilePattern] -> m (Within b [Path Rel File]) getDirectoryFilesWithin x pat = do+ xs <- getDirectoryFiles x pat+ return (xs `within` x)++-- | Like `getDirectoryFilesWithin`, but returns a list of `Within` values instead of a `Within`` of a list.+getDirectoryFilesWithin' :: MonadAction m => Path b Dir -> [FilePattern] -> m [Within b (Path Rel File)]+getDirectoryFilesWithin' x pat = do xs <- getDirectoryFiles x pat return ((`within` x) <$> xs)
src/Development/Shake/Plus/Env.hs view
@@ -1,13 +1,13 @@ module Development.Shake.Plus.Env ( getEnv , getEnvWithDefault-, getEnvError +, getEnvError ) where -import Control.Exception.Extra+import Control.Exception.Extra import qualified Development.Shake-import Development.Shake.Plus-import RIO+import Development.Shake.Plus+import RIO -- | Lifted version of `Development.Shake.getEnv` getEnv :: MonadAction m => String -> m (Maybe String)
src/Development/Shake/Plus/File.hs view
@@ -16,14 +16,14 @@ , removeFilesAfter ) where -import Control.Exception.Extra+import Control.Comonad.Env as E+import Control.Exception.Extra import qualified Development.Shake-import Development.Shake (FilePattern)-import Development.Shake.Plus.Core-import RIO-import qualified RIO.Text as T-import Path-import Within+import Development.Shake.Plus.Core+import Path+import RIO+import qualified RIO.Text as T+import Within -- | Lifted version of `Development.Shake.copyFile` with well-typed `Path`s. copyFile' :: (MonadAction m, Partial) => Path Rel File -> Path Rel File -> m ()@@ -47,8 +47,8 @@ readFileIn' x y = readFile' $ x </> y -- | Like 'readFile'`, but accepts a `Within` value.-readFileWithin :: MonadAction m => Within Rel File -> m Text-readFileWithin = readFile' . fromWithin+readFileWithin :: MonadAction m => Within Rel (Path Rel File) -> m Text+readFileWithin = readFile' . liftA2 (</>) E.ask extract -- | Lifted version of `Development.Shake.writeFile` with well-typed `Path`. writeFile' :: (MonadAction m, Partial) => Path Rel File -> Text -> m ()@@ -64,8 +64,8 @@ writeFileIn' x y = writeFile' $ x </> y -- | Like 'writeFile'`, but accepts a `Within` value.-writeFileWithin :: MonadAction m => Within Rel File -> Text -> m ()-writeFileWithin = writeFile' . fromWithin+writeFileWithin :: MonadAction m => Within Rel (Path Rel File) -> Text -> m ()+writeFileWithin = writeFile' . liftA2 (</>) E.ask extract -- | Lifted version of `Development.Shake.writeFileChanged` with well-typed `Path`. writeFileChanged :: (MonadAction m, Partial) => Path b File -> Text -> m ()@@ -77,8 +77,8 @@ writeFileChangedIn x y = writeFileChanged $ x </> y -- | Like `writeFileChanged'`, but accepts a `Within` value.-writeFileChangedWithin :: MonadAction m => Within Rel File -> Text -> m ()-writeFileChangedWithin = writeFileChanged . fromWithin +writeFileChangedWithin :: MonadAction m => Within Rel (Path Rel File) -> Text -> m ()+writeFileChangedWithin = writeFileChanged . liftA2 (</>) E.ask extract -- | Lifted version of `Development.Shake.removeFiles` with well-typed `Path`. removeFiles :: MonadAction m => Path b File -> [FilePattern] -> m ()
src/Development/Shake/Plus/FileRules.hs view
@@ -5,65 +5,66 @@ , wantP , needIn , wantIn-, needWithin-, wantWithin , (%>) , (|%>)+, (%^>)+, (|%^>) , phony ) where -import Control.Exception.Extra-import Development.Shake.Plus.Core+import Control.Comonad.Env as E+import Control.Exception.Extra import qualified Development.Shake-import Development.Shake (FilePattern)-import RIO-import Path-import Within+import qualified Development.Shake.FilePath+import Development.Shake.Plus.Core+import Path+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 -- use `needP`-need :: MonadAction m => [String] -> m ()+need :: (Partial, MonadAction m) => [String] -> m () need = liftAction . Development.Shake.need -- | Lifted version of `Development.Shake.want`. This still uses `String`s -- because it may refer to a phony rule. For the `Path` specific version -- use wantP.-want :: MonadRules m => [String] -> m ()+want :: (Partial, MonadRules m) => [String] -> m () want = liftRules . Development.Shake.want -- | Lifted version of `Development.Shake.need` using well-typed `Path`s-needP :: (MonadAction m, Partial) => [Path Rel File] -> m ()+needP :: (Partial, MonadAction m) => [Path Rel File] -> m () needP = need . map toFilePath -- | Lifted version of `Development.Shake.want` using well-typed `Path`s-wantP :: MonadRules m => [Path Rel File] -> m ()+wantP :: (Partial, MonadRules m) => [Path Rel File] -> m () wantP = want . map toFilePath -- | Like `needP`, but accepts `Path`s relative to the first argument.-needIn :: MonadAction m => Path Rel Dir -> [Path Rel File] -> m ()+needIn :: (Partial, MonadAction m) => Path Rel Dir -> [Path Rel File] -> m () needIn x = needP . fmap (x </>) -- | Like `wantP`, but accepts `Path`s relative to the first argument.-wantIn :: MonadRules m => Path Rel Dir -> [Path Rel File] -> m ()+wantIn :: (Partial, MonadRules m) => Path Rel Dir -> [Path Rel File] -> m () wantIn x = wantP . fmap (x </>) --- | Like `needP`, but accepts `Within` values.-needWithin :: MonadAction m => [Within Rel File] -> m ()-needWithin = needP . map fromWithin---- | Like `wantP`, but accepts `Within` values.-wantWithin :: MonadRules m => [Within Rel File] -> m ()-wantWithin = wantP . map fromWithin- -- | Lifted version of `Development.Shake.%>` using well-typed `Path`s (%>) :: (Partial, MonadReader r m, MonadRules m) => FilePattern -> (Path Rel File -> RAction r ()) -> m ()-(%>) x ract = ask >>= \r -> liftRules $ x Development.Shake.%> (runRAction r . (ract <=< parseRelFile))+(%>) x ract = R.ask >>= \r -> liftRules $ x Development.Shake.%> (runRAction r . (ract <=< parseRelFile)) -- | Lifted version of `Development.Shake.|%>` using well-typed `Path`s (|%>) :: (Partial, MonadReader r m, MonadRules m) => [FilePattern] -> (Path Rel File -> RAction r ()) -> m ()-(|%>) x ract = ask >>= \r -> liftRules $ x Development.Shake.|%> (runRAction r . (ract <=< parseRelFile))+(|%>) x ract = R.ask >>= \r -> liftRules $ x Development.Shake.|%> (runRAction r . (ract <=< parseRelFile)) --- | Lifted version of `Development.Shake.phony` using well-typed `Path`s and `RAction`+-- | `Within` variant of `(%>)`, used to keep track of local directories.+(%^>) :: (Partial, MonadReader r m, MonadRules m) => Within Rel FilePattern -> (Within Rel (Path Rel File) -> RAction r ()) -> m ()+(%^>) xs ract = liftA2 (Development.Shake.FilePath.</>) (toFilePath . E.ask) extract xs %> (ract <=< (`asWithin` E.ask xs))++-- | `Within` variant of `(%>)`, used to keep track of local directories.+(|%^>) :: (Partial, MonadReader r m, MonadRules m) => Within Rel [FilePattern] -> (Within Rel (Path Rel File) -> RAction r ()) -> m ()+(|%^>) xs ract = ((Development.Shake.FilePath.</>) (toFilePath . E.ask $ xs) <$> extract xs) |%> (ract <=< (`asWithin` E.ask xs))++-- | Lifted version of `Development.Shake.phony` using `RAction` phony :: (MonadReader r m, MonadRules m) => String -> RAction r () -> m ()-phony x ract = ask >>= \r -> liftRules $ Development.Shake.phony x $ runRAction r ract+phony x ract = R.ask >>= \r -> liftRules $ Development.Shake.phony x $ runRAction r ract
src/Development/Shake/Plus/Loaders.hs view
@@ -1,42 +1,46 @@ module Development.Shake.Plus.Loaders (- loadSortFilterApply-, loadSortFilterApplyW+ batchLoad+, batchLoadWithin+, batchLoadWithin' ) where -import Development.Shake.Plus.Core-import Development.Shake.Plus.Directory-import RIO-import RIO.List-import Path-import Within+import Development.Shake.Plus.Core+import Development.Shake.Plus.Directory+import Path+import RIO+import qualified RIO.HashMap as HM+import Within traverseToSnd :: Functor f => (a -> f b) -> a -> f (a, b) traverseToSnd f a = (a,) <$> f a --- | Batch loading function. Loads all items detected by the filtepattern and provides parameters--- for sorting, filtering and a simple transformation via an endofunction. Returns a list of values--- indexed by their source `Path`.-loadSortFilterApply :: (MonadAction m, Ord b)- => (Path Rel File -> m a) -- ^ A loading function, (i.e readFile' or a custom `readMarkdownFile, readJPG etc that returns a type you can sort/filter on.)- -> Path Rel Dir -- ^ The path to search in.- -> [FilePattern] -- ^ A filepattern to match on.- -> (a -> b) -- ^ The value to sortOn .- -> (a -> Bool) -- ^ A filtering predicate.- -> (a -> a) -- ^ A simple endotransformation.- -> m [(Path Rel File, a)]-loadSortFilterApply l dir pat s f e = do- xs <- getDirectoryFiles dir pat >>= mapM (traverseToSnd l)- return $ fmap (second e) $ sortOn (s . snd) $ filter (f . snd) $ xs+-- | Load a directory of `FilePattern`s via some loading function. This should+-- be a `Development.Shake.newCache` operation that takes full filepaths.+batchLoad :: MonadAction m+ => Path b Dir -- ^ The directory to search in+ -> [FilePattern] -- ^ A filepattern to match against.+ -> (Path b File -> m a) -- ^ A `Development.Shake.newCache` operation that loads the file and turns it into some `a`.+ -> m (HashMap (Path Rel File) a)+batchLoad dir pat f = do+ xs <- getDirectoryFiles dir pat >>= mapM (traverseToSnd $ f . fromWithin . (`within` dir))+ return . HM.fromList $ xs --- | Like `loadSortFilterApply`, but returns `Within` values.-loadSortFilterApplyW :: (MonadAction m, Ord b)- => (Within Rel File -> m a) -- ^ A loading function, (i.e readFile' or a custom `readMarkdownFile, readJPG etc that returns a type you can sort/filter on.)- -> Path Rel Dir -- ^ The path to search in.- -> [FilePattern] -- ^ A filepattern to match on.- -> (a -> b) -- ^ The value to sortOn .- -> (a -> Bool) -- ^ A filtering predicate.- -> (a -> a) -- ^ A simple endotransformation.- -> m [(Within Rel File, a)]-loadSortFilterApplyW l dir pat s f e = do- xs <- getDirectoryFilesWithin dir pat >>= mapM (traverseToSnd l)- return $ fmap (second e) $ sortOn (s . snd) $ filter (f . snd) $ xs+-- | Like `batchLoad`, but returns an `Within` of a `Dir` containing the `HashMap`+batchLoadWithin :: MonadAction m+ => Path b Dir -- ^ The directory to search in+ -> [FilePattern] -- ^ A filepattern to match against.+ -> (Path b File -> m a) -- ^ A `Development.Shake.newCache` operation that loads the file and turns it into some `a`.+ -> m (Within b (HashMap (Path Rel File) a))+batchLoadWithin dir pat f = do+ xs <- getDirectoryFiles dir pat >>= mapM (traverseToSnd $ f . fromWithin . (`within` dir))+ return $ (`within` dir) $ HM.fromList xs++-- | Like `batchLoadWithin'`, but returns a `HashMap` containing `Within` values instead of an `Within` of a `Hashmap`.+batchLoadWithin' :: MonadAction m+ => Path b Dir -- ^ The directory to search in+ -> [FilePattern] -- ^ A filepattern to match against.+ -> (Path b File -> m a) -- ^ A `Development.Shake.newCache` operation that loads the file and turns it into some `a`.+ -> m (HashMap (Within b (Path Rel File)) a)+batchLoadWithin' dir pat f = do+ xs <- getDirectoryFiles dir pat >>= mapM (traverseToSnd $ f . fromWithin . (`within` dir))+ return $ HM.fromList (first (`within` dir) <$> xs)
src/Development/Shake/Plus/Oracle.hs view
@@ -6,11 +6,11 @@ , askOracles ) where -import Control.Exception.Extra+import Control.Exception.Extra+import Development.Shake (RuleResult, ShakeValue) import qualified Development.Shake-import Development.Shake (RuleResult, ShakeValue)-import Development.Shake.Plus.Core-import RIO+import Development.Shake.Plus.Core+import RIO -- | Lifted version of `Development.Shake.addOracle` using `RAction` runner. addOracle :: (MonadRules m, MonadReader r m, RuleResult q ~ a, ShakeValue q, ShakeValue a, Partial)@@ -37,4 +37,4 @@ -- | Lifted version of `Development.Shake.askOracles`. askOracles :: (MonadAction m, RuleResult q ~ a, ShakeValue q, ShakeValue a) => [q]-> m [a] askOracles = liftAction . Development.Shake.askOracles- +
src/Development/Shake/Plus/Temp.hs view
@@ -6,9 +6,9 @@ ) where import qualified Development.Shake-import Development.Shake.Plus.Core-import RIO hiding (withTempFile)-import Path+import Development.Shake.Plus.Core+import Path+import RIO hiding (withTempFile) -- | Unlifted version of `Development.Shake.withTempFile` with well-typed `Path`. withTempFile :: (MonadUnliftAction m, MonadThrow m) => (Path Rel File -> m a) -> m a