packages feed

simple-cmd 0.1.4 → 0.2.0

raw patch · 4 files changed

+148/−26 lines, 4 filesdep ~processPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: process

API changes (from Hackage documentation)

+ SimpleCmd: pipe :: PipeCommand -> PipeCommand -> IO String
+ SimpleCmd: pipe3_ :: PipeCommand -> PipeCommand -> PipeCommand -> IO ()
+ SimpleCmd: pipeBool :: PipeCommand -> PipeCommand -> IO Bool
+ SimpleCmd: pipeFile_ :: FilePath -> PipeCommand -> PipeCommand -> IO ()
+ SimpleCmd: pipe_ :: PipeCommand -> PipeCommand -> IO ()
+ SimpleCmd: shellBool :: String -> IO Bool
+ SimpleCmd: sudo_ :: String -> [String] -> IO ()
+ SimpleCmd: type PipeCommand = (String, [String])
+ SimpleCmd: warning :: String -> IO ()
- SimpleCmd: sudo :: String -> [String] -> IO ()
+ SimpleCmd: sudo :: String -> [String] -> IO String

Files

ChangeLog.md view
@@ -1,10 +1,17 @@ # Revision history for simple-cmd -## 0.1.4+## 0.2.0 (2019-06-03)+- add warning command+- API change: sudo and sudo_+- add shellBool+- add pipe, pipe_, pipeBool, pipeFile_, pipe3+- quoteCmd uses showCommandForUser++## 0.1.4 (2019-04-08) - export error' - add cmdLog (deprecates cmdlog) -## 0.1.3.1+## 0.1.3.1 (2019-03-15) - sudo: ignored for root or when no sudo installed  ## 0.1.3 -- 2019-02-20
README.md view
@@ -18,6 +18,7 @@ outputs to stdout. For example  ```haskell+cmd_ "echo" ["Hello"] cmd_ "git" ["clone", url] ``` This can shortened to `git_ "clone" [url]`.@@ -25,15 +26,24 @@ ```haskell cmd :: String -> [String] -> IO String ```-returns stdout as a `String`.+returns stdout as a `String`. eg +```haskell+date <- cmd "date" []+```+ There are also `cmdBool`, `cmdMaybe`, `cmdList`, `shell`, and others. +Simple pipes are also supported:+```haskell+pipe_ ("echo",["hello"]) ("grep",["ello"])+```+ Other examples: ```haskell gitBranch :: IO String grep_ pat file :: IO Bool-sudo c args :: IO ()+sudo_ c args :: IO () ```  See the library documentation for more details.
SimpleCmd.hs view
@@ -32,7 +32,7 @@   cmdIgnoreErr,   cmdLines,   cmdMaybe,-  cmdLog, cmdlog {-TODO: remove for 0.2 -},+  cmdLog, cmdlog {-TODO: remove for 0.3 -},   cmdN,   cmdQuiet,   cmdSilent,@@ -43,23 +43,31 @@   logMsg,   removePrefix, removeStrictPrefix, removeSuffix,   shell, shell_,-  sudo,+  shellBool,+  sudo, sudo_,+  warning,+  PipeCommand,+  pipe, pipe_, pipeBool,+  pipe3_, pipeFile_,   (+-+)) where  #if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,0)) #else import Control.Applicative ((<$>)) #endif-import Control.Monad (when)+import Control.Monad  import Data.List (stripPrefix) import Data.Maybe (isNothing, fromMaybe)  import System.Directory (findExecutable) import System.Exit (ExitCode (..))-import System.IO (hPutStrLn, stderr)+import System.IO (hGetContents, hPutStrLn, IOMode(ReadMode), stderr, withFile) import System.Posix.User (getEffectiveUserID)-import System.Process (readProcess, readProcessWithExitCode, rawSystem)+import System.Process (createProcess, proc, ProcessHandle, rawSystem, readProcess,+                       readProcessWithExitCode, runProcess, showCommandForUser,+                       std_in, std_out, StdStream(CreatePipe, UseHandle),+                       waitForProcess, withCreateProcess)  removeTrailingNewline :: String -> String removeTrailingNewline "" = ""@@ -69,7 +77,7 @@   else str  quoteCmd :: String -> [String] -> String-quoteCmd c args = "'" ++ unwords (c:args) ++ "'"+quoteCmd = showCommandForUser  -- | Alias for errorWithoutStackTrace (for base >= 4.9) --@@ -95,14 +103,18 @@     ExitSuccess -> return ()     ExitFailure n -> error' $ quoteCmd c args +-+ "failed with exit code" +-+ show n --- | 'cmdBool c args' runs a command, and return Boolean status-cmdBool :: String -> [String] -> IO Bool-cmdBool c args = do-  ret <- rawSystem c args+boolWrapper :: IO ExitCode -> IO Bool+boolWrapper pr = do+  ret <- pr   case ret of     ExitSuccess -> return True     ExitFailure _ -> return False +-- | 'cmdBool c args' runs a command, and return Boolean status+cmdBool :: String -> [String] -> IO Bool+cmdBool c args =+  boolWrapper (rawSystem c args)+ -- | 'cmdMaybe c args' runs a command, maybe returning output if it succeeds cmdMaybe :: String -> [String] -> IO (Maybe String) cmdMaybe c args = do@@ -125,10 +137,17 @@ shell :: String -> IO String shell cs = cmd "sh" ["-c", cs] --- | 'shell_ c' runs a command string in a shell, output goes to stdout+-- | 'shell_ cs' runs a command string in a shell, output goes to stdout shell_ :: String -> IO ()-shell_ c = cmd_ "sh" ["-c", c]+shell_ cs = cmd_ "sh" ["-c", cs] +-- | 'shellBool cs' runs a command string in a shell, output goes to stdout+--+-- @since 0.2.0+shellBool :: String -> IO Bool+shellBool cs =+  boolWrapper (rawSystem "sh" ["-c", cs])+ -- | 'cmdLog c args' logs a command with a datestamp -- -- @since 0.1.4@@ -137,7 +156,7 @@   logMsg $ unwords $ c:args   cmd_ c args --- | 'cmdlog' deprecated alias for 'cmdLog' (to be removed in 0.2)+-- | 'cmdlog' deprecated alias for 'cmdLog' (will be removed in 0.3) cmdlog :: String -> [String] -> IO () cmdlog = cmdLog @@ -206,19 +225,32 @@ egrep_ pat file =   cmdBool "grep" ["-q", "-e", pat, file] --- | 'sudo c args' runs a command as sudo+-- | 'sudo c args' runs a command as sudo returning stdout+--+-- Result type changed from IO () to IO String in 0.2.0 sudo :: String -- ^ command      -> [String] -- ^ arguments+     -> IO String+sudo = sudoInternal cmd++-- | 'sudo_ c args' runs a command as sudo+--+-- @since 0.2.0+sudo_ :: String -- ^ command+     -> [String] -- ^ arguments      -> IO ()-sudo c args = do+sudo_ = sudoInternal cmdLog++sudoInternal :: (String -> [String] -> IO a) -> String -> [String] -> IO a+sudoInternal exc c args = do   uid <- getEffectiveUserID   sd <- if uid == 0     then return Nothing     else findExecutable "sudo"   let noSudo = isNothing sd   when (uid /= 0 && noSudo) $-    hPutStrLn stderr "'sudo' not found"-  cmdLog (fromMaybe c sd) (if noSudo then args else c:args)+    warning "'sudo' not found"+  exc (fromMaybe c sd) (if noSudo then args else c:args)  -- | Combine two strings with a single space infixr 4 +-+@@ -249,3 +281,76 @@   fromMaybe orig $ stripSuffix suffix orig   where     stripSuffix sf str = reverse <$> stripPrefix (reverse sf) (reverse str)++-- | 'warning' outputs to stderr+--+-- @since 0.2.0+warning :: String -> IO ()+warning = hPutStrLn stderr++type PipeCommand = (String,[String])++-- | Return stdout from piping the output of one process to another+--+-- @since 0.2.0+pipe :: PipeCommand -> PipeCommand -> IO String+pipe (c1,args1) (c2,args2) =+  withCreateProcess ((proc c1 args1) { std_out = CreatePipe }) $+    \ _si (Just ho1) _se p1 -> do+      (_, Just ho2, _, p2) <- createProcess ((proc c2 args2) {std_in = UseHandle ho1, std_out = CreatePipe})+      out <- hGetContents ho2+      void $ waitForProcess p1+      void $ waitForProcess p2+      return out++-- | Pipe two commands without returning anything+--+-- @since 0.2.0+pipe_ :: PipeCommand -> PipeCommand -> IO ()+pipe_ (c1,args1) (c2,args2) =+  void $ pipeInternal (c1,args1) (c2,args2) >>= waitForProcess++-- | Bool result of piping of commands+--+-- @since 0.2.0+pipeBool :: PipeCommand -> PipeCommand -> IO Bool+pipeBool (c1,args1) (c2,args2) =+  boolWrapper $ pipeInternal (c1,args1) (c2,args2) >>= waitForProcess++pipeInternal :: PipeCommand -> PipeCommand -> IO ProcessHandle+pipeInternal (c1,args1) (c2,args2) =+  -- nicer with process-typed:+  -- withProcess_ (setStdout createPipe proc1) $ \ p -> runProcess (setStdin (useHandleClose (getStdout p)) proc2)+  withCreateProcess ((proc c1 args1) { std_out = CreatePipe }) $+    \ _si so _se p1 -> do+      p2 <- runProcess c2 args2 Nothing Nothing so Nothing Nothing+      void $ waitForProcess p1+      return p2++-- | Pipe 3 commands, no returning anything+--+-- @since 0.2.0+pipe3_ :: PipeCommand -> PipeCommand -> PipeCommand -> IO ()+pipe3_ (c1,a1) (c2,a2) (c3,a3) =+  withCreateProcess ((proc c1 a1) { std_out = CreatePipe }) $+  \ _hi1 (Just ho1) _he1 p1 ->+    withCreateProcess ((proc c2 a2) {std_in = UseHandle ho1, std_out = CreatePipe}) $+    \ _hi2 ho2 _he2 p2 -> do+      p3 <- runProcess c3 a3 Nothing Nothing ho2 Nothing Nothing+      void $ waitForProcess p1+      void $ waitForProcess p2+      void $ waitForProcess p3++-- | Pipe a file to the first of a pipe of commands+--+-- @since 0.2.0+pipeFile_ :: FilePath -> PipeCommand -> PipeCommand -> IO ()+pipeFile_ infile (c1,a1) (c2,a2) =+  withFile infile ReadMode $+  \ hin ->+    withCreateProcess ((proc c1 a1) { std_in = UseHandle hin, std_out = CreatePipe }) $+    \ _si so _se p1 -> do+      p2 <- runProcess c2 a2 Nothing Nothing so Nothing Nothing+      void $ waitForProcess p1+      void $ waitForProcess p2+
simple-cmd.cabal view
@@ -1,10 +1,10 @@ name:                simple-cmd-version:             0.1.4+version:             0.2.0 synopsis:            Simple String-based process commands description:-            Thin wrappers over System.Process (readProcess,-            readProcessWithExitCode, and rawSystem). The idea is to provide-            some simple common idioms for easy calling out to commands+            Simple wrappers over System.Process+            (readProcess, readProcessWithExitCode, rawSystem, and createProcess). +            The idea is to provide some common idioms for calling out to commands             from programs.  For more advanced shell-scripting or streaming             use turtle, shelly, command, etc. license:             BSD3@@ -18,7 +18,7 @@ extra-source-files:  README.md ChangeLog.md TODO tested-with:         GHC == 7.0.4, GHC == 7.4.2, GHC == 7.6.3, GHC == 7.8.4,                      GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4,-                     GHC == 8.6.4+                     GHC == 8.6.5  source-repository head   type:     git