queries: Update boolean queries to be case-insensitive
That is, the query operators AND, OR, and NOT are now case-insensitive. Queries are otherwise left the same as they were.
This commit is contained in:
parent
cddbae6467
commit
891853d2f2
@ -84,7 +84,7 @@ import qualified Data.Text as T
|
||||
import Data.Time.Calendar (Day, fromGregorian )
|
||||
import Safe (readDef, readMay, maximumByMay, maximumMay, minimumMay)
|
||||
import Text.Megaparsec (between, noneOf, sepBy, try, (<?>), notFollowedBy)
|
||||
import Text.Megaparsec.Char (char, string)
|
||||
import Text.Megaparsec.Char (char, string, string')
|
||||
|
||||
|
||||
import Hledger.Utils hiding (words')
|
||||
@ -359,18 +359,18 @@ parseBooleanQuery d t = either (Left . ("failed to parse query:" <>) . customErr
|
||||
Left err -> error' err
|
||||
|
||||
keywordSpaceP :: SimpleTextParser T.Text
|
||||
keywordSpaceP = choice' ["NOT ", "AND ", "OR "]
|
||||
keywordSpaceP = choice' (string' <$> ["not ", "and ", "or "])
|
||||
|
||||
parQueryP,notQueryP :: SimpleTextParser (Query, [QueryOpt])
|
||||
parQueryP = between (char '(' >> skipNonNewlineSpaces)
|
||||
(try $ skipNonNewlineSpaces >> char ')')
|
||||
spacedQueriesP
|
||||
<|> queryTermP
|
||||
notQueryP = (maybe id (\_ (q, qopts) -> (Not q, qopts)) <$> optional (string "NOT" >> skipNonNewlineSpaces1)) <*> parQueryP
|
||||
notQueryP = (maybe id (\_ (q, qopts) -> (Not q, qopts)) <$> optional (try $ string' "not" >> notFollowedBy (char ':') >> skipNonNewlineSpaces1)) <*> parQueryP
|
||||
|
||||
andQueriesP,orQueriesP,spacedQueriesP :: SimpleTextParser (Query, [QueryOpt])
|
||||
andQueriesP = nArityOp And <$> notQueryP `sepBy` (try $ skipNonNewlineSpaces >> string "AND" >> skipNonNewlineSpaces1)
|
||||
orQueriesP = nArityOp Or <$> andQueriesP `sepBy` (try $ skipNonNewlineSpaces >> string "OR" >> skipNonNewlineSpaces1)
|
||||
andQueriesP = nArityOp And <$> notQueryP `sepBy` (try $ skipNonNewlineSpaces >> string' "and" >> skipNonNewlineSpaces1)
|
||||
orQueriesP = nArityOp Or <$> andQueriesP `sepBy` (try $ skipNonNewlineSpaces >> string' "or" >> skipNonNewlineSpaces1)
|
||||
spacedQueriesP = nArityOp combineQueryList <$> orQueriesP `sepBy` skipNonNewlineSpaces1
|
||||
|
||||
nArityOp :: ([Query] -> Query) -> [(Query, [QueryOpt])] -> (Query, [QueryOpt])
|
||||
@ -939,6 +939,9 @@ tests_Query = testGroup "Query" [
|
||||
parseBooleanQuery nulldate " acct:'a' acct:'b'" @?= Right (Or [Acct $ toRegexCI' "a", Acct $ toRegexCI' "b"], [])
|
||||
parseBooleanQuery nulldate "not:a" @?= Right (Not $ Acct $ toRegexCI' "a", [])
|
||||
parseBooleanQuery nulldate "expenses:food OR (tag:A expenses:drink)" @?= Right (Or [Acct $ toRegexCI' "expenses:food", And [Acct $ toRegexCI' "expenses:drink", Tag (toRegexCI' "A") Nothing]], [])
|
||||
parseBooleanQuery nulldate "not a" @?= Right (Not $ Acct $ toRegexCI' "a", [])
|
||||
parseBooleanQuery nulldate "nota" @?= Right (Acct $ toRegexCI' "nota", [])
|
||||
parseBooleanQuery nulldate "not (acct:a)" @?= Right (Not $ Acct $ toRegexCI' "a", [])
|
||||
|
||||
,testCase "words''" $ do
|
||||
(words'' [] "a b") @?= ["a","b"]
|
||||
|
||||
@ -93,3 +93,54 @@ $ hledger -f - print expr:"NOT tag:'transactiontag=B' OR desc:4"
|
||||
expenses:drink
|
||||
|
||||
>=
|
||||
|
||||
# 7. Boolean expression query keywords are case insensitive
|
||||
$ hledger -f - print expr:"NoT tag:'transactiontag=B' OR desc:4"
|
||||
2022-01-01 Transaction 1 ; transactiontag:A
|
||||
assets:bank:main -1 ; A comment
|
||||
expenses:food
|
||||
|
||||
2022-01-01 Transaction 2 ; transactiontag:A
|
||||
assets:bank:main -1
|
||||
assets:bank:secondary -1 ; atag:a
|
||||
expenses:food
|
||||
|
||||
2022-01-01 Transaction 4 ; transactiontag:B
|
||||
assets:bank:main -1 ; A comment
|
||||
expenses:food 2
|
||||
expenses:drink
|
||||
|
||||
>=
|
||||
|
||||
# 8. Lower case not is not confused with existing not: queries
|
||||
$ hledger -f - print expr:"not tag:transactiontag=B"
|
||||
2022-01-01 Transaction 1 ; transactiontag:A
|
||||
assets:bank:main -1 ; A comment
|
||||
expenses:food
|
||||
|
||||
2022-01-01 Transaction 2 ; transactiontag:A
|
||||
assets:bank:main -1
|
||||
assets:bank:secondary -1 ; atag:a
|
||||
expenses:food
|
||||
|
||||
>=
|
||||
|
||||
# 9. Having parentheses directly follow 'not' sees 'not' as part of a query.
|
||||
$ hledger -f - print expr:"not(tag:transactiontag=B)"
|
||||
>2
|
||||
hledger: Error: This regular expression is malformed, please correct it:
|
||||
not(tag:transactiontag=B
|
||||
>=1
|
||||
|
||||
# 10. ... whereas parentheses with a space between 'not' and '(' is fine.
|
||||
$ hledger -f - print expr:"not (tag:transactiontag=B)"
|
||||
2022-01-01 Transaction 1 ; transactiontag:A
|
||||
assets:bank:main -1 ; A comment
|
||||
expenses:food
|
||||
|
||||
2022-01-01 Transaction 2 ; transactiontag:A
|
||||
assets:bank:main -1
|
||||
assets:bank:secondary -1 ; atag:a
|
||||
expenses:food
|
||||
|
||||
>=
|
||||
|
||||
Loading…
Reference in New Issue
Block a user