{- |
   Module     : Development.Shake.Plus.FileRules
   License    : MIT
   Stability  : experimental

Filerules in "Development.Shake" lifted to `MonadAction` and well-typed `Path`s.
-}
module Development.Shake.Plus.FileRules (
  need
, want
, needP
, wantP
, needIn
, wantIn
, (%>)
, (|%>)
, phony
) where

import           Control.Exception.Extra
import qualified Development.Shake
import           Development.Shake.Plus.Core
import           Path
import           RIO                         as R

-- | 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 :: (Partial, MonadAction m, Foldable t) => t String -> m ()
need :: t String -> m ()
need = Action () -> m ()
forall (m :: * -> *) a. MonadAction m => Action a -> m a
liftAction (Action () -> m ()) -> (t String -> Action ()) -> t String -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Partial => [String] -> Action ()
[String] -> Action ()
Development.Shake.need ([String] -> Action ())
-> (t String -> [String]) -> t String -> Action ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. t String -> [String]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList

-- | 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 :: (Partial, MonadRules m, Foldable t) => t String -> m ()
want :: t String -> m ()
want = Rules () -> m ()
forall (m :: * -> *) a. MonadRules m => Rules a -> m a
liftRules (Rules () -> m ()) -> (t String -> Rules ()) -> t String -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Partial => [String] -> Rules ()
[String] -> Rules ()
Development.Shake.want ([String] -> Rules ())
-> (t String -> [String]) -> t String -> Rules ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. t String -> [String]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList

-- | Lifted version of `Development.Shake.need` using well-typed `Path`s
needP :: (Partial, MonadAction m, Traversable t) => t (Path b File) -> m ()
needP :: t (Path b File) -> m ()
needP = t String -> m ()
forall (m :: * -> *) (t :: * -> *).
(Partial, MonadAction m, Foldable t) =>
t String -> m ()
need (t String -> m ())
-> (t (Path b File) -> t String) -> t (Path b File) -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Path b File -> String) -> t (Path b File) -> t String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Path b File -> String
forall b t. Path b t -> String
toFilePath

-- | Lifted version of `Development.Shake.want` using well-typed `Path`s
wantP :: (Partial, MonadRules m, Traversable t) => t (Path b File) -> m ()
wantP :: t (Path b File) -> m ()
wantP = t String -> m ()
forall (m :: * -> *) (t :: * -> *).
(Partial, MonadRules m, Foldable t) =>
t String -> m ()
want (t String -> m ())
-> (t (Path b File) -> t String) -> t (Path b File) -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Path b File -> String) -> t (Path b File) -> t String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Path b File -> String
forall b t. Path b t -> String
toFilePath

-- | Like `needP`, but accepts `Path`s relative to the first argument.
needIn :: (Partial, MonadAction m, Traversable t) => Path b Dir -> t (Path Rel File) -> m ()
needIn :: Path b Dir -> t (Path Rel File) -> m ()
needIn Path b Dir
x = t (Path b File) -> m ()
forall (m :: * -> *) (t :: * -> *) b.
(Partial, MonadAction m, Traversable t) =>
t (Path b File) -> m ()
needP (t (Path b File) -> m ())
-> (t (Path Rel File) -> t (Path b File))
-> t (Path Rel File)
-> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Path Rel File -> Path b File)
-> t (Path Rel File) -> t (Path b File)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Path b Dir
x Path b Dir -> Path Rel File -> Path b File
forall b t. Path b Dir -> Path Rel t -> Path b t
</>)

-- | Like `wantP`, but accepts `Path`s relative to the first argument.
wantIn :: (Partial, MonadRules m, Traversable t) => Path b Dir -> t (Path Rel File) -> m ()
wantIn :: Path b Dir -> t (Path Rel File) -> m ()
wantIn Path b Dir
x = t (Path b File) -> m ()
forall (m :: * -> *) (t :: * -> *) b.
(Partial, MonadRules m, Traversable t) =>
t (Path b File) -> m ()
wantP (t (Path b File) -> m ())
-> (t (Path Rel File) -> t (Path b File))
-> t (Path Rel File)
-> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Path Rel File -> Path b File)
-> t (Path Rel File) -> t (Path b File)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Path b Dir
x Path b Dir -> Path Rel File -> Path b File
forall b t. Path b Dir -> Path Rel t -> Path b t
</>)

-- | Lifted version of `Development.Shake.%>` using well-typed `Path`s
(%>) :: (Partial, MonadReader r m, MonadRules m) => FilePattern -> (Path Rel File -> RAction r ()) -> m ()
%> :: String -> (Path Rel File -> RAction r ()) -> m ()
(%>) String
x Path Rel File -> RAction r ()
ract = m r
forall r (m :: * -> *). MonadReader r m => m r
R.ask m r -> (r -> m ()) -> m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \r
r -> Rules () -> m ()
forall (m :: * -> *) a. MonadRules m => Rules a -> m a
liftRules (Rules () -> m ()) -> Rules () -> m ()
forall a b. (a -> b) -> a -> b
$ String
x Partial => String -> (String -> Action ()) -> Rules ()
String -> (String -> Action ()) -> Rules ()
Development.Shake.%> (r -> RAction r () -> Action ()
forall (m :: * -> *) env a.
MonadAction m =>
env -> RAction env a -> m a
runRAction r
r (RAction r () -> Action ())
-> (String -> RAction r ()) -> String -> Action ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Path Rel File -> RAction r ()
ract (Path Rel File -> RAction r ())
-> (String -> RAction r (Path Rel File)) -> String -> RAction r ()
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< String -> RAction r (Path Rel File)
forall (m :: * -> *). MonadThrow m => String -> m (Path Rel File)
parseRelFile))

-- | Lifted version of `Development.Shake.|%>` using well-typed `Path`s
(|%>) :: (Partial, MonadReader r m, MonadRules m) => [FilePattern] -> (Path Rel File -> RAction r ()) -> m ()
|%> :: [String] -> (Path Rel File -> RAction r ()) -> m ()
(|%>) [String]
x Path Rel File -> RAction r ()
ract = m r
forall r (m :: * -> *). MonadReader r m => m r
R.ask m r -> (r -> m ()) -> m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \r
r -> Rules () -> m ()
forall (m :: * -> *) a. MonadRules m => Rules a -> m a
liftRules (Rules () -> m ()) -> Rules () -> m ()
forall a b. (a -> b) -> a -> b
$ [String]
x Partial => [String] -> (String -> Action ()) -> Rules ()
[String] -> (String -> Action ()) -> Rules ()
Development.Shake.|%> (r -> RAction r () -> Action ()
forall (m :: * -> *) env a.
MonadAction m =>
env -> RAction env a -> m a
runRAction r
r (RAction r () -> Action ())
-> (String -> RAction r ()) -> String -> Action ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Path Rel File -> RAction r ()
ract (Path Rel File -> RAction r ())
-> (String -> RAction r (Path Rel File)) -> String -> RAction r ()
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< String -> RAction r (Path Rel File)
forall (m :: * -> *). MonadThrow m => String -> m (Path Rel File)
parseRelFile))

-- | Lifted version of `Development.Shake.phony` using `RAction`
phony :: (MonadReader r m, MonadRules m) => String -> RAction r () -> m ()
phony :: String -> RAction r () -> m ()
phony String
x RAction r ()
ract = m r
forall r (m :: * -> *). MonadReader r m => m r
R.ask m r -> (r -> m ()) -> m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \r
r -> Rules () -> m ()
forall (m :: * -> *) a. MonadRules m => Rules a -> m a
liftRules (Rules () -> m ()) -> Rules () -> m ()
forall a b. (a -> b) -> a -> b
$ Partial => String -> Action () -> Rules ()
String -> Action () -> Rules ()
Development.Shake.phony String
x (Action () -> Rules ()) -> Action () -> Rules ()
forall a b. (a -> b) -> a -> b
$ r -> RAction r () -> Action ()
forall (m :: * -> *) env a.
MonadAction m =>
env -> RAction env a -> m a
runRAction r
r RAction r ()
ract