{-# LANGUAGE FlexibleInstances, TypeSynonymInstances,
TypeFamilies, ExistentialQuantification #-}
module Shelly.Pipe
(
Sh, shs, shelly, shellyFailDir, shsFailDir, sub, silently, verbosely, escaping, print_stdout, print_commands, tracing, errExit, log_stdout_with, log_stderr_with
, roll, unroll, liftSh
, FoldCallback
, run, run_, runFoldLines, cmd
, (-|-), lastStderr, setStdin, lastExitCode
, command, command_, command1, command1_
, sshPairs, sshPairs_
, setenv, get_env, get_env_text, get_env_def, appendToPath, prependToPath
, cd, chdir, pwd
, echo, echo_n, echo_err, echo_n_err, inspect, inspect_err
, tag, trace, show_command
, ls, lsT, test_e, test_f, test_d, test_s, which
, absPath, (</>), (<.>), canonic, canonicalize, relPath, relativeTo
, hasExt
, mv, rm, rm_f, rm_rf, cp, cp_r, mkdir, mkdir_p, mkdirTree
, readfile, readBinary, writefile, appendfile, touchfile, withTmpDir
, exit, errorExit, quietExit, terror
, catchany, catch_sh, finally_sh
, ShellyHandler(..), catches_sh
, catchany_sh
, toTextIgnore, toTextWarn, S.fromText
, (<$>), whenM, unlessM, time
, liftIO, when, unless, FilePath
, get, put
, find, findWhen, findFold
, findDirFilter, findDirFilterWhen, findFoldDirFilter
, followSymlink
) where
import Prelude hiding (FilePath)
import Control.Applicative
import Control.Monad
import Control.Monad.Trans
import Control.Exception hiding (handle)
import System.FilePath(FilePath)
import qualified Shelly as S
import Shelly(
(</>), (<.>), hasExt
, whenM, unlessM, toTextIgnore
, catchany
, FoldCallback)
import Data.Maybe(fromMaybe)
import Shelly.Base(State)
import Data.ByteString (ByteString)
import Data.Tree(Tree)
import Data.Text as T hiding (concat, all, find, cons)
newtype Sh a = Sh { unSh :: S.Sh [a] }
instance Functor Sh where
fmap f = Sh . fmap (fmap f) . unSh
instance Monad Sh where
return = Sh . return . return
a >>= f = Sh $ fmap concat $ mapM (unSh . f) =<< unSh a
a >> b = Sh $ unSh a >> unSh b
instance Applicative Sh where
pure = return
(<*>) = ap
instance Alternative Sh where
empty = mzero
(<|>) = mplus
instance MonadPlus Sh where
mzero = Sh $ return []
mplus a b = Sh $ liftA2 (++) (unSh a) (unSh b)
instance MonadIO Sh where
liftIO = sh1 liftIO
sh0 :: S.Sh a -> Sh a
sh0 = Sh . fmap return
sh1 :: (a -> S.Sh b) -> (a -> Sh b)
sh1 f = \a -> sh0 (f a)
sh2 :: (a1 -> a2 -> S.Sh b) -> (a1 -> a2 -> Sh b)
sh2 f = \a b -> sh0 (f a b)
sh3 :: (a1 -> a2 -> a3 -> S.Sh b) -> (a1 -> a2 -> a3 -> Sh b)
sh3 f = \a b c -> sh0 (f a b c)
sh4 :: (a1 -> a2 -> a3 -> a4 -> S.Sh b) -> (a1 -> a2 -> a3 -> a4 -> Sh b)
sh4 f = \a b c d -> sh0 (f a b c d)
sh0s :: S.Sh [a] -> Sh a
sh0s = Sh
sh1s :: (a -> S.Sh [b]) -> (a -> Sh b)
sh1s f = \a -> sh0s (f a)
lift1 :: (S.Sh a -> S.Sh b) -> (Sh a -> Sh b)
lift1 f = Sh . (mapM (f . return) =<< ) . unSh
lift2 :: (S.Sh a -> S.Sh b -> S.Sh c) -> (Sh a -> Sh b -> Sh c)
lift2 f a b = Sh $ join $ liftA2 (mapM2 f') (unSh a) (unSh b)
where f' = \x y -> f (return x) (return y)
mapM2 :: Monad m => (a -> b -> m c)-> [a] -> [b] -> m [c]
mapM2 f as bs = sequence $ liftA2 f as bs
unroll :: Sh a -> Sh [a]
unroll = Sh . fmap return . unSh
roll :: Sh [a] -> Sh a
roll = Sh . fmap concat . unSh
liftSh :: ([a] -> [b]) -> Sh a -> Sh b
liftSh f = Sh . fmap f . unSh
shelly :: MonadIO m => Sh a -> m [a]
shelly = S.shelly . unSh
shs :: MonadIO m => Sh () -> m ()
shs x = shelly x >> return ()
shellyFailDir :: MonadIO m => Sh a -> m [a]
shellyFailDir = S.shellyFailDir . unSh
shsFailDir :: MonadIO m => Sh () -> m ()
shsFailDir x = shellyFailDir x >> return ()
sub :: Sh a -> Sh a
sub = lift1 S.sub
silently :: Sh a -> Sh a
silently = lift1 S.silently
verbosely :: Sh a -> Sh a
verbosely = lift1 S.verbosely
escaping :: Bool -> Sh a -> Sh a
escaping b = lift1 (S.escaping b)
log_stdout_with :: (Text -> IO ()) -> Sh a -> Sh a
log_stdout_with logger = lift1 (S.log_stdout_with logger)
log_stderr_with :: (Text -> IO ()) -> Sh a -> Sh a
log_stderr_with logger = lift1 (S.log_stdout_with logger)
print_stdout :: Bool -> Sh a -> Sh a
print_stdout b = lift1 (S.print_stdout b)
print_commands :: Bool -> Sh a -> Sh a
print_commands b = lift1 (S.print_commands b)
tracing :: Bool -> Sh a -> Sh a
tracing b = lift1 (S.tracing b)
errExit :: Bool -> Sh a -> Sh a
errExit b = lift1 (S.errExit b)
followSymlink :: Bool -> Sh a -> Sh a
followSymlink b = lift1 (S.followSymlink b)
run :: FilePath -> [Text] -> Sh Text
run a b = sh0 $ S.run a b
run_ :: FilePath -> [Text] -> Sh ()
run_ a b = sh0 $ S.run_ a b
runFoldLines :: a -> FoldCallback a -> FilePath -> [Text] -> Sh a
runFoldLines a cb fp ts = sh0 $ S.runFoldLines a cb fp ts
(-|-) :: Sh Text -> Sh b -> Sh b
(-|-) = lift2 (S.-|-)
lastStderr :: Sh Text
lastStderr = sh0 S.lastStderr
setStdin :: Text -> Sh ()
setStdin = sh1 S.setStdin
lastExitCode :: Sh Int
lastExitCode = sh0 S.lastExitCode
command :: FilePath -> [Text] -> [Text] -> Sh Text
command = sh3 S.command
command_ :: FilePath -> [Text] -> [Text] -> Sh ()
command_ = sh3 S.command_
command1 :: FilePath -> [Text] -> Text -> [Text] -> Sh Text
command1 = sh4 S.command1
command1_ :: FilePath -> [Text] -> Text -> [Text] -> Sh ()
command1_ = sh4 S.command1_
sshPairs :: Text -> [(FilePath, [Text])] -> Sh Text
sshPairs = sh2 S.sshPairs
sshPairs_ :: Text -> [(FilePath, [Text])] -> Sh ()
sshPairs_ = sh2 S.sshPairs_
setenv :: Text -> Text -> Sh ()
setenv = sh2 S.setenv
get_env :: Text -> Sh (Maybe Text)
get_env = sh1 S.get_env
get_env_text :: Text -> Sh Text
get_env_text = sh1 S.get_env_text
get_env_def :: Text -> Text -> Sh Text
get_env_def a d = sh0 $ fmap (fromMaybe d) $ S.get_env a
{-# DEPRECATED get_env_def "use fromMaybe DEFAULT get_env" #-}
appendToPath :: FilePath -> Sh ()
appendToPath = sh1 S.appendToPath
prependToPath :: FilePath -> Sh ()
prependToPath = sh1 S.prependToPath
cd :: FilePath -> Sh ()
cd = sh1 S.cd
chdir :: FilePath -> Sh a -> Sh a
chdir p = lift1 (S.chdir p)
pwd :: Sh FilePath
pwd = sh0 S.pwd
echo, echo_n_err, echo_err, echo_n :: Text -> Sh ()
echo = sh1 S.echo
echo_n_err = sh1 S.echo_n_err
echo_err = sh1 S.echo_err
echo_n = sh1 S.echo_n
inspect :: Show s => s -> Sh ()
inspect = sh1 S.inspect
inspect_err :: Show s => s -> Sh ()
inspect_err = sh1 S.inspect_err
tag :: Sh a -> Text -> Sh a
tag a t = lift1 (flip S.tag t) a
trace :: Text -> Sh ()
trace = sh1 S.trace
show_command :: FilePath -> [Text] -> Text
show_command = S.show_command
ls :: FilePath -> Sh FilePath
ls = sh1s S.ls
lsT :: FilePath -> Sh Text
lsT = sh1s S.lsT
test_e :: FilePath -> Sh Bool
test_e = sh1 S.test_e
test_f :: FilePath -> Sh Bool
test_f = sh1 S.test_f
test_d :: FilePath -> Sh Bool
test_d = sh1 S.test_d
test_s :: FilePath -> Sh Bool
test_s = sh1 S.test_s
which :: FilePath -> Sh (Maybe FilePath)
which = sh1 S.which
absPath :: FilePath -> Sh FilePath
absPath = sh1 S.absPath
canonic :: FilePath -> Sh FilePath
canonic = sh1 S.canonic
canonicalize :: FilePath -> Sh FilePath
canonicalize = sh1 S.canonicalize
relPath :: FilePath -> Sh FilePath
relPath = sh1 S.relPath
relativeTo :: FilePath
-> FilePath
-> Sh FilePath
relativeTo = sh2 S.relativeTo
mv :: FilePath -> FilePath -> Sh ()
mv = sh2 S.mv
rm :: FilePath -> Sh ()
rm = sh1 S.rm
rm_f :: FilePath -> Sh ()
rm_f = sh1 S.rm_f
rm_rf :: FilePath -> Sh ()
rm_rf = sh1 S.rm_rf
cp :: FilePath -> FilePath -> Sh ()
cp = sh2 S.cp
cp_r :: FilePath -> FilePath -> Sh ()
cp_r = sh2 S.cp_r
mkdir :: FilePath -> Sh ()
mkdir = sh1 S.mkdir
mkdir_p :: FilePath -> Sh ()
mkdir_p = sh1 S.mkdir_p
mkdirTree :: Tree FilePath -> Sh ()
mkdirTree = sh1 S.mkdirTree
readfile :: FilePath -> Sh Text
readfile = sh1 S.readfile
readBinary :: FilePath -> Sh ByteString
readBinary = sh1 S.readBinary
writefile :: FilePath -> Text -> Sh ()
writefile = sh2 S.writefile
touchfile :: FilePath -> Sh ()
touchfile = sh1 S.touchfile
appendfile :: FilePath -> Text -> Sh ()
appendfile = sh2 S.appendfile
withTmpDir :: (FilePath -> Sh a) -> Sh a
withTmpDir f = Sh $ S.withTmpDir (unSh . f)
find :: FilePath -> Sh FilePath
find = sh1s S.find
findWhen :: (FilePath -> Sh Bool) -> FilePath -> Sh FilePath
findWhen p a = Sh $ S.findWhen (fmap and . unSh . p) a
findFold :: (a -> FilePath -> Sh a) -> a -> FilePath -> Sh a
findFold cons nil a = Sh $ S.findFold cons' nil' a
where nil' = return nil
cons' as dir = unSh $ roll $ mapM (flip cons dir) as
findDirFilter :: (FilePath -> Sh Bool) -> FilePath -> Sh FilePath
findDirFilter p a = Sh $ S.findDirFilter (fmap and . unSh . p) a
findDirFilterWhen :: (FilePath -> Sh Bool)
-> (FilePath -> Sh Bool)
-> FilePath
-> Sh FilePath
findDirFilterWhen dirPred filePred a =
Sh $ S.findDirFilterWhen
(fmap and . unSh . dirPred)
(fmap and . unSh . filePred)
a
findFoldDirFilter :: (a -> FilePath -> Sh a) -> a -> (FilePath -> Sh Bool) -> FilePath -> Sh a
findFoldDirFilter cons nil p a = Sh $ S.findFoldDirFilter cons' nil' p' a
where p' = fmap and . unSh . p
nil' = return nil
cons' as dir = unSh $ roll $ mapM (flip cons dir) as
exit :: Int -> Sh ()
exit = sh1 S.exit
errorExit :: Text -> Sh ()
errorExit = sh1 S.errorExit
quietExit :: Int -> Sh ()
quietExit = sh1 S.quietExit
terror :: Text -> Sh a
terror = sh1 S.terror
catch_sh :: (Exception e) => Sh a -> (e -> Sh a) -> Sh a
catch_sh a f = Sh $ S.catch_sh (unSh a) (unSh . f)
catchany_sh :: Sh a -> (SomeException -> Sh a) -> Sh a
catchany_sh = catch_sh
finally_sh :: Sh a -> Sh b -> Sh a
finally_sh = lift2 S.finally_sh
time :: Sh a -> Sh (Double, a)
time = lift1 S.time
data ShellyHandler a = forall e . Exception e => ShellyHandler (e -> Sh a)
catches_sh :: Sh a -> [ShellyHandler a] -> Sh a
catches_sh a hs = Sh $ S.catches_sh (unSh a) (fmap convert hs)
where convert :: ShellyHandler a -> S.ShellyHandler [a]
convert (ShellyHandler f) = S.ShellyHandler (unSh . f)
toTextWarn :: FilePath -> Sh Text
toTextWarn = sh1 S.toTextWarn
get :: Sh State
get = sh0 S.get
put :: State -> Sh ()
put = sh1 S.put
class ShellArg a where toTextArg :: a -> Text
instance ShellArg Text where toTextArg = id
instance ShellArg FilePath where toTextArg = toTextIgnore
class ShellCommand t where
cmdAll :: FilePath -> [Text] -> t
instance ShellCommand (Sh Text) where
cmdAll fp args = run fp args
instance (s ~ Text, Show s) => ShellCommand (Sh s) where
cmdAll fp args = run fp args
instance ShellCommand (Sh ()) where
cmdAll fp args = run_ fp args
instance (ShellArg arg, ShellCommand result) => ShellCommand (arg -> result) where
cmdAll fp acc = \x -> cmdAll fp (acc ++ [toTextArg x])
cmd :: (ShellCommand result) => FilePath -> result
cmd fp = cmdAll fp []