packages feed

shh 0.1.0.0 → 0.1.0.1

raw patch · 6 files changed

+66/−47 lines, 6 files

Files

ChangeLog.md view
@@ -1,5 +1,12 @@ # Revision history for execpath -## 0.1.0.0  -- YYYY-mm-dd+## 0.1.0.1 -- 2019-01-22++* Force output of lazy read functions to normal form to prevent+  people from accidentally holding onto resources.++* New helper functions for reading.+  +## 0.1.0.0  -- 2018-11-02  * First version. Released on an unsuspecting world.
shh.cabal view
@@ -1,5 +1,5 @@ name:                shh-version:             0.1.0.0+version:             0.1.0.1 synopsis:            Simple shell scripting from Haskell description:         Provides a shell scripting environment for Haskell. It                      helps you all external binaries, and allows you to@@ -21,9 +21,8 @@  library   exposed-modules:     Shh-                     , Shh.Example                      , Shh.Internal-  build-depends:       base >=4.9 && <4.12+  build-depends:       base >=4.9 && <4.13                      , async                      , deepseq                      , directory
src/Shh.hs view
@@ -1,11 +1,3 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE GADTs #-} -- | Shh provides a shell-like environment for Haskell. module Shh     ( initInteractive@@ -22,19 +14,34 @@     , Stream(..)     , devNull     -- | == Reading @stdout@-    , readProc+    -- === Lazy/Streaming reads+    -- These reads are lazy. The process is run long enough to produce+    -- the amount of output that is actually used. It is therefor suitable+    -- for use with infinite output streams. The process is terminated+    -- as soon the function finishes. Note that the result is forced to+    -- normal form to prevent any accidental reading after the process has+    -- terminated.     , withRead-    , trim+    , withReadSplit0+    , withReadLines+    , withReadWords+    -- | === Strict reads+    , readProc     , readTrim-    , split0     , readSplit0     , readLines+    , readWords     , readAuto+    -- | === String manipulation+    -- Utility functions for dealing with common string issues in shell+    -- scripting.+    , trim+    , split0     -- | == Writing to @stdin@     , writeProc     , (<<<), (>>>)     , readWriteProc-    , mapP+    , apply     -- | == Exceptions     -- If any exception is allowed to propagate out of a pipeline, all the     -- processes comprising the pipeline will be terminated. This is contrary
− src/Shh/Example.hs
@@ -1,7 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}--module Shh.Example where--import Shh--$(loadAnnotatedEnv (\s -> s ++ "_"))
src/Shh/Internal.hs view
@@ -12,7 +12,7 @@   import Control.Concurrent.Async-import Control.DeepSeq (rnf)+import Control.DeepSeq (rnf,force,NFData) import Control.Exception as C import Control.Monad import Control.Monad.IO.Class@@ -217,27 +217,34 @@ -- This is strict, so the whole output is read into a `String`. See `withRead` -- for a lazy version that can be used for streaming. readProc :: MonadIO io => Proc a -> io String-readProc (Proc f) = liftIO $ do-    (r,w) <- createPipe-    (_,o) <- concurrently-        (f stdin w stderr (pure ()) (hClose w))-        (do-            output <- hGetContents r-            C.evaluate $ rnf output-            hClose r-            pure output-        )-    pure o+readProc p = withRead p pure  -- | Run a process and capture it's output lazily. Once the continuation -- is completed, the handles are closed, and the process is terminated.-withRead :: MonadIO io => Proc a -> (String -> IO b) -> io b+withRead :: (NFData b, MonadIO io) => Proc a -> (String -> IO b) -> io b withRead (Proc f) k = liftIO $      withPipe $ \r w -> do         withAsync (f stdin w stderr (pure ()) (hClose w)) $ \_ ->-            (hGetContents r >>= k) `finally` hClose r+            (hGetContents r >>= k >>= C.evaluate . force) `finally` hClose r +-- | Apply a transformation function to the string before the IO action.+withRead' :: (NFData b, MonadIO io) => (String -> a) -> Proc x -> (a -> IO b) -> io b+withRead' f p io = withRead p (io . f) +-- | Like @'withRead'@ except it splits the string with @'split0'@ first.+withReadSplit0 :: (NFData b, MonadIO io) => Proc a -> ([String] -> IO b) -> io b+withReadSplit0 = withRead' split0++-- | Like @'withRead'@ except it splits the string with @'lines'@ first.+--+-- NB: Please consider using @'withReadSplit0'@ where you can.+withReadLines :: (NFData b, MonadIO io) => Proc a -> ([String] -> IO b) -> io b+withReadLines = withRead' lines++-- | Like @'withRead'@ except it splits the string with @'words'@ first.+withReadWords :: (NFData b, MonadIO io) => Proc a -> ([String] -> IO b) -> io b+withReadWords = withRead' words+ -- | Read and write to a `Proc`... readWriteProc :: MonadIO io => Proc a -> String -> io String readWriteProc (Proc f) input = liftIO $ do@@ -255,12 +262,12 @@         )     pure o --- | Some as `readWriteProc`. Map a `Proc` over a `String`.+-- | Some as `readWriteProc`. Apply a `Proc` to a `String`. ----- >>> mapP shasum "Hello"+-- >>> apply shasum "Hello" -- "f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0  -\n"-mapP :: MonadIO io => Proc a -> String -> io String-mapP = readWriteProc+apply :: MonadIO io => Proc a -> String -> io String+apply = readWriteProc  -- | Provide the stdin of a `Proc` from a `String` writeProc :: MonadIO io => Proc a -> String -> io a@@ -328,7 +335,6 @@ readTrim :: MonadIO io => Proc a -> io String readTrim = fmap trim . readProc - -- | A class for things that can be converted to arguments on the command -- line. The default implementation is to use `show`. class ExecArg a where@@ -440,7 +446,8 @@             | validIdentifier (f s) = Just (f s, s)             | otherwise             = Nothing --- | Function that splits '\0' seperated list of strings.+-- | Function that splits '\0' seperated list of strings. Useful in conjuction+-- with @find . "-print0"@. split0 :: String -> [String] split0 = endBy "\0" @@ -449,11 +456,17 @@ -- -- > readSplit0 $ find "-print0" readSplit0 :: Proc () -> IO [String]-readSplit0 p = split0 <$> readProc p+readSplit0 p = withReadSplit0 p pure  -- | A convinience function for reading the output lines of a `Proc`.+--+-- Note: Please consider using @'readSplit0'@ instead if you can. readLines :: Proc () -> IO [String]-readLines p = lines <$> readProc p+readLines p = withReadLines p pure++-- | Read output into a list of words+readWords :: Proc () -> IO [String]+readWords p = withReadWords p pure  -- | Like `readProc`, but attempts to `Prelude.read` the result. readAuto :: Read a => Proc () -> IO a
test/Test.hs view
@@ -70,8 +70,8 @@         writeProc (cat &> Truncate t) "Goodbye"         r <- readProc (cat t)         r @?= "Goodbye"-    , testCase "mapP" $ do-        r <- mapP shasum "test"+    , testCase "apply" $ do+        r <- apply shasum "test"         r @?= "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3  -\n"     , testCase "ignoreFailure" $ do         r <- readProc $ ignoreFailure false |> echo "Hello"