From fff9087ff75a7abe1fd33280f449fe4d9f154b33 Mon Sep 17 00:00:00 2001 From: Nikolay Yakimov Date: Sun, 27 Dec 2015 02:42:45 +0300 Subject: [PATCH 1/4] [Shell-Parse] Use \STX and \ETX for quoting Also drops escaping --- src/GHCMod/Options/ShellParse.hs | 34 +++++++++----------------------- test/ShellParseSpec.hs | 24 +++------------------- 2 files changed, 12 insertions(+), 46 deletions(-) diff --git a/src/GHCMod/Options/ShellParse.hs b/src/GHCMod/Options/ShellParse.hs index 5799906..4ad4efe 100644 --- a/src/GHCMod/Options/ShellParse.hs +++ b/src/GHCMod/Options/ShellParse.hs @@ -16,35 +16,19 @@ module GHCMod.Options.ShellParse (parseCmdLine) where import Data.Char -import Data.Maybe -isQuote :: Char -> Bool -isQuote = (==) '"' - -isEscapeChar :: Char -> Bool -isEscapeChar = (==) '\\' - -isEscapable :: Char -> Bool -isEscapable c = any ($ c) [isSpace, isQuote, isEscapeChar] - -go :: String -> String -> [String] -> Maybe Char -> [String] +go :: String -> String -> [String] -> Bool -> [String] -- result go [] curarg accargs _ = reverse $ reverse curarg : accargs --- escaped character -go (esc:c:cl) curarg accargs quote - | isEscapeChar esc - = if isEscapable c - then go cl (c:curarg) accargs quote - else go (c:cl) (esc:curarg) accargs quote go (c:cl) curarg accargs quotes - -- quote character -- opens quotes - | isQuote c, isNothing quotes - = go cl curarg accargs (Just c) + -- open quotes + | c == '\STX', not quotes + = go cl curarg accargs True -- close quotes - | quotes == Just c - = go cl curarg accargs Nothing - -- space separates argumetns outside quotes - | isSpace c, isNothing quotes + | c == '\ETX', quotes + = go cl curarg accargs False + -- space separates arguments outside quotes + | isSpace c, not quotes = if null curarg then go cl curarg accargs quotes else go cl [] (reverse curarg : accargs) quotes @@ -52,4 +36,4 @@ go (c:cl) curarg accargs quotes | otherwise = go cl (c:curarg) accargs quotes parseCmdLine :: String -> [String] -parseCmdLine comline = go comline [] [] Nothing +parseCmdLine comline = go comline [] [] False diff --git a/test/ShellParseSpec.hs b/test/ShellParseSpec.hs index 3d02f43..8817ec7 100644 --- a/test/ShellParseSpec.hs +++ b/test/ShellParseSpec.hs @@ -10,27 +10,9 @@ spec = describe "parseCmdLine" $ do it "splits arguments" $ parseCmdLine "test command line" `shouldBe` ["test", "command", "line"] - it "honors double quotes" $ - parseCmdLine "test command line \"with double quotes\"" - `shouldBe` ["test", "command", "line", "with double quotes"] - it "escapes spaces" $ do - parseCmdLine "with\\ spaces" - `shouldBe` ["with spaces"] - parseCmdLine "\"with\\ spaces\"" - `shouldBe` ["with spaces"] - it "escapes '\\'" $ do - parseCmdLine "\\\\" - `shouldBe` ["\\"] - parseCmdLine "\"\\\\\"" - `shouldBe` ["\\"] - it "escapes double quotes" $ do - parseCmdLine "\\\"" - `shouldBe` ["\""] - parseCmdLine "\"\\\"\"" - `shouldBe` ["\""] - it "doesn't escape random characters" $ - parseCmdLine "\\a\\b\\c" - `shouldBe` ["\\a\\b\\c"] + it "honors quoted segments" $ + parseCmdLine "test command line \STXwith quoted segment\ETX" + `shouldBe` ["test", "command", "line", "with quoted segment"] it "squashes multiple spaces" $ parseCmdLine "test command" `shouldBe` ["test", "command"] From d49d4cf2ea9a227e3f310105a8d7d2cb31426d95 Mon Sep 17 00:00:00 2001 From: Nikolay Yakimov Date: Wed, 30 Dec 2015 20:46:06 +0300 Subject: [PATCH 2/4] [Shell-escape] Escape toggle with \ prefix E.g. check file.hs will treat quote characters as literal characters, while \check file.hs will assume quoting behavior Backslash will be dropped, naturally. --- src/GHCMod/Options/ShellParse.hs | 4 +++- test/ShellParseSpec.hs | 14 ++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/GHCMod/Options/ShellParse.hs b/src/GHCMod/Options/ShellParse.hs index 4ad4efe..2bcba0c 100644 --- a/src/GHCMod/Options/ShellParse.hs +++ b/src/GHCMod/Options/ShellParse.hs @@ -36,4 +36,6 @@ go (c:cl) curarg accargs quotes | otherwise = go cl (c:curarg) accargs quotes parseCmdLine :: String -> [String] -parseCmdLine comline = go comline [] [] False +parseCmdLine ('\\':comline) = go comline [] [] False +parseCmdLine [] = [""] +parseCmdLine comline = words comline diff --git a/test/ShellParseSpec.hs b/test/ShellParseSpec.hs index 8817ec7..30274f9 100644 --- a/test/ShellParseSpec.hs +++ b/test/ShellParseSpec.hs @@ -8,11 +8,17 @@ import Test.Hspec spec :: Spec spec = describe "parseCmdLine" $ do - it "splits arguments" $ + it "splits arguments" $ do parseCmdLine "test command line" `shouldBe` ["test", "command", "line"] - it "honors quoted segments" $ - parseCmdLine "test command line \STXwith quoted segment\ETX" + parseCmdLine "\\test command line" `shouldBe` ["test", "command", "line"] + it "honors quoted segments if turned on" $ + parseCmdLine "\\test command line \STXwith quoted segment\ETX" `shouldBe` ["test", "command", "line", "with quoted segment"] - it "squashes multiple spaces" $ + it "doesn't honor quoted segments if turned off" $ + parseCmdLine "test command line \STXwith quoted segment\ETX" + `shouldBe` words "test command line \STXwith quoted segment\ETX" + it "squashes multiple spaces" $ do parseCmdLine "test command" `shouldBe` ["test", "command"] + parseCmdLine "\\test command" + `shouldBe` ["test", "command"] From 849496c0473b4fadd34ebf6b524cbe2737256d8f Mon Sep 17 00:00:00 2001 From: Nikolay Yakimov Date: Wed, 30 Dec 2015 21:11:39 +0300 Subject: [PATCH 3/4] [Shell-escape] 'ascii-escape ' prefix toggle --- src/GHCMod/Options/ShellParse.hs | 5 ++++- test/ShellParseSpec.hs | 11 ++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/GHCMod/Options/ShellParse.hs b/src/GHCMod/Options/ShellParse.hs index 2bcba0c..acd609b 100644 --- a/src/GHCMod/Options/ShellParse.hs +++ b/src/GHCMod/Options/ShellParse.hs @@ -16,6 +16,7 @@ module GHCMod.Options.ShellParse (parseCmdLine) where import Data.Char +import Data.List go :: String -> String -> [String] -> Bool -> [String] -- result @@ -36,6 +37,8 @@ go (c:cl) curarg accargs quotes | otherwise = go cl (c:curarg) accargs quotes parseCmdLine :: String -> [String] -parseCmdLine ('\\':comline) = go comline [] [] False +parseCmdLine comline' + | Just comline <- stripPrefix "ascii-escape " $ dropWhile isSpace comline' + = go (dropWhile isSpace comline) [] [] False parseCmdLine [] = [""] parseCmdLine comline = words comline diff --git a/test/ShellParseSpec.hs b/test/ShellParseSpec.hs index 30274f9..5517a11 100644 --- a/test/ShellParseSpec.hs +++ b/test/ShellParseSpec.hs @@ -10,9 +10,9 @@ spec = describe "parseCmdLine" $ do it "splits arguments" $ do parseCmdLine "test command line" `shouldBe` ["test", "command", "line"] - parseCmdLine "\\test command line" `shouldBe` ["test", "command", "line"] + parseCmdLine "ascii-escape test command line" `shouldBe` ["test", "command", "line"] it "honors quoted segments if turned on" $ - parseCmdLine "\\test command line \STXwith quoted segment\ETX" + parseCmdLine "ascii-escape test command line \STXwith quoted segment\ETX" `shouldBe` ["test", "command", "line", "with quoted segment"] it "doesn't honor quoted segments if turned off" $ parseCmdLine "test command line \STXwith quoted segment\ETX" @@ -20,5 +20,10 @@ spec = it "squashes multiple spaces" $ do parseCmdLine "test command" `shouldBe` ["test", "command"] - parseCmdLine "\\test command" + parseCmdLine "ascii-escape test command" + `shouldBe` ["test", "command"] + it "ingores leading spaces" $ do + parseCmdLine " test command" + `shouldBe` ["test", "command"] + parseCmdLine " ascii-escape test command" `shouldBe` ["test", "command"] From 9f5dc6dc3cf8112bec1b77531ecf866e179c100c Mon Sep 17 00:00:00 2001 From: Nikolay Yakimov Date: Wed, 30 Dec 2015 21:18:57 +0300 Subject: [PATCH 4/4] [Shell-escape] Add empty input string test --- test/ShellParseSpec.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/ShellParseSpec.hs b/test/ShellParseSpec.hs index 5517a11..2c5cefe 100644 --- a/test/ShellParseSpec.hs +++ b/test/ShellParseSpec.hs @@ -27,3 +27,8 @@ spec = `shouldBe` ["test", "command"] parseCmdLine " ascii-escape test command" `shouldBe` ["test", "command"] + it "parses empty string as no argument" $ do + parseCmdLine "" + `shouldBe` [""] + parseCmdLine "ascii-escape " + `shouldBe` [""]