@@ -259,6 +259,7 @@ data CliArg
259259 | QuotedArg
260260 String
261261 Bool -- whether the quote was terminated
262+ Char -- the quote character used
262263 | UnquotedArg String
263264 deriving (Eq , Show )
264265
@@ -271,8 +272,8 @@ renderCliArg =
271272 NumberedRange s e -> show s <> " -" <> show e
272273 NumberedAfterStart s -> show s <> " -"
273274 NumberedBeforeEnd e -> " -" <> show e
274- QuotedArg s False -> " \" " <> s <> " \" "
275- QuotedArg s True -> " \" " <> s
275+ QuotedArg s False quoteChar -> [quoteChar] <> s <> [quoteChar]
276+ QuotedArg s True quoteChar -> [quoteChar] <> s
276277 UnquotedArg s -> s
277278
278279-- | Like `renderCliArg`, but does not include quotes regardless of whether the argument was quoted.
@@ -284,8 +285,8 @@ renderCliArgUnquoted =
284285 NumberedRange s e -> show s <> " -" <> show e
285286 NumberedAfterStart s -> show s <> " -"
286287 NumberedBeforeEnd e -> " -" <> show e
287- QuotedArg s False -> s
288- QuotedArg s True -> s
288+ QuotedArg s False _quoteChar -> s
289+ QuotedArg s True _quoteChar -> s
289290 UnquotedArg s -> s
290291
291292-- | Like `parseArgs`, but indicates whether each argument was quoted, and also whether the quote was terminated..
@@ -308,7 +309,7 @@ argP = do
308309 escapedQuote :: Parser Char
309310 escapedQuote = do
310311 _ <- MP. char ' \\ '
311- MP. char ' "'
312+ MP. char ' "' <|> MP. char ' \' '
312313
313314 numberedArgP :: Parser CliArg
314315 numberedArgP = do
@@ -334,13 +335,13 @@ argP = do
334335
335336 quotedArgP :: Parser CliArg
336337 quotedArgP = do
337- _ <- MP. char ' "'
338+ quoteChar <- MP. char ' "' <|> MP. char ' \' '
338339 (content, hasUnterminatedQuote) <-
339340 MP. manyTill_
340341 (escapedQuote <|> MP. anySingle)
341342 -- Treat EOF as closing quote so completion still functions on unterminated quotes
342- (((MP. char ' " ' ) $> False ) <|> (MP. eof $> True ))
343- pure $ QuotedArg content hasUnterminatedQuote
343+ (((MP. char quoteChar ) $> False ) <|> (MP. eof $> True ))
344+ pure $ QuotedArg content hasUnterminatedQuote quoteChar
344345 unquotedArgP :: Parser CliArg
345346 unquotedArgP = do
346347 UnquotedArg <$> MP. some (MP. satisfy (not . Char. isSpace))
@@ -349,14 +350,14 @@ argP = do
349350-- Just [UnquotedArg "one",UnquotedArg "two",UnquotedArg "three"]
350351--
351352-- >>> MP.parseMaybe argsP "\"one two\" three"
352- -- Just [QuotedArg "one two" False,UnquotedArg "three"]
353+ -- Just [QuotedArg "one two" False '"' ,UnquotedArg "three"]
353354--
354355-- >>> MP.parseMaybe argsP "one two three"
355356-- Just [UnquotedArg "one",UnquotedArg "two",UnquotedArg "three"]
356357--
357358-- Unfinished quote should auto-close quote at end of input, but indicate that it was unterminated
358359-- >>> MP.parseMaybe argsP "one two \"three four"
359- -- Just [UnquotedArg "one",UnquotedArg "two",QuotedArg "three four" True]
360+ -- Just [UnquotedArg "one",UnquotedArg "two",QuotedArg "three four" True '"' ]
360361--
361362-- Should require args to take up a whole segment, and should fall back to raw args.
362363-- >>> MP.parseMaybe argsP "1.2.3 abc-def"
0 commit comments