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

File utilities in "Development.Shake" lifted to `MonadAction` and
well-typed `Path`s.
-}
module Development.Shake.Plus.File (
  copyFile
, copyFileChanged
, readFile'
, readFileLines
, readFileIn'
, writeFile'
, writeFileLines
, writeFileIn'
, writeFileChanged
, writeFileChangedIn
, removeFiles
, removeFilesAfter
) where

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

-- | Lifted version of `Development.Shake.copyFile` with well-typed filepaths.
copyFile :: (MonadAction m, Partial) => Path b File -> Path b' File -> m ()
copyFile :: Path b File -> Path b' File -> m ()
copyFile Path b File
x Path b' File
y = Action () -> m ()
forall (m :: * -> *) a. MonadAction m => Action a -> m a
liftAction (Action () -> m ()) -> Action () -> m ()
forall a b. (a -> b) -> a -> b
$ Partial => FilePath -> FilePath -> Action ()
FilePath -> FilePath -> Action ()
Development.Shake.copyFile' (Path b File -> FilePath
forall b t. Path b t -> FilePath
toFilePath Path b File
x) (Path b' File -> FilePath
forall b t. Path b t -> FilePath
toFilePath Path b' File
y)

-- | Lifted version of `Development.Shake.copyFileChanged'` with well-typed filepaths.
copyFileChanged :: (MonadAction m, Partial) => Path b File -> Path b' File -> m ()
copyFileChanged :: Path b File -> Path b' File -> m ()
copyFileChanged Path b File
x Path b' File
y = Action () -> m ()
forall (m :: * -> *) a. MonadAction m => Action a -> m a
liftAction (Action () -> m ()) -> Action () -> m ()
forall a b. (a -> b) -> a -> b
$ Partial => FilePath -> FilePath -> Action ()
FilePath -> FilePath -> Action ()
Development.Shake.copyFileChanged (Path b File -> FilePath
forall b t. Path b t -> FilePath
toFilePath Path b File
x) (Path b' File -> FilePath
forall b t. Path b t -> FilePath
toFilePath Path b' File
y)

-- | Lifted version of `Development.Shake.readFile'` with a well-typed filepath.
readFile' :: (MonadAction m, Partial) => Path b File -> m Text
readFile' :: Path b File -> m Text
readFile' = Action Text -> m Text
forall (m :: * -> *) a. MonadAction m => Action a -> m a
liftAction (Action Text -> m Text)
-> (Path b File -> Action Text) -> Path b File -> m Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath -> Text) -> Action FilePath -> Action Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap FilePath -> Text
T.pack (Action FilePath -> Action Text)
-> (Path b File -> Action FilePath) -> Path b File -> Action Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Partial => FilePath -> Action FilePath
FilePath -> Action FilePath
Development.Shake.readFile' (FilePath -> Action FilePath)
-> (Path b File -> FilePath) -> Path b File -> Action FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Path b File -> FilePath
forall b t. Path b t -> FilePath
toFilePath

