fix an error when running an addon with an argument containing a single quote
More crazy quote engineering.. seems more robust than before.
This commit is contained in:
parent
8454299666
commit
0d1d3ed057
@ -32,7 +32,7 @@ import Hledger.Utils
|
||||
type RawOpts = [(String,String)]
|
||||
|
||||
setopt :: String -> String -> RawOpts -> RawOpts
|
||||
setopt name val = (++ [(name,singleQuoteIfNeeded val)])
|
||||
setopt name val = (++ [(name, quoteIfNeeded val)])
|
||||
|
||||
setboolopt :: String -> RawOpts -> RawOpts
|
||||
setboolopt name = (++ [(name,"")])
|
||||
|
||||
@ -33,6 +33,7 @@ module Hledger.Query (
|
||||
matchesAccount,
|
||||
matchesMixedAmount,
|
||||
matchesAmount,
|
||||
words'',
|
||||
-- * tests
|
||||
tests_Hledger_Query
|
||||
)
|
||||
@ -169,18 +170,17 @@ tests_parseQuery = [
|
||||
words'' :: [String] -> String -> [String]
|
||||
words'' prefixes = fromparse . parsewith maybeprefixedquotedphrases -- XXX
|
||||
where
|
||||
maybeprefixedquotedphrases = choice' [prefixedQuotedPattern, quotedPattern, pattern] `sepBy` many1 spacenonewline
|
||||
maybeprefixedquotedphrases = choice' [prefixedQuotedPattern, singleQuotedPattern, doubleQuotedPattern, pattern] `sepBy` many1 spacenonewline
|
||||
prefixedQuotedPattern = do
|
||||
not' <- fromMaybe "" `fmap` (optionMaybe $ string "not:")
|
||||
let allowednexts | null not' = prefixes
|
||||
| otherwise = prefixes ++ [""]
|
||||
next <- choice' $ map string allowednexts
|
||||
let prefix = not' ++ next
|
||||
p <- quotedPattern
|
||||
p <- singleQuotedPattern <|> doubleQuotedPattern
|
||||
return $ prefix ++ stripquotes p
|
||||
quotedPattern = do
|
||||
p <- between (oneOf "'\"") (oneOf "'\"") $ many $ noneOf "'\""
|
||||
return $ stripquotes p
|
||||
singleQuotedPattern = between (char '\'') (char '\'') (many $ noneOf "'") >>= return . stripquotes
|
||||
doubleQuotedPattern = between (char '"') (char '"') (many $ noneOf "\"") >>= return . stripquotes
|
||||
pattern = many (noneOf " \n\r")
|
||||
|
||||
tests_words'' = [
|
||||
|
||||
@ -91,7 +91,7 @@ underline s = s' ++ replicate (length s) '-' ++ "\n"
|
||||
| last s == '\n' = s
|
||||
| otherwise = s ++ "\n"
|
||||
|
||||
-- | Wrap a string in single quotes, and \-prefix any embedded single
|
||||
-- | Wrap a string in double quotes, and \-prefix any embedded single
|
||||
-- quotes, if it contains whitespace and is not already single- or
|
||||
-- double-quoted.
|
||||
quoteIfSpaced :: String -> String
|
||||
@ -99,6 +99,22 @@ quoteIfSpaced s | isSingleQuoted s || isDoubleQuoted s = s
|
||||
| not $ any (`elem` s) whitespacechars = s
|
||||
| otherwise = "'"++escapeSingleQuotes s++"'"
|
||||
|
||||
-- | Double-quote this string if it contains whitespace, single quotes
|
||||
-- or double-quotes, escaping the quotes as needed.
|
||||
quoteIfNeeded s | any (`elem` s) (quotechars++whitespacechars) = "\"" ++ escapeDoubleQuotes s ++ "\""
|
||||
| otherwise = s
|
||||
|
||||
-- | Single-quote this string if it contains whitespace or double-quotes.
|
||||
-- No good for strings containing single quotes.
|
||||
singleQuoteIfNeeded s | any (`elem` s) whitespacechars = "'"++s++"'"
|
||||
| otherwise = s
|
||||
|
||||
quotechars = "'\""
|
||||
whitespacechars = " \t\n\r"
|
||||
|
||||
escapeDoubleQuotes :: String -> String
|
||||
escapeDoubleQuotes = regexReplace "\"" "\""
|
||||
|
||||
escapeSingleQuotes :: String -> String
|
||||
escapeSingleQuotes = regexReplace "'" "\'"
|
||||
|
||||
@ -111,22 +127,17 @@ words' :: String -> [String]
|
||||
words' "" = []
|
||||
words' s = map stripquotes $ fromparse $ parsewith p s
|
||||
where
|
||||
p = do ss <- (quotedPattern <|> pattern) `sepBy` many1 spacenonewline
|
||||
p = do ss <- (singleQuotedPattern <|> doubleQuotedPattern <|> pattern) `sepBy` many1 spacenonewline
|
||||
-- eof
|
||||
return ss
|
||||
pattern = many (noneOf whitespacechars)
|
||||
quotedPattern = between (oneOf "'\"") (oneOf "'\"") $ many $ noneOf "'\""
|
||||
singleQuotedPattern = between (char '\'') (char '\'') (many $ noneOf "'")
|
||||
doubleQuotedPattern = between (char '"') (char '"') (many $ noneOf "\"")
|
||||
|
||||
-- | Quote-aware version of unwords - single-quote strings which contain whitespace
|
||||
unwords' :: [String] -> String
|
||||
unwords' = unwords . map singleQuoteIfNeeded
|
||||
|
||||
-- | Single-quote this string if it contains whitespace or double-quotes
|
||||
singleQuoteIfNeeded s | any (`elem` s) whitespacechars = "'"++s++"'"
|
||||
| otherwise = s
|
||||
|
||||
whitespacechars = " \t\n\r"
|
||||
|
||||
-- | Strip one matching pair of single or double quotes on the ends of a string.
|
||||
stripquotes :: String -> String
|
||||
stripquotes s = if isSingleQuoted s || isDoubleQuoted s then init $ tail s else s
|
||||
|
||||
Loading…
Reference in New Issue
Block a user