module SimpleCmd (
cmd, cmd_,
cmdBool,
cmdIgnoreErr,
cmdLines,
cmdlog,
cmdMaybe,
cmdN,
cmdQuiet,
cmdSilent,
cmdStdIn,
cmdStdErr,
egrep_, grep_,
logMsg,
removePrefix, removeStrictPrefix, removeSuffix,
shell, shell_,
sudo,
(+-+)) where
#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,2))
#else
import Control.Applicative ((<$>))
#endif
import Data.List (stripPrefix)
import Data.Maybe (fromMaybe)
import System.Exit (ExitCode (..))
import System.Process (readProcess, readProcessWithExitCode, rawSystem)
removeTrailingNewline :: String -> String
removeTrailingNewline "" = ""
removeTrailingNewline str =
if last str == '\n'
then init str
else str
quoteCmd :: String -> [String] -> String
quoteCmd c args = "'" ++ unwords (c:args) ++ "'"
-- | Run a command in a process and return stdout
cmd :: String -> [String] -> IO String
cmd c args = cmdStdIn c args ""
-- | Run command in process, output goes to stdout and stderr
cmd_ :: String -> [String] -> IO ()
cmd_ c args = do
ret <- rawSystem c args
case ret of
ExitSuccess -> return ()
ExitFailure n -> error $ quoteCmd c args +-+ "failed with exit code" +-+ show n
-- | Run a command, and return Boolean status
cmdBool :: String -> [String] -> IO Bool
cmdBool c args = do
ret <- rawSystem c args
case ret of
ExitSuccess -> return True
ExitFailure _ -> return False
-- | Run a command in a process, maybe returning output if it succeeds
cmdMaybe :: String -> [String] -> IO (Maybe String)
cmdMaybe c args = do
(ret, out, _err) <- readProcessWithExitCode c args ""
case ret of
ExitSuccess -> return $ Just $ removeTrailingNewline out
ExitFailure _ -> return Nothing
-- | Run command, return list of stdout lines
-- | since 0.1.1
cmdLines :: String -> [String] -> IO [String]
cmdLines c args = lines <$> cmd c args
-- | Run a command, passing input string as stdin, and return stdout
cmdStdIn :: String -> [String] -> String -> IO String
cmdStdIn c args inp = removeTrailingNewline <$> readProcess c args inp
-- | Run a command string in a shell, and return stdout
shell :: String -> IO String
shell cs = cmd "sh" ["-c", cs]
-- | Run a command string in a shell, output goes to stdout
shell_ :: String -> IO ()
shell_ c = cmd_ "sh" ["-c", c]
-- | Log a command with a datestamp
cmdlog :: String -> [String] -> IO ()
cmdlog c args = do
logMsg $ unwords $ c:args
cmd_ c args
logMsg :: String -> IO ()
logMsg msg = do
date <- cmd "date" ["+%T"]
putStrLn $ date +-+ msg
-- | Dry-run a command: print it to stdout - more used for debugging
cmdN :: String -> [String] -> IO ()
cmdN c args = putStrLn $ unwords $ c:args
-- | Run command in a process, returning stdout and stderr
cmdStdErr :: String -> [String] -> IO (String, String)
cmdStdErr c args = do
(_ret, out, err) <- readProcessWithExitCode c args ""
return (removeTrailingNewline out, removeTrailingNewline err)
-- -- | Run command, if it fails output msg as error.
-- cmdAssert :: String -> String -> [String] -> IO ()
-- cmdAssert msg c args = do
-- ret <- rawSystem c args
-- case ret of
-- ExitSuccess -> return ()
-- ExitFailure _ -> error msg
-- | Run a command hiding stderr, if it succeeds return stdout
cmdQuiet :: String -> [String] -> IO String
cmdQuiet c args = do
(ret, out, err) <- readProcessWithExitCode c args ""
case ret of
ExitSuccess -> return $removeTrailingNewline out
ExitFailure n -> error $ quoteCmd c args +-+ "failed with status" +-+ show n ++ "\n" ++ err
-- | Run a command hiding stdout: stderr is only output if it fails.
cmdSilent :: String -> [String] -> IO ()
cmdSilent c args = do
(ret, _, err) <- readProcessWithExitCode c args ""
case ret of
ExitSuccess -> return ()
ExitFailure n -> error $ quoteCmd c args +-+ "failed with status" +-+ show n ++ "\n" ++ err
-- | Run a command, drop stderr, and return stdout
cmdIgnoreErr :: String -> [String] -> String -> IO String
cmdIgnoreErr c args input = do
(_exit, out, _err) <- readProcessWithExitCode c args input
return out
-- grep :: String -> FilePath -> IO [String]
-- grep pat file =
-- cmdLines "grep" [pat, file]
-- | grep a pattern in file and return Boolean status
grep_ :: String -> FilePath -> IO Bool
grep_ pat file =
cmdBool "grep" ["-q", pat, file]
-- | grep for extended regexp in file, and return Boolean status
egrep_ :: String -> FilePath -> IO Bool
egrep_ pat file =
cmdBool "grep" ["-q", "-e", pat, file]
-- | sudo a command
sudo :: String -> [String] -> IO ()
sudo c args = cmdlog "sudo" (c:args)
-- | Combine strings with a single space
infixr 4 +-+
(+-+) :: String -> String -> String
"" +-+ s = s
s +-+ "" = s
s +-+ t | last s == ' ' = s ++ t
| head t == ' ' = s ++ t
s +-+ t = s ++ " " ++ t
-- singleLine :: String -> String
-- singleLine "" = ""
-- singleLine s = (head . lines) s
-- | Remove a prefix from a string if there
removePrefix :: String -> String-> String
removePrefix prefix orig =
fromMaybe orig $ stripPrefix prefix orig
-- | Remove prefix, or fail with error
removeStrictPrefix :: String -> String -> String
removeStrictPrefix prefix orig =
fromMaybe (error prefix +-+ "is not prefix of" +-+ orig) $ stripPrefix prefix orig
-- | Remove a suffix from a string if there
removeSuffix :: String -> String -> String
removeSuffix suffix orig =
fromMaybe orig $ stripSuffix suffix orig
where
stripSuffix sf str = reverse <$> stripPrefix (reverse sf) (reverse str)