shellwords 0.1.1.0 → 0.1.2.0
raw patch · 4 files changed
+46/−41 lines, 4 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ ShellWords: parseText :: Text -> Either String [Text]
- ShellWords: parse :: Text -> Either String [Text]
+ ShellWords: parse :: String -> Either String [String]
Files
- CHANGELOG.md +9/−1
- shellwords.cabal +3/−5
- src/ShellWords.hs +24/−22
- test/ShellWordsSpec.hs +10/−13
CHANGELOG.md view
@@ -1,6 +1,14 @@-## [*Unreleased*](https://github.com/pbrisbin/hs-shellwords/compare/v0.1.0.0...master)+## [*Unreleased*](https://github.com/pbrisbin/hs-shellwords/compare/v0.1.2.0...master) None++## [v0.1.2.0](https://github.com/pbrisbin/hs-shellwords/compare/v0.1.1.0...v0.1.2.0)++- `parse` works on `String` now, use `parseText` for the `Text` interface++## [v0.1.1.0](https://github.com/pbrisbin/hs-shellwords/compare/v0.1.0.0...v0.1.1.0)++- Bugfixes that I can't remember ## [v0.1.0.0](https://github.com/pbrisbin/hs-shellwords/tree/v0.1.0.0)
shellwords.cabal view
@@ -1,11 +1,11 @@--- This file has been generated from package.yaml by hpack version 0.20.0.+-- This file has been generated from package.yaml by hpack version 0.28.2. -- -- see: https://github.com/sol/hpack ----- hash: 2e963e67460e2f0c8a0eaacb4cd50df10ec08b0ade7f08593d3858ca6d8ce1a8+-- hash: d41ef6dd8e4fd0597b45fbd58e4127227dd0c1501032d7f7d5de8213ca96223e name: shellwords-version: 0.1.1.0+version: 0.1.2.0 synopsis: Parse strings into words, like a shell would description: See https://github.com/pbrisbin/hs-shellwords#readme category: Text@@ -18,7 +18,6 @@ license-file: LICENSE build-type: Simple cabal-version: >= 1.10- extra-source-files: CHANGELOG.md README.md@@ -51,7 +50,6 @@ base >=4.7 && <5 , hspec , shellwords- , text other-modules: ShellWordsSpec Paths_shellwords
src/ShellWords.hs view
@@ -2,6 +2,7 @@ module ShellWords ( parse+ , parseText ) where import Data.Bifunctor (first)@@ -9,53 +10,54 @@ import Data.Maybe (fromMaybe) import Data.Semigroup ((<>)) import Data.Text (Text)-import Data.Text as T+import qualified Data.Text as T import Data.Void (Void) import Text.Megaparsec hiding (parse) import qualified Text.Megaparsec as Megaparsec import Text.Megaparsec.Char -type Parser = Parsec Void Text+type Parser = Parsec Void String -parse :: Text -> Either String [Text]+parse :: String -> Either String [String] parse = first parseErrorPretty . Megaparsec.parse parser "<input>" -parser :: Parser [Text]+-- | Parse and return @'Text'@ values+parseText :: Text -> Either String [Text]+parseText = fmap (map T.pack) . parse . T.unpack++parser :: Parser [String] parser = shellword `sepBy` space1 -shellword :: Parser Text+shellword :: Parser String shellword = choice [quoted, shelloption, value] -- | A balanced, single- or double-quoted string-quoted :: Parser Text+quoted :: Parser String quoted = do q <- oneOf ['\'', '\"']- T.pack <$> manyTill (try (escaped q) <|> anyToken) (char q)+ manyTill (try (escaped q) <|> anyToken) (char q) -- | A flag, with or without an argument-shelloption :: Parser Text-shelloption = (<>)- <$> flag- <*> (fromMaybe "" <$> optional argument)+shelloption :: Parser String+shelloption = (<>) <$> flag <*> (fromMaybe "" <$> optional argument) -- | A flag like @--foo@, or (apparently) @--\"baz bat\"@-flag :: Parser Text-flag = (<>)- <$> (string "--" <|> string "-")- <*> (quoted <|> (T.pack <$> many (noneOf ['=', ' '])))+flag :: Parser String+flag =+ (<>)+ <$> (string "--" <|> string "-")+ <*> (quoted <|> many (noneOf ['=', ' '])) -- | The argument to a flag like @=foo@, or @=\"baz bat\"@-argument :: Parser Text-argument = (<>)- <$> (T.singleton <$> char '=')- <*> (quoted <|> value)+argument :: Parser String+argument = (:) <$> char '=' <*> (quoted <|> value) -- | A plain value, here till an (unescaped) space-value :: Parser Text-value = T.pack <$> many (try (escaped ' ') <|> nonSpace)+value :: Parser String+value = many (try (escaped ' ') <|> nonSpace) escaped :: Char -> Parser Char-escaped c = c <$ string ("\\" <> T.singleton c)+escaped c = c <$ string ("\\" <> [c]) anyToken :: Parser Char anyToken = satisfy $ const True
test/ShellWordsSpec.hs view
@@ -12,12 +12,10 @@ import Data.Foldable (for_) import Data.Semigroup ((<>))-import Data.Text (Text)-import qualified Data.Text as T import ShellWords import Test.Hspec -testCases :: [(Text, [Text])]+testCases :: [(String, [String])] testCases = [ ("var --bar=baz", ["var", "--bar=baz"]) , ("var --bar=\"baz\"", ["var", "--bar=baz"])@@ -25,7 +23,13 @@ , ("var \"--bar='baz'\"", ["var", "--bar='baz'"]) , ("var --bar=`baz`", ["var", "--bar=`baz`"]) , ("var \"--bar=\\\"baz'\"", ["var", "--bar=\"baz'"])+ , ("var \"--bar=\\'baz\\'\"", ["var", "--bar=\\'baz\\'"])+ , ("var \"--bar baz\"", ["var", "--bar baz"])+ , ("var --\"bar baz\"", ["var", "--bar baz"])+ , ("var --\"bar baz\"", ["var", "--bar baz"])+ ] + -- Omitted cases: -- -- I think the Python test case is wrong here: --@@ -36,19 +40,12 @@ -- -- , ("var \"--bar=\\'baz\\'\"", ["var", "--bar='baz'"]) --- , ("var \"--bar=\\'baz\\'\"", ["var", "--bar=\\'baz\\'"])- -- -- I can't get this one to work: -- -- , ("var --bar='\\'", ["var", "--bar=\\"]) - , ("var \"--bar baz\"", ["var", "--bar baz"])- , ("var --\"bar baz\"", ["var", "--bar baz"])- , ("var --\"bar baz\"", ["var", "--bar baz"])- ]--errorCases :: [Text]+errorCases :: [String] errorCases = [ "foo '" , "foo \""@@ -62,11 +59,11 @@ spec :: Spec spec = describe "parse" $ do for_ testCases $ \(input, expected) -> do- it (T.unpack $ "parses |" <> input <> "| correctly") $ do+ it ("parses |" <> input <> "| correctly") $ do parse input `shouldBe` Right expected for_ errorCases $ \input -> do- it (T.unpack $ "errors on |" <> input <> "|") $ do+ it ("errors on |" <> input <> "|") $ do parse input `shouldSatisfy` isLeft isLeft :: Either a b -> Bool