Behaviour is at odds with usual shell quoting practices, violating principle of least surprise.
Examples of unexpected behaviour:
no expectation that quotes are balanced (f Quot [] should be a failure state)
non-handling of '-quoted strings
""" == \" (usually, former is a longer spelling of ")
\\ escapes only in front of "
In addition, some of the state complexity seems unwarranted.
Why not something along the lines of:
import Data.Bifunctor ( first )
import Data.Char ( isSpace )
import Data.List.NonEmpty ( NonEmpty((:|))
, (<|)
)
data IState = Lit | SingQ | DoubleQ
data OState = Break | Word
-- | split a string into quoted words
-- single/double quotes literal until next occurrence,
-- are escaped by prefixing \
-- \ is itself escaped by \
-- outside quotes, spaces break words and are coalesced
splitArgs :: String -> Maybe (NonEmpty String)
splitArgs s = snd <$> f Lit s
where
f :: IState -> String -> Maybe (OState, NonEmpty String)
f s ('\\' : x : xs) | x `elem` ['\\', '\'', '\"'] = push x <$> f s xs
f Lit ('\'' : xs) = f SingQ xs
f Lit ('\"' : xs) = f DoubleQ xs
f Lit (x : xs) | isSpace x = first (const Break) <$> f Lit xs
f SingQ ('\'' : xs) = f Lit xs
f DoubleQ ('\"' : xs) = f Lit xs
f s (x : xs) = push x <$> f s xs
f Lit [] = Just (Word, "" :| [])
f s [] = Nothing
push :: a -> (OState, NonEmpty [a]) -> (OState, NonEmpty [a])
push x (Break, xss ) = (Word, [x] <| xss)
push x (Word , xs :| xss) = (Word, (x : xs) :| xss)
Behaviour is at odds with usual shell quoting practices, violating principle of least surprise. Examples of unexpected behaviour:
f Quot []
should be a failure state)'
-quoted strings""" == \"
(usually, former is a longer spelling of"
)\\
escapes only in front of"
In addition, some of the state complexity seems unwarranted. Why not something along the lines of: