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)]
|
type RawOpts = [(String,String)]
|
||||||
|
|
||||||
setopt :: String -> String -> RawOpts -> RawOpts
|
setopt :: String -> String -> RawOpts -> RawOpts
|
||||||
setopt name val = (++ [(name,singleQuoteIfNeeded val)])
|
setopt name val = (++ [(name, quoteIfNeeded val)])
|
||||||
|
|
||||||
setboolopt :: String -> RawOpts -> RawOpts
|
setboolopt :: String -> RawOpts -> RawOpts
|
||||||
setboolopt name = (++ [(name,"")])
|
setboolopt name = (++ [(name,"")])
|
||||||
|
|||||||
@ -33,6 +33,7 @@ module Hledger.Query (
|
|||||||
matchesAccount,
|
matchesAccount,
|
||||||
matchesMixedAmount,
|
matchesMixedAmount,
|
||||||
matchesAmount,
|
matchesAmount,
|
||||||
|
words'',
|
||||||
-- * tests
|
-- * tests
|
||||||
tests_Hledger_Query
|
tests_Hledger_Query
|
||||||
)
|
)
|
||||||
@ -169,18 +170,17 @@ tests_parseQuery = [
|
|||||||
words'' :: [String] -> String -> [String]
|
words'' :: [String] -> String -> [String]
|
||||||
words'' prefixes = fromparse . parsewith maybeprefixedquotedphrases -- XXX
|
words'' prefixes = fromparse . parsewith maybeprefixedquotedphrases -- XXX
|
||||||
where
|
where
|
||||||
maybeprefixedquotedphrases = choice' [prefixedQuotedPattern, quotedPattern, pattern] `sepBy` many1 spacenonewline
|
maybeprefixedquotedphrases = choice' [prefixedQuotedPattern, singleQuotedPattern, doubleQuotedPattern, pattern] `sepBy` many1 spacenonewline
|
||||||
prefixedQuotedPattern = do
|
prefixedQuotedPattern = do
|
||||||
not' <- fromMaybe "" `fmap` (optionMaybe $ string "not:")
|
not' <- fromMaybe "" `fmap` (optionMaybe $ string "not:")
|
||||||
let allowednexts | null not' = prefixes
|
let allowednexts | null not' = prefixes
|
||||||
| otherwise = prefixes ++ [""]
|
| otherwise = prefixes ++ [""]
|
||||||
next <- choice' $ map string allowednexts
|
next <- choice' $ map string allowednexts
|
||||||
let prefix = not' ++ next
|
let prefix = not' ++ next
|
||||||
p <- quotedPattern
|
p <- singleQuotedPattern <|> doubleQuotedPattern
|
||||||
return $ prefix ++ stripquotes p
|
return $ prefix ++ stripquotes p
|
||||||
quotedPattern = do
|
singleQuotedPattern = between (char '\'') (char '\'') (many $ noneOf "'") >>= return . stripquotes
|
||||||
p <- between (oneOf "'\"") (oneOf "'\"") $ many $ noneOf "'\""
|
doubleQuotedPattern = between (char '"') (char '"') (many $ noneOf "\"") >>= return . stripquotes
|
||||||
return $ stripquotes p
|
|
||||||
pattern = many (noneOf " \n\r")
|
pattern = many (noneOf " \n\r")
|
||||||
|
|
||||||
tests_words'' = [
|
tests_words'' = [
|
||||||
|
|||||||
@ -91,7 +91,7 @@ underline s = s' ++ replicate (length s) '-' ++ "\n"
|
|||||||
| last s == '\n' = s
|
| last s == '\n' = s
|
||||||
| otherwise = s ++ "\n"
|
| 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
|
-- quotes, if it contains whitespace and is not already single- or
|
||||||
-- double-quoted.
|
-- double-quoted.
|
||||||
quoteIfSpaced :: String -> String
|
quoteIfSpaced :: String -> String
|
||||||
@ -99,6 +99,22 @@ quoteIfSpaced s | isSingleQuoted s || isDoubleQuoted s = s
|
|||||||
| not $ any (`elem` s) whitespacechars = s
|
| not $ any (`elem` s) whitespacechars = s
|
||||||
| otherwise = "'"++escapeSingleQuotes 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 :: String -> String
|
||||||
escapeSingleQuotes = regexReplace "'" "\'"
|
escapeSingleQuotes = regexReplace "'" "\'"
|
||||||
|
|
||||||
@ -111,22 +127,17 @@ words' :: String -> [String]
|
|||||||
words' "" = []
|
words' "" = []
|
||||||
words' s = map stripquotes $ fromparse $ parsewith p s
|
words' s = map stripquotes $ fromparse $ parsewith p s
|
||||||
where
|
where
|
||||||
p = do ss <- (quotedPattern <|> pattern) `sepBy` many1 spacenonewline
|
p = do ss <- (singleQuotedPattern <|> doubleQuotedPattern <|> pattern) `sepBy` many1 spacenonewline
|
||||||
-- eof
|
-- eof
|
||||||
return ss
|
return ss
|
||||||
pattern = many (noneOf whitespacechars)
|
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
|
-- | Quote-aware version of unwords - single-quote strings which contain whitespace
|
||||||
unwords' :: [String] -> String
|
unwords' :: [String] -> String
|
||||||
unwords' = unwords . map singleQuoteIfNeeded
|
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.
|
-- | Strip one matching pair of single or double quotes on the ends of a string.
|
||||||
stripquotes :: String -> String
|
stripquotes :: String -> String
|
||||||
stripquotes s = if isSingleQuoted s || isDoubleQuoted s then init $ tail s else s
|
stripquotes s = if isSingleQuoted s || isDoubleQuoted s then init $ tail s else s
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user