shell-conduit 4.5.2 → 4.6.0
raw patch · 8 files changed
+169/−48 lines, 8 filesdep +hspecdep +hspec-expectationsdep +shell-conduitdep ~basedep ~processnew-uploader
Dependencies added: hspec, hspec-expectations, shell-conduit
Dependency ranges changed: base, process
Files
- CHANGELOG.md +6/−0
- README.md +2/−2
- shell-conduit.cabal +20/−7
- src/Data/Conduit/Shell/PATH.hs +17/−12
- src/Data/Conduit/Shell/Process.hs +4/−6
- src/Data/Conduit/Shell/TH.hs +1/−1
- src/Data/Conduit/Shell/Variadic.hs +38/−20
- test/Spec.hs +81/−0
+ CHANGELOG.md view
@@ -0,0 +1,6 @@+# 4.6.0++* Add basic tests code+* Accept list as variadic command line arguments+ `mkdir "-p" ["folder1", "folder2"]` works now.+* TRAVIS CI added
README.md view
@@ -1,9 +1,9 @@-shell-conduit [](https://hackage.haskell.org/package/shell-conduit)+shell-conduit [](https://hackage.haskell.org/package/shell-conduit) [](https://travis-ci.org/psibi/shell-conduit) ===== Write shell scripts with Conduit. Still in the experimental phase. -[Haddock API documentation](http://chrisdone.github.io/shell-conduit/).+[Haddock API documentation](https://www.stackage.org/package/shell-conduit). ### Examples
shell-conduit.cabal view
@@ -1,17 +1,18 @@ name: shell-conduit-version: 4.5.2+version: 4.6.0 synopsis: Write shell scripts with Conduit description: Write shell scripts with Conduit. See "Data.Conduit.Shell" for documentation. license: BSD3 license-file: LICENSE author: Chris Done-maintainer: chrisdone@gmail.com-copyright: 2014 Chris Done+maintainer: Sibi Prabakaran <sibi@psibi.in>+copyright: 2014-2017 Chris Done category: Conduit, Scripting build-type: Simple cabal-version: >=1.8-homepage: https://github.com/chrisdone/shell-conduit-extra-source-files: README.md+homepage: https://github.com/psibi/shell-conduit+extra-source-files: CHANGELOG.md README.md+bug-reports: https://github.com/psibi/shell-conduit/issues library hs-source-dirs: src/@@ -33,7 +34,7 @@ , filepath , monad-control , monads-tf- , process+ , process >= 1.2.1.0 , resourcet , semigroups , split@@ -43,6 +44,18 @@ , transformers-base , unix >= 2.7.0.1 +test-suite test+ type: exitcode-stdio-1.0+ ghc-options: -Wall+ hs-source-dirs: test/+ main-is: Spec.hs+ + build-depends: base >= 4.5 && < 5,+ shell-conduit,+ hspec >= 2.1 && < 3,+ hspec-expectations,+ template-haskell+ source-repository head type: git- location: https://github.com/chrisdone/shell-conduit.git+ location: http://github.com/psibi/shell-conduit
src/Data/Conduit/Shell/PATH.hs view
@@ -1,24 +1,29 @@ {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE QuasiQuotes #-}-{-# OPTIONS_GHC -fno-warn-missing-signatures -fno-warn-unused-imports #-}+{-# OPTIONS_GHC+ -fno-warn-missing-signatures -fno-warn-unused-imports #-} -- | All binaries in PATH.- module Data.Conduit.Shell.PATH where -import Control.Monad-import Control.Monad.IO.Class-import Data.Conduit.Shell.Process-import Data.Conduit.Shell.TH-import Data.Conduit.Shell.Variadic-import Data.List+import Control.Monad+import Control.Monad.IO.Class+import Data.Conduit.Shell.Process+import Data.Conduit.Shell.TH+import Data.Conduit.Shell.Variadic+import Data.List import qualified Data.Text as T (unpack)-import Prelude-import System.Directory+import Prelude+import System.Directory -- | Helpful CD command.-cd :: (MonadIO m,CmdArg arg) => arg -> m ()-cd fp = liftIO (setCurrentDirectory (T.unpack (toTextArg fp)))+cd+ :: (MonadIO m, CmdArg arg)+ => arg -> m ()+cd fp =+ case (toTextArg fp) of+ [] -> return ()+ (path:_) -> liftIO $ setCurrentDirectory (T.unpack path) $(generateBinaries)
src/Data/Conduit/Shell/Process.hs view
@@ -31,21 +31,18 @@ import Control.Exception import Control.Monad import Control.Monad.IO.Class-import Control.Monad.Trans.Resource import Data.ByteString (ByteString) import qualified Data.ByteString as S import Data.Conduit import Data.Conduit.Binary import qualified Data.Conduit.List as CL-import Data.Conduit.Text (Codec)-import qualified Data.Conduit.Text as T+import Data.Conduit.Text (encodeUtf8, decodeUtf8) import Data.Text (Text) import Data.Typeable import System.Exit import System.IO import System.Posix.IO (createPipe, fdToHandle) import System.Process hiding (createPipe)-import System.Process.Internals (createProcess_) -- | A pipeable segment. Either a conduit or a process. data Segment r@@ -77,7 +74,7 @@ do ex <- tryS this case ex of Right x -> pure x- Left (e :: ProcessException) -> that+ Left (_ :: ProcessException) -> that empty = throw ProcessEmpty -- | Try something in a segment.@@ -104,6 +101,7 @@ instance Exception ProcessException instance Show ProcessException where+ show ProcessEmpty = "empty process" show (ProcessException cp ec) = concat ["The " ,case cmdspec cp of@@ -166,7 +164,7 @@ -- | Work on the stream as 'Text' values from UTF-8. text :: (r ~ (),m ~ IO) => ConduitM Text Text m r -> Segment r-text conduit = bytes (T.decodeUtf8 $= conduit $= T.encodeUtf8)+text conduit' = bytes (decodeUtf8 $= conduit' $= encodeUtf8) -- | Lift a conduit into a segment. bytes :: (a ~ ByteString,m ~ IO) => ConduitM a ByteString m r -> Segment r
src/Data/Conduit/Shell/TH.hs view
@@ -57,7 +57,7 @@ do inScope <- recover (return False) (do void (reify (mkName candidate)) return True)- if inScope || candidate == "import"+ if inScope || candidate == "import" || candidate == "type" then getUniqueName (candidate ++ "'") else return (mkName candidate)
src/Data/Conduit/Shell/Variadic.hs view
@@ -2,24 +2,25 @@ {-# LANGUAGE TypeFamilies #-} -- | Variadic process calling.- module Data.Conduit.Shell.Variadic- (ProcessType(..)- ,variadicProcess- ,CmdArg(..))- where+ ( ProcessType(..)+ , variadicProcess+ , CmdArg(..)+ ) where import qualified Data.ByteString as SB import qualified Data.ByteString.Lazy as LB-import Data.Conduit.Shell.Process+import Data.Conduit.Shell.Process import qualified Data.Text as ST import qualified Data.Text.Encoding as ST import qualified Data.Text.Lazy as LT import qualified Data.Text.Lazy.Encoding as LT+import Control.Applicative (pure) -- | A variadic process maker.-variadicProcess :: (ProcessType r)- => String -> r+variadicProcess+ :: (ProcessType r)+ => String -> r variadicProcess name = spr name [] -- | Make the final conduit.@@ -27,31 +28,48 @@ makeProcessLauncher name args = proc name (map ST.unpack args) -- | Process return type.-class ProcessType t where- spr :: String -> [ST.Text] -> t+class ProcessType t where+ spr :: String -> [ST.Text] -> t -instance (r ~ ()) => ProcessType (Segment r) where- spr name args = makeProcessLauncher name (reverse args)+instance (r ~ ()) =>+ ProcessType (Segment r) where+ spr name args = makeProcessLauncher name args -- | Accept strings as arguments.-instance (ProcessType r,CmdArg a) => ProcessType (a -> r) where- spr name args = \a -> spr name (toTextArg a : args)+instance (ProcessType r, CmdArg a) =>+ ProcessType (a -> r) where+ spr name args = \a -> spr name (args ++ toTextArg a) -- | Command line argument. class CmdArg a where- toTextArg :: a -> ST.Text+ toTextArg :: a -> [ST.Text] instance CmdArg ST.Text where- toTextArg = id+ toTextArg = pure . id instance CmdArg LT.Text where- toTextArg = LT.toStrict+ toTextArg = pure . LT.toStrict instance CmdArg SB.ByteString where- toTextArg = ST.decodeUtf8+ toTextArg = pure . ST.decodeUtf8 instance CmdArg LB.ByteString where- toTextArg = LT.toStrict . LT.decodeUtf8+ toTextArg = pure . LT.toStrict . LT.decodeUtf8 instance CmdArg String where- toTextArg = ST.pack+ toTextArg = pure . ST.pack++instance CmdArg [String] where+ toTextArg = map ST.pack++instance CmdArg [ST.Text] where+ toTextArg = map id++instance CmdArg [LT.Text] where+ toTextArg = map LT.toStrict++instance CmdArg [SB.ByteString] where+ toTextArg = map ST.decodeUtf8++instance CmdArg [LB.ByteString] where+ toTextArg = map (LT.toStrict . LT.decodeUtf8)
+ test/Spec.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE ExtendedDefaultRules #-}+{-# LANGUAGE CPP #-}++import Test.Hspec+import Data.Conduit.Shell+import Data.Conduit.Shell.PATH (true, false)+import Data.Conduit.Shell.Segments (strings, ignore)+import Control.Applicative++main :: IO ()+main =+ hspec $+ do describe "SHELL path functions" $+ do it "false" $+ do val <- run $ strings (false <|> echo "failed")+ val `shouldBe` ["failed"]+ it "true" $+ do val <- run $ strings (true <|> echo "passed")+ val `shouldBe` []+ describe "ls" $+ do it "home directory check" $+ do val <- run $ strings (ls "/")+ val `shouldContain` ["home"]+ it "long option" $+ do val <- run $ strings (ls "-a" ["/"])+ val `shouldContain` ["home"]+ describe "multiple string usage" $+ do it "make two directory" $+ do val <-+ run $+ do ignore $ mkdir "-p" "mtest1" "mtest2" "mtest3"+ strings $ ls "."+ run $ rmdir ["mtest1", "mtest2", "mtest3"]+ val `shouldContain` ["mtest1", "mtest2", "mtest3"]+ describe "list usage in variadic" $+ do it "two directory" $+ do val <-+ run $+ do ignore $ mkdir "-p" ["test1", "test2"]+ strings $ ls "."+ run $ rmdir ["test1", "test2"]+ val `shouldContain` ["test1", "test2"]+ describe "shell calls" $+ do it "shell ls" $+ do val <- run $ do strings $ shell "ls /"+ val `shouldContain` ["home"]+ describe "ordering of arguments" $+ do it "echo -e" $+ do val <- run $ do strings $ echo "-e" "hello\n" "haskell"+#ifdef darwin_HOST_OS+ val `shouldBe` ["-e hello", " haskell"]+#else+ val `shouldBe` ["hello", " haskell"]+#endif+ it "mixed variant" $+ do val <- run $ strings $ echo "-e" ["hello\n", "haskell"]+#ifdef darwin_HOST_OS+ val `shouldBe` ["-e hello", " haskell"]+#else+ val `shouldBe` ["hello", " haskell"]+#endif+ it "list variant" $+ do val <- run $ strings $ echo ["-e", "hello\n", "haskell"]+#ifdef darwin_HOST_OS+ val `shouldBe` ["-e hello", " haskell"]+#else+ val `shouldBe` ["hello", " haskell"]+#endif+ describe "cd" $+ do it "cd /" $+ do val <-+ run $+ do ignore $ cd "/"+ strings pwd+ val `shouldBe` ["/"]+ it "cd /home" $+ do val <-+ run $+ do ignore $ cd ["/home", undefined]+ strings pwd+ val `shouldBe` ["/home"]