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 Data.Time.Calendar (Day, fromGregorian )
|
||||||
import Safe (readDef, readMay, maximumByMay, maximumMay, minimumMay)
|
import Safe (readDef, readMay, maximumByMay, maximumMay, minimumMay)
|
||||||
import Text.Megaparsec (between, noneOf, sepBy, try, (<?>), notFollowedBy)
|
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')
|
import Hledger.Utils hiding (words')
|
||||||
@ -359,18 +359,18 @@ parseBooleanQuery d t = either (Left . ("failed to parse query:" <>) . customErr
|
|||||||
Left err -> error' err
|
Left err -> error' err
|
||||||
|
|
||||||
keywordSpaceP :: SimpleTextParser T.Text
|
keywordSpaceP :: SimpleTextParser T.Text
|
||||||
keywordSpaceP = choice' ["NOT ", "AND ", "OR "]
|
keywordSpaceP = choice' (string' <$> ["not ", "and ", "or "])
|
||||||
|
|
||||||
parQueryP,notQueryP :: SimpleTextParser (Query, [QueryOpt])
|
parQueryP,notQueryP :: SimpleTextParser (Query, [QueryOpt])
|
||||||
parQueryP = between (char '(' >> skipNonNewlineSpaces)
|
parQueryP = between (char '(' >> skipNonNewlineSpaces)
|
||||||
(try $ skipNonNewlineSpaces >> char ')')
|
(try $ skipNonNewlineSpaces >> char ')')
|
||||||
spacedQueriesP
|
spacedQueriesP
|
||||||
<|> queryTermP
|
<|> 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,orQueriesP,spacedQueriesP :: SimpleTextParser (Query, [QueryOpt])
|
||||||
andQueriesP = nArityOp And <$> notQueryP `sepBy` (try $ skipNonNewlineSpaces >> string "AND" >> skipNonNewlineSpaces1)
|
andQueriesP = nArityOp And <$> notQueryP `sepBy` (try $ skipNonNewlineSpaces >> string' "and" >> skipNonNewlineSpaces1)
|
||||||
orQueriesP = nArityOp Or <$> andQueriesP `sepBy` (try $ skipNonNewlineSpaces >> string "OR" >> skipNonNewlineSpaces1)
|
orQueriesP = nArityOp Or <$> andQueriesP `sepBy` (try $ skipNonNewlineSpaces >> string' "or" >> skipNonNewlineSpaces1)
|
||||||
spacedQueriesP = nArityOp combineQueryList <$> orQueriesP `sepBy` skipNonNewlineSpaces1
|
spacedQueriesP = nArityOp combineQueryList <$> orQueriesP `sepBy` skipNonNewlineSpaces1
|
||||||
|
|
||||||
nArityOp :: ([Query] -> Query) -> [(Query, [QueryOpt])] -> (Query, [QueryOpt])
|
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 " acct:'a' acct:'b'" @?= Right (Or [Acct $ toRegexCI' "a", Acct $ toRegexCI' "b"], [])
|
||||||
parseBooleanQuery nulldate "not:a" @?= Right (Not $ Acct $ toRegexCI' "a", [])
|
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 "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
|
,testCase "words''" $ do
|
||||||
(words'' [] "a b") @?= ["a","b"]
|
(words'' [] "a b") @?= ["a","b"]
|
||||||
|
|||||||
@ -93,3 +93,54 @@ $ hledger -f - print expr:"NOT tag:'transactiontag=B' OR desc:4"
|
|||||||
expenses:drink
|
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