From f61d1bfa8a36e2f50fcfa7efc7612317d79da2a1 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Sat, 7 May 2016 22:45:25 +0200 Subject: Parse line input to argument list --- src/Command.hs | 41 ++++++++++++++++++++++++++++++++++++++++- src/Main.hs | 1 + 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/Command.hs b/src/Command.hs index fd21087..49dc966 100644 --- a/src/Command.hs +++ b/src/Command.hs @@ -5,6 +5,8 @@ module Command , parseCmd ) where +import Data.Char (isSpace) + import Types data Cmd = PerformAlt Alteration @@ -12,6 +14,43 @@ data Cmd = PerformAlt Alteration | Step | UnknownCommand String | ParseError String + | Empty parseCmd :: SequenceM m => String -> m Cmd -parseCmd input = return $ UnknownCommand input +parseCmd = parseCmd' . split + where + split :: String -> [String] + split = reverse . split' [] "" Nothing Nothing + split' :: [String] -> String -> Maybe Char -> Maybe Char -> String -> [String] + split' ws w q e "" = trimStart $ (prepend q . append e $ reverse w):ws + where + prepend (Just c) = (c : ) + prepend _ = id + append (Just c) = (++ [c]) + append _ = id + trimStart ("":ws) = ws + trimStart ws = ws + split' ws w q e (c:cs) + | null w + , Nothing <- q + , Nothing <- e + , isQuote c = split' ws w (Just c) Nothing cs -- Start quoted word at unescaped quote + | Nothing <- e + , (Just q') <- q + , c == q' = split' (reverse w : ws) "" Nothing Nothing cs -- Close quoted word at unescaped quote of same type + | null w + , isSpace c + , Nothing <- e + , Nothing <- q = split' ws w Nothing Nothing cs -- Ignore leading unescaped spaces if not within quotes + | isSpace c + , Nothing <- e + , Nothing <- q = split' (reverse w : ws) "" Nothing Nothing cs -- Close unquoted word at unescaped space + | Nothing <- e + , isEscape c = split' ws w q (Just c) cs -- Set escaped flag at unescaped escape char + | otherwise = split' ws (c : w) q Nothing cs -- Append to word + isQuote q = q `elem` ['"', '\''] + isEscape e = e == '\\' + +parseCmd' :: SequenceM m => [String] -> m Cmd +parseCmd' [] = return Empty +parseCmd' (cmd:args) = return $ UnknownCommand (show $ cmd:args) -- DEBUG diff --git a/src/Main.hs b/src/Main.hs index c4c09bc..e6a3024 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -44,6 +44,7 @@ runCli = do lift . outputStrLn $ "Unknown command: »" <> cmd <> "«" ParseError err -> do lift . outputStrLn $ "Error parsing input »" <> (fromMaybe "" input) <> "«: " <> err + Empty -> return () Quit -> liftIO exitSuccess PerformAlt alt -> apply' alt -- cgit v1.2.3