diff --git a/src/Streamly/Internal/System/Command.hs b/src/Streamly/Internal/System/Command.hs index fd8d402..0603852 100644 --- a/src/Streamly/Internal/System/Command.hs +++ b/src/Streamly/Internal/System/Command.hs @@ -35,11 +35,14 @@ module Streamly.Internal.System.Command , foreground , daemon - -- * Helpers - , quotedWord + -- * Low-level Functions + , shellWord , runWith , streamWith , pipeWith + + -- * Deprecated + , quotedWord ) where @@ -63,7 +66,10 @@ import qualified Streamly.Internal.System.Process as Process #include "DocTestCommand.hs" --- | Posix compliant quote escaping: +-- | Posix compliant quoted shell command string parsing with escaping: +-- +-- Quotes and escapes are parsed as in a standard POSIX shell. +-- Examples (using shell @echo@ command): -- -- $ echo 'hello\\"world' -- hello\\"world @@ -73,9 +79,9 @@ import qualified Streamly.Internal.System.Process as Process -- -- $ echo 'hello\' -- hello\ -{-# INLINE quotedWord #-} -quotedWord :: MonadCatch m => Parser Char m String -quotedWord = +{-# INLINE shellWord #-} +shellWord :: MonadCatch m => Parser Char m String +shellWord = let toRQuote x = case x of '"' -> Just x @@ -92,6 +98,11 @@ quotedWord = trEsc _ _ = Nothing in Parser.wordWithQuotes False trEsc '\\' toRQuote isSpace Fold.toList +{-# DEPRECATED quotedWord "Use shellWord instead." #-} +{-# INLINE quotedWord #-} +quotedWord :: MonadCatch m => Parser Char m String +quotedWord = shellWord + -- | A modifier for stream generation APIs in "Streamly.System.Process" to -- generate streams from command strings. -- @@ -110,7 +121,7 @@ streamWith f cmd = Stream.concatEffect $ do xs <- Stream.fold Fold.toList $ Stream.catRights - $ Stream.parseMany quotedWord + $ Stream.parseMany shellWord $ Stream.fromList cmd case xs of y:ys -> return $ f y ys @@ -133,7 +144,7 @@ runWith :: MonadCatch m => runWith f cmd = do xs <- Stream.fold Fold.toList $ Stream.catRights - $ Stream.parseMany quotedWord + $ Stream.parseMany shellWord $ Stream.fromList cmd case xs of y:ys -> f y ys @@ -161,7 +172,7 @@ pipeWith f cmd input = Stream.concatEffect $ do xs <- Stream.fold Fold.toList $ Stream.catRights - $ Stream.parseMany quotedWord + $ Stream.parseMany shellWord $ Stream.fromList cmd case xs of y:ys -> return $ f y ys input diff --git a/test/Streamly/System/Process.hs b/test/Streamly/System/Process.hs index 5193775..2ea4b73 100644 --- a/test/Streamly/System/Process.hs +++ b/test/Streamly/System/Process.hs @@ -38,7 +38,7 @@ import qualified Streamly.System.Process as Proc import qualified Streamly.Data.Stream as Stream import qualified Streamly.Internal.FileSystem.Handle as FH (putBytes, read) -import qualified Streamly.Internal.System.Command as Cmd (quotedWord) +import qualified Streamly.Internal.System.Command as Cmd (shellWord) ------------------------------------------------------------------------------- -- Compatibility @@ -486,12 +486,12 @@ pipeChunksEither4 = monadicIO $ run checkFailAction checkFailAction = catch action failAction -quotedWordTest :: String -> [String] -> IO () -quotedWordTest inp expected = do +shellWordTest :: String -> [String] -> IO () +shellWordTest inp expected = do res <- Stream.fold Fold.toList $ Stream.catRights - $ Stream.parseMany Cmd.quotedWord $ Stream.fromList inp + $ Stream.parseMany Cmd.shellWord $ Stream.fromList inp res `shouldBe` expected main :: IO () @@ -551,14 +551,14 @@ main = do prop "toBytesEither cat = FH.toBytes" toBytes1 prop "toBytesEither on failing executable" toBytes2 - describe "quotedWord" $ do + describe "shellWord" $ do it "Single quote test" $ - quotedWordTest "'hello\\\\\"world'" ["hello\\\\\"world"] + shellWordTest "'hello\\\\\"world'" ["hello\\\\\"world"] it "Double quote test" $ - quotedWordTest + shellWordTest "\"hello\\\"\\\\w\\'orld\"" ["hello\"\\w\\'orld"] - -- TODO: We need to let the escape character be at the end - -- "wordWithQuotes" needs to be fixed! - -- it "Double quote test" $ - -- quotedWordTest "'hello\'" ["hello\\"] +#if MIN_VERSION_streamly_core(0,3,0) + it "Double quote test, escape at end" $ + shellWordTest "'hello\\'" ["hello\\"] +#endif