-- | Lifted version of `Development.Shake.readFileLines` a well-typed filepath.
readFileLines :: (MonadAction m, Partial) => Path b File -> m [Text]
readFileLines :: Path b File -> m [Text]
readFileLines = Action [Text] -> m [Text]
forall (m :: * -> *) a. MonadAction m => Action a -> m a
liftAction (Action [Text] -> m [Text])
-> (Path b File -> Action [Text]) -> Path b File -> m [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([FilePath] -> [Text]) -> Action [FilePath] -> Action [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((FilePath -> Text) -> [FilePath] -> [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap FilePath -> Text
T.pack) (Action [FilePath] -> Action [Text])
-> (Path b File -> Action [FilePath])
-> Path b File
-> Action [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Partial => FilePath -> Action [FilePath]
FilePath -> Action [FilePath]
Development.Shake.readFileLines (FilePath -> Action [FilePath])
-> (Path b File -> FilePath) -> Path b File -> Action [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Path b File -> FilePath
forall b t. Path b t -> FilePath
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, Partial) => Path b Dir -> Path Rel File -> m Text
readFileIn' :: Path b Dir -> Path Rel File -> m Text
readFileIn' Path b Dir
x Path Rel File
y = Path b File -> m Text
forall (m :: * -> *) b.
(MonadAction m, Partial) =>
Path b File -> m Text
readFile' (Path b File -> m Text) -> Path b File -> m Text
forall a b. (a -> b) -> a -> b
$ 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
</> Path Rel File
y

-- | Lifted version of `Development.Shake.writeFile` a well-typed filepath.
writeFile' :: (MonadAction m, Partial) => Path b File -> Text -> m ()
writeFile' :: Path b File -> Text -> m ()
writeFile' Path b File
x Text
y = Action () -> m ()
forall (m :: * -> *) a. MonadAction m => Action a -> m a
liftAction (Action () -> m ()) -> Action () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> Action ()
forall (m :: * -> *).
(MonadIO m, Partial) =>
FilePath -> FilePath -> m ()
Development.Shake.writeFile' (Path b File -> FilePath
forall b t. Path b t -> FilePath
toFilePath Path b File
x) (Text -> FilePath
T.unpack Text
y)

-- | Lifted version of `Development.Shake.writeFileLines` with a well-typed filepath..
writeFileLines :: (MonadAction m, Partial) => Path b File -> [Text] -> m ()
writeFileLines :: Path b File -> [Text] -> m ()
writeFileLines Path b File
x [Text]
y = Action () -> m ()
forall (m :: * -> *) a. MonadAction m => Action a -> m a
liftAction (Action () -> m ()) -> Action () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> [FilePath] -> Action ()
forall (m :: * -> *).
(MonadIO m, Partial) =>
FilePath -> [FilePath] -> m ()
Development.Shake.writeFileLines (Path b File -> FilePath
forall b t. Path b t -> FilePath
toFilePath Path b File
x) ((Text -> FilePath) -> [Text] -> [FilePath]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> FilePath
T.unpack [Text]
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, Partial) => Path b Dir -> Path Rel File -> Text -> m ()
writeFileIn' :: Path b Dir -> Path Rel File -> Text -> m ()
writeFileIn' Path b Dir
x Path Rel File
y = Path b File -> Text -> m ()
forall (m :: * -> *) b.
(MonadAction m, Partial) =>
Path b File -> Text -> m ()
writeFile' (Path b File -> Text -> m ()) -> Path b File -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ 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
</> Path Rel File
y

-- | Lifted version of `Development.Shake.writeFileChanged` with a well-typed filepath.
writeFileChanged :: (MonadAction m, Partial) => Path b File -> Text -> m ()
writeFileChanged :: Path b File -> Text -> m ()
writeFileChanged Path b File
x Text
y = Action () -> m ()
forall (m :: * -> *) a. MonadAction m => Action a -> m a
liftAction (Action () -> m ()) -> Action () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> Action ()
forall (m :: * -> *).
(MonadIO m, Partial) =>
FilePath -> FilePath -> m ()
Development.Shake.writeFileChanged (Path b File -> FilePath
forall b t. Path b t -> FilePath
toFilePath Path b File
x) (Text -> FilePath
T.unpack Text
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, Partial) => Path b Dir -> Path Rel File -> Text -> m ()
writeFileChangedIn :: Path b Dir -> Path Rel File -> Text -> m ()
writeFileChangedIn Path b Dir
x Path Rel File
y = Path b File -> Text -> m ()
forall (m :: * -> *) b.
(MonadAction m, Partial) =>
Path b File -> Text -> m ()
writeFileChanged (Path b File -> Text -> m ()) -> Path b File -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ 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
</> Path Rel File
y

-- | Lifted version of `Development.Shake.removeFiles` that accepts a well-typed directory.
removeFiles :: MonadAction m => Path b Dir -> [FilePattern] -> m ()
removeFiles :: Path b Dir -> [FilePath] -> m ()
removeFiles Path b Dir
x [FilePath]
y = Action () -> m ()
forall (m :: * -> *) a. MonadAction m => Action a -> m a
liftAction (Action () -> m ()) -> (IO () -> Action ()) -> IO () -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO () -> Action ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> [FilePath] -> IO ()
Development.Shake.removeFiles (Path b Dir -> FilePath
forall b t. Path b t -> FilePath
toFilePath Path b Dir
x) [FilePath]
y

-- | Lifted version of `Development.Shake.removeFilesAfter` that accepts a well-typed directory.
removeFilesAfter :: MonadAction m => Path b Dir -> [FilePattern] -> m ()
removeFilesAfter :: Path b Dir -> [FilePath] -> m ()
removeFilesAfter Path b Dir
x [FilePath]
y = Action () -> m ()
forall (m :: * -> *) a. MonadAction m => Action a -> m a
liftAction (Action () -> m ()) -> Action () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> [FilePath] -> Action ()
Development.Shake.removeFilesAfter (Path b Dir -> FilePath
forall b t. Path b t -> FilePath
toFilePath Path b Dir
x) [FilePath]
y