{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
module Data.Attoparsec.Args
( EscapingMode (..)
, argsParser
, parseArgs
, parseArgsFromString
) where
import Data.Attoparsec.Text ( (<?>) )
import qualified Data.Attoparsec.Text as P
import qualified Data.Text as T
import Stack.Prelude
data EscapingMode
= Escaping
| NoEscaping
deriving (Int -> EscapingMode
EscapingMode -> Int
EscapingMode -> [EscapingMode]
EscapingMode -> EscapingMode
EscapingMode -> EscapingMode -> [EscapingMode]
EscapingMode -> EscapingMode -> EscapingMode -> [EscapingMode]
(EscapingMode -> EscapingMode)
-> (EscapingMode -> EscapingMode)
-> (Int -> EscapingMode)
-> (EscapingMode -> Int)
-> (EscapingMode -> [EscapingMode])
-> (EscapingMode -> EscapingMode -> [EscapingMode])
-> (EscapingMode -> EscapingMode -> [EscapingMode])
-> (EscapingMode -> EscapingMode -> EscapingMode -> [EscapingMode])
-> Enum EscapingMode
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: EscapingMode -> EscapingMode
succ :: EscapingMode -> EscapingMode
$cpred :: EscapingMode -> EscapingMode
pred :: EscapingMode -> EscapingMode
$ctoEnum :: Int -> EscapingMode
toEnum :: Int -> EscapingMode
$cfromEnum :: EscapingMode -> Int
fromEnum :: EscapingMode -> Int
$cenumFrom :: EscapingMode -> [EscapingMode]
enumFrom :: EscapingMode -> [EscapingMode]
$cenumFromThen :: EscapingMode -> EscapingMode -> [EscapingMode]
enumFromThen :: EscapingMode -> EscapingMode -> [EscapingMode]
$cenumFromTo :: EscapingMode -> EscapingMode -> [EscapingMode]
enumFromTo :: EscapingMode -> EscapingMode -> [EscapingMode]
$cenumFromThenTo :: EscapingMode -> EscapingMode -> EscapingMode -> [EscapingMode]
enumFromThenTo :: EscapingMode -> EscapingMode -> EscapingMode -> [EscapingMode]
Enum, EscapingMode -> EscapingMode -> Bool
(EscapingMode -> EscapingMode -> Bool)
-> (EscapingMode -> EscapingMode -> Bool) -> Eq EscapingMode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: EscapingMode -> EscapingMode -> Bool
== :: EscapingMode -> EscapingMode -> Bool
$c/= :: EscapingMode -> EscapingMode -> Bool
/= :: EscapingMode -> EscapingMode -> Bool
Eq, Int -> EscapingMode -> ShowS
[EscapingMode] -> ShowS
EscapingMode -> [Char]
(Int -> EscapingMode -> ShowS)
-> (EscapingMode -> [Char])
-> ([EscapingMode] -> ShowS)
-> Show EscapingMode
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> EscapingMode -> ShowS
showsPrec :: Int -> EscapingMode -> ShowS
$cshow :: EscapingMode -> [Char]
show :: EscapingMode -> [Char]
$cshowList :: [EscapingMode] -> ShowS
showList :: [EscapingMode] -> ShowS
Show)
parseArgs :: EscapingMode -> Text -> Either String [String]
parseArgs :: EscapingMode -> Text -> Either [Char] [[Char]]
parseArgs EscapingMode
mode = Parser [[Char]] -> Text -> Either [Char] [[Char]]
forall a. Parser a -> Text -> Either [Char] a
P.parseOnly (EscapingMode -> Parser [[Char]]
argsParser EscapingMode
mode)
parseArgsFromString :: EscapingMode -> String -> Either String [String]
parseArgsFromString :: EscapingMode -> [Char] -> Either [Char] [[Char]]
parseArgsFromString EscapingMode
mode = Parser [[Char]] -> Text -> Either [Char] [[Char]]
forall a. Parser a -> Text -> Either [Char] a
P.parseOnly (EscapingMode -> Parser [[Char]]
argsParser EscapingMode
mode) (Text -> Either [Char] [[Char]])
-> ([Char] -> Text) -> [Char] -> Either [Char] [[Char]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Text
T.pack
argsParser :: EscapingMode -> P.Parser [String]
argsParser :: EscapingMode -> Parser [[Char]]
argsParser EscapingMode
mode = Parser Text [Char] -> Parser [[Char]]
forall a. Parser Text a -> Parser Text [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (Parser ()
P.skipSpace Parser () -> Parser Text [Char] -> Parser Text [Char]
forall a b. Parser Text a -> Parser Text b -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (Parser Text [Char]
quoted Parser Text [Char] -> Parser Text [Char] -> Parser Text [Char]
forall a. Parser Text a -> Parser Text a -> Parser Text a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Text [Char]
unquoted)) Parser [[Char]] -> Parser () -> Parser [[Char]]
forall a b. Parser Text a -> Parser Text b -> Parser Text a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<*
Parser ()
P.skipSpace Parser [[Char]] -> Parser () -> Parser [[Char]]
forall a b. Parser Text a -> Parser Text b -> Parser Text a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* (Parser ()
forall t. Chunk t => Parser t ()
P.endOfInput Parser () -> [Char] -> Parser ()
forall i a. Parser i a -> [Char] -> Parser i a
<?> [Char]
"unterminated string")
where
unquoted :: Parser Text [Char]
unquoted = Parser Text Char -> Parser Text [Char]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
P.many1 Parser Text Char
naked
quoted :: Parser Text [Char]
quoted = Char -> Parser Text Char
P.char Char
'"' Parser Text Char -> Parser Text [Char] -> Parser Text [Char]
forall a b. Parser Text a -> Parser Text b -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Text [Char]
str Parser Text [Char] -> Parser Text Char -> Parser Text [Char]
forall a b. Parser Text a -> Parser Text b -> Parser Text a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> Parser Text Char
P.char Char
'"'
str :: Parser Text [Char]
str = Parser Text Char -> Parser Text [Char]
forall a. Parser Text a -> Parser Text [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many ( case EscapingMode
mode of
EscapingMode
Escaping -> Parser Text Char
escaped Parser Text Char -> Parser Text Char -> Parser Text Char
forall a. Parser Text a -> Parser Text a -> Parser Text a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Text Char
nonquote
EscapingMode
NoEscaping -> Parser Text Char
nonquote
)
escaped :: Parser Text Char
escaped = Char -> Parser Text Char
P.char Char
'\\' Parser Text Char -> Parser Text Char -> Parser Text Char
forall a b. Parser Text a -> Parser Text b -> Parser Text b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Text Char
P.anyChar
nonquote :: Parser Text Char
nonquote = (Char -> Bool) -> Parser Text Char
P.satisfy (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'"')
naked :: Parser Text Char
naked = (Char -> Bool) -> Parser Text Char
P.satisfy (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> [Char] -> Bool) -> [Char] -> Char -> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip Char -> [Char] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem ([Char]
"\" " :: String))