shh 0.7.0.8 → 0.7.1.0
raw patch · 6 files changed
+74/−16 lines, 6 filesdep ~base
Dependency ranges changed: base
Files
- ChangeLog.md +5/−0
- README.md +8/−3
- shh.cabal +2/−2
- src/Shh.hs +6/−0
- src/Shh/Internal.hs +45/−8
- test/Readme.lhs +8/−3
ChangeLog.md view
@@ -1,5 +1,10 @@ # Revision history for shh +## 0.7.1.0 -- 2020-09-05++* Assume UTF-8 encoding in places. This is a temporary workaroun until we+ can remove all encoding assumptions.+ ## 0.7.0.8 -- 2020-05-28 * Flush std buffers before executing a process to make interaction
README.md view
@@ -191,15 +191,20 @@ {-# LANGUAGE ExtendedDefaultRules #-} $(loadEnv SearchPath) -You now have all your executables available as simple to read Haskell-functions. This may render the namespace unwieldy. Executables may be loaded-explicitly using instead `load ShellPath`, such as+You now have all your executables available as simple to Haskell+functions. If you don't want to load your entire environment you+can load specific commands directly: load SearchPath ["echo", "grep", "cat", "ls"] If you want to check that all the dependencies still exist, you can use `missingExecutables :: IO [String]`, which will tell you if anything is missing.++For use in a project, it makes sense to have a dedicated module for your+project which does the template Haskell above. This will prevent recompilation+of all the executables, and also allow you to easily namespace them to+avoid collisions with normal Haskell functions. ### Usage in GHCi
shh.cabal view
@@ -1,5 +1,5 @@ name: shh-version: 0.7.0.8+version: 0.7.1.0 synopsis: Simple shell scripting from Haskell description: Provides a shell scripting environment for Haskell. It helps you use external binaries, and allows you to@@ -33,7 +33,7 @@ process >= 1.6.3 && < 1.7, split >= 0.2.3 && < 0.3, stringsearch >= 0.3.6.6 && < 0.4,- template-haskell >= 2.13.0 && < 2.17,+ template-haskell >= 2.13.0 && < 2.18, containers >= 0.5.11 && < 0.7, unix >= 2.7.2 && < 2.8, utf8-string
src/Shh.hs view
@@ -75,9 +75,15 @@ -- to how a shell normally works (even with @-o pipefail@!). , Failure(..) , ignoreFailure+ , ignoreCode , tryFailure+ , tryFailureJust+ , catchFailure+ , catchFailureJust , failWithStdErr , exitCode+ , translateCode+ , translateCode' -- | == Constructing Arguments , Cmd , ExecArg(..)
src/Shh/Internal.hs view
@@ -101,7 +101,7 @@ show f = concat $ [ "Command `" ]- ++ [intercalate " " (BC8.unpack (failureProg f) : map show (failureArgs f))]+ ++ [intercalate " " (toString (failureProg f) : map show (failureArgs f))] ++ [ "` failed [exit " , show (failureCode f)@@ -109,7 +109,7 @@ , prettyCallStack (failureStack f) ] ++ flip (maybe []) (failureStdErr f) (\s ->- ["\n-- stderr --\n" ++ BC8.unpack s])+ ["\n-- stderr --\n" ++ toString s]) instance Exception Failure @@ -195,9 +195,9 @@ p &> StdOut = runProc p (Proc f) &> StdErr = buildProc $ \i _ e -> f i e e (Proc f) &> (Truncate path) = buildProc $ \i _ e ->- withBinaryFile (BC8.unpack path) WriteMode $ \h -> f i h e+ withBinaryFile (toString path) WriteMode $ \h -> f i h e (Proc f) &> (Append path) = buildProc $ \i _ e ->- withBinaryFile (BC8.unpack path) AppendMode $ \h -> f i h e+ withBinaryFile (toString path) AppendMode $ \h -> f i h e infixl 9 &> -- | Redirect stderr of this process to another location@@ -208,9 +208,9 @@ p &!> StdErr = runProc $ p (Proc f) &!> StdOut = buildProc $ \i o _ -> f i o o (Proc f) &!> (Truncate path) = buildProc $ \i o _ ->- withBinaryFile (BC8.unpack path) WriteMode $ \h -> f i o h+ withBinaryFile (toString path) WriteMode $ \h -> f i o h (Proc f) &!> (Append path) = buildProc $ \i o _ ->- withBinaryFile (BC8.unpack path) AppendMode $ \h -> f i o h+ withBinaryFile (toString path) AppendMode $ \h -> f i o h infixl 9 &!> -- | Lift a Haskell function into a @`Proc`@. The handles are the @stdin@@@ -434,8 +434,8 @@ mkProc' :: HasCallStack => Bool -> ByteString -> [ByteString] -> Proc () mkProc' delegate cmd args = Proc $ \i o e -> do let- cmd' = BC8.unpack cmd- args' = BC8.unpack <$> args+ cmd' = toString cmd+ args' = toString <$> args bracket (createProcess_ cmd' (proc cmd' args') { std_in = UseHandle i@@ -543,6 +543,32 @@ tryFailure :: Shell m => Proc a -> m (Either Failure a) tryFailure (Proc f) = buildProc $ \i o e -> try $ f i o e +-- | Like @`tryFailure`@ except that it takes an exception predicate which+-- selects which exceptions to catch. Any exception not matching the predicate+-- (returning @Nothing@) is re-thrown.+tryFailureJust :: Shell m => (Failure -> Maybe b) -> Proc a -> m (Either b a)+tryFailureJust pr (Proc f) = buildProc $ \i o e -> tryJust pr (f i o e)++-- | Run a `Proc` with an action to take if an exception is thrown.+catchFailure :: Shell m => Proc a -> (Failure -> Proc a) -> m a+catchFailure (Proc f) pr = buildProc $ \i o e -> catch (f i o e) (runProc . pr)++-- | Like @`catchFailureJust`@ except that it takes an exception predicate+-- which selects which exceptions to catch. Any exceptions not matching the+-- predicate (returning @Nothing@) are re-thrown.+catchFailureJust :: Shell m => (Failure -> Maybe b) -> Proc a -> (b -> Proc a) -> m a+catchFailureJust pr (Proc f) h = buildProc $ \i o e -> catchJust pr (f i o e) (runProc . h)++-- | Apply a function that translates non-0 exit codes to results. Any code+-- that returns a @Nothing@ will be thrown as a @`Failure`@.+translateCode' :: Shell m => (Int -> Maybe b) -> Proc a -> m (Either b a)+translateCode' f p = tryFailureJust (f . failureCode) p++-- | Apply a function to non-0 exit codes to extract a result. If @Nothing@+-- is produced, the @`Failure`@ is thrown.+translateCode :: Shell m => (Int -> Maybe a) -> Proc a -> m a+translateCode f p = catchFailureJust (f . failureCode) p pure+ -- | Capture the stderr of the proc, and attach it to any @`Failure`@ -- exceptions that are thrown. The stderr is also forwarded to downstream -- processes, or the inherited stderr handle. Note that capturing stderr@@ -580,6 +606,17 @@ where getCode (Right _) = 0 getCode (Left f) = failureCode f++-- | Run the @`Proc`@, but don't throw an exception if it exits with the+-- given code. Note, that from this point on, if the proc did fail with the+-- code, everything else now sees it as having exited with 0. If you need+-- to know the code, you have to use `exitCode`.+ignoreCode :: (Monad m, Shell m) => Int -> Proc a -> m ()+ignoreCode code p = catchFailureJust pr (void p) pure+ where+ pr f+ | failureCode f == code = Just ()+ | otherwise = Nothing -- | A class for things that can be converted to arguments on the command -- line. The default implementation is to use `show`.
test/Readme.lhs view
@@ -191,15 +191,20 @@ {-# LANGUAGE ExtendedDefaultRules #-} $(loadEnv SearchPath) -You now have all your executables available as simple to read Haskell-functions. This may render the namespace unwieldy. Executables may be loaded-explicitly using instead `load ShellPath`, such as+You now have all your executables available as simple to Haskell+functions. If you don't want to load your entire environment you+can load specific commands directly: load SearchPath ["echo", "grep", "cat", "ls"] If you want to check that all the dependencies still exist, you can use `missingExecutables :: IO [String]`, which will tell you if anything is missing.++For use in a project, it makes sense to have a dedicated module for your+project which does the template Haskell above. This will prevent recompilation+of all the executables, and also allow you to easily namespace them to+avoid collisions with normal Haskell functions. ### Usage in GHCi