module System.Handsy
( Handsy
, run
, shell
, command
, readFile
, writeFile
, appendFile
, shell_
, command_
, CommandOptions (..)
, Options (..)
, ExitCode (..)
, def
) where
import Prelude hiding (appendFile, readFile,
writeFile)
import Data.Bool
import qualified Data.ByteString.Char8 as C8
import qualified Data.ByteString.Lazy as B
import qualified Data.ByteString.Lazy.Char8 as C
import System.Exit
import Data.Default.Class
import System.Process.ByteString.Lazy
import Text.ShellEscape
import System.Handsy.Internal hiding (shell)
import qualified System.Handsy.Internal as I
command :: FilePath
-> [String]
-> CommandOptions
-> Handsy (ExitCode, B.ByteString, B.ByteString)
command cmd args opts = let cmd' = C8.unpack . C8.intercalate " " . map (bytes . bash . C8.pack) $ (cmd:args)
in shell cmd' opts
shell :: String
-> CommandOptions
-> Handsy (ExitCode, B.ByteString, B.ByteString)
shell cmd opts = let esc = C8.unpack . bytes . bash . C8.pack
CommandOptions stdin' cwd' = opts
in I.shell (bool ("cd " ++ esc cwd' ++ "; ") "" (null cwd') ++ cmd) stdin'
data CommandOptions =
CommandOptions { stdin :: B.ByteString
, cwd :: String
}
deriving Show
instance Default CommandOptions where
def = CommandOptions "" ""
readFile :: FilePath -> Handsy B.ByteString
readFile fp = command "cat" [fp] def >>= \case
(ExitSuccess, stdout, _) -> return stdout
(_, _, stderr) -> error $ "Error reading " ++ fp ++ "\nStderr was: " ++ C.unpack stderr
writeFile :: FilePath -> B.ByteString -> Handsy ()
writeFile fp s = command "dd" ["of=" ++ fp] def{stdin=s} >>= \case
(ExitSuccess, _, _) -> return ()
(_, _, stderr) -> error $ "Error writing to " ++ fp ++ "\nStderr was: " ++ C.unpack stderr
appendFile :: FilePath -> B.ByteString -> Handsy ()
appendFile fp s = command "dd" ["of=" ++ fp, "conv=notrunc", "oflag=append"] def{stdin=s} >>= \case
(ExitSuccess, _, _) -> return ()
(_, _, stderr) -> error $ "Error appending to " ++ fp ++ "\nStderr was: " ++ C.unpack stderr
command_ :: FilePath -> [String] -> CommandOptions -> Handsy (B.ByteString, B.ByteString)
command_ path args opts = command path args opts >>= \case
(ExitFailure code, _, stderr) -> error ('`':path ++ ' ' : show args ++ "` returned " ++ show code
++ "\nStderr was: " ++ C.unpack stderr)
(ExitSuccess, stdout, stderr) -> return (stdout, stderr)
shell_ :: String -> CommandOptions -> Handsy (B.ByteString, B.ByteString)
shell_ cmd opts = shell cmd opts >>= \case
(ExitFailure code, _, stderr) -> error ('`':cmd ++ "` returned " ++ show code
++ "\nStderr was: " ++ C.unpack stderr)
(ExitSuccess, stdout, stderr) -> return (stdout, stderr)
run :: Options -> Handsy a -> IO a
run = interpretSimple (\cmdline -> readProcessWithExitCode "bash" ["-c", cmdline])