imp: Hledger.Query: new predicates, haddock cleanups

added:
matchesQuery,
queryIsAccountRelated,
queryIsTransactionOrPostingRelated,
This commit is contained in:
Simon Michael 2022-04-14 09:55:07 -10:00
parent b82021e0b6
commit 161c911cb4

View File

@ -22,10 +22,12 @@ module Hledger.Query (
parseQueryList, parseQueryList,
parseQueryTerm, parseQueryTerm,
parseAccountType, parseAccountType,
-- * modifying
simplifyQuery, simplifyQuery,
filterQuery, filterQuery,
filterQueryOrNotQuery, filterQueryOrNotQuery,
-- * accessors matchesQuery,
-- * predicates
queryIsNull, queryIsNull,
queryIsAcct, queryIsAcct,
queryIsAmt, queryIsAmt,
@ -39,6 +41,9 @@ module Hledger.Query (
queryIsStatus, queryIsStatus,
queryIsType, queryIsType,
queryIsTag, queryIsTag,
queryIsAccountRelated,
queryIsTransactionOrPostingRelated,
-- * accessors
queryStartDate, queryStartDate,
queryEndDate, queryEndDate,
queryDateSpan, queryDateSpan,
@ -46,7 +51,7 @@ module Hledger.Query (
queryDepth, queryDepth,
inAccount, inAccount,
inAccountQuery, inAccountQuery,
-- * matching -- * matching things with queries
matchesTransaction, matchesTransaction,
matchesTransactionExtra, matchesTransactionExtra,
matchesDescription, matchesDescription,
@ -402,6 +407,8 @@ parseBool s = s `elem` truestrings
truestrings :: [T.Text] truestrings :: [T.Text]
truestrings = ["1"] truestrings = ["1"]
-- * modifying
simplifyQuery :: Query -> Query simplifyQuery :: Query -> Query
simplifyQuery q = simplifyQuery q =
let q' = simplify q let q' = simplify q
@ -428,31 +435,40 @@ same [] = True
same (a:as) = all (a==) as same (a:as) = all (a==) as
-- | Remove query terms (or whole sub-expressions) from this query -- | Remove query terms (or whole sub-expressions) from this query
-- which do not match the given predicate. -- which do not match the given predicate. XXX Semantics not completely clear.
-- XXX Semantics not completely clear. -- Also calls simplifyQuery on the result.
filterQuery :: (Query -> Bool) -> Query -> Query filterQuery :: (Query -> Bool) -> Query -> Query
filterQuery p = simplifyQuery . filterQuery' p filterQuery p = simplifyQuery . filterQuery' p
where
filterQuery' :: (Query -> Bool) -> Query -> Query -- | Like filterQuery, but returns the filtered query as is, without simplifying.
filterQuery' p (And qs) = And $ map (filterQuery p) qs filterQuery' :: (Query -> Bool) -> Query -> Query
filterQuery' p (Or qs) = Or $ map (filterQuery p) qs filterQuery' p (And qs) = And $ map (filterQuery p) qs
filterQuery' p q = if p q then q else Any filterQuery' p (Or qs) = Or $ map (filterQuery p) qs
filterQuery' p q = if p q then q else Any
-- | Remove query terms (or whole sub-expressions) from this query -- | Remove query terms (or whole sub-expressions) from this query
-- which match neither the given predicate nor that predicate negated -- which match neither the given predicate nor that predicate negated
-- (eg, if predicate is queryIsAcct, this will keep both "acct:" and "not:acct:" terms). -- (eg, if predicate is queryIsAcct, this will keep both "acct:" and "not:acct:" terms).
-- Also calls simplifyQuery on the result.
-- (Since 1.24.1, might be merged into filterQuery in future.) -- (Since 1.24.1, might be merged into filterQuery in future.)
-- XXX Semantics not completely clear. -- XXX Semantics not completely clear.
filterQueryOrNotQuery :: (Query -> Bool) -> Query -> Query filterQueryOrNotQuery :: (Query -> Bool) -> Query -> Query
filterQueryOrNotQuery p = simplifyQuery . filterQuery' p filterQueryOrNotQuery p = simplifyQuery . filterQueryOrNotQuery' p
where where
filterQuery' :: (Query -> Bool) -> Query -> Query filterQueryOrNotQuery' :: (Query -> Bool) -> Query -> Query
filterQuery' p (And qs) = And $ map (filterQueryOrNotQuery p) qs filterQueryOrNotQuery' p (And qs) = And $ map (filterQueryOrNotQuery p) qs
filterQuery' p (Or qs) = Or $ map (filterQueryOrNotQuery p) qs filterQueryOrNotQuery' p (Or qs) = Or $ map (filterQueryOrNotQuery p) qs
filterQuery' p (Not q) | p q = Not $ filterQueryOrNotQuery p q filterQueryOrNotQuery' p (Not q) | p q = Not $ filterQueryOrNotQuery p q
filterQuery' p q = if p q then q else Any filterQueryOrNotQuery' p q = if p q then q else Any
-- * accessors -- * predicates
-- | Does this simple query predicate match any part of this possibly compound query ?
matchesQuery :: (Query -> Bool) -> Query -> Bool
matchesQuery p (And qs) = any (matchesQuery p) qs
matchesQuery p (Or qs) = any (matchesQuery p) qs
matchesQuery p (Not q) = p q
matchesQuery p q = p q
-- | Does this query match everything ? -- | Does this query match everything ?
queryIsNull :: Query -> Bool queryIsNull :: Query -> Bool
@ -525,6 +541,36 @@ queryIsStartDateOnly False (Date (DateSpan (Just _) _)) = True
queryIsStartDateOnly True (Date2 (DateSpan (Just _) _)) = True queryIsStartDateOnly True (Date2 (DateSpan (Just _) _)) = True
queryIsStartDateOnly _ _ = False queryIsStartDateOnly _ _ = False
-- | Does this query involve a property which only accounts (without their balances) have,
-- making it inappropriate for matching other things ?
queryIsAccountRelated :: Query -> Bool
queryIsAccountRelated = matchesQuery (
queryIsAcct
||| queryIsDepth
||| queryIsType
)
-- | Does this query involve a property which only transactions or postings have,
-- making it inappropriate for matching other things ?
queryIsTransactionOrPostingRelated :: Query -> Bool
queryIsTransactionOrPostingRelated = matchesQuery (
queryIsAmt
-- ||| queryIsCode
-- ||| queryIsCur
||| queryIsDesc
||| queryIsDate
||| queryIsDate2
-- ||| queryIsNote
-- ||| queryIsPayee
||| queryIsReal
||| queryIsStatus
)
(|||) :: (a->Bool) -> (a->Bool) -> (a->Bool)
p ||| q = \v -> p v || q v
-- * accessors
-- | What start date (or secondary date) does this query specify, if any ? -- | What start date (or secondary date) does this query specify, if any ?
-- For OR expressions, use the earliest of the dates. NOT is ignored. -- For OR expressions, use the earliest of the dates. NOT is ignored.
queryStartDate :: Bool -> Query -> Maybe Day queryStartDate :: Bool -> Query -> Maybe Day
@ -616,7 +662,7 @@ inAccountQuery (QueryOptInAcct a : _) = Just . Acct $ accountNameToAccountRe
-- negateQuery :: Query -> Query -- negateQuery :: Query -> Query
-- negateQuery = Not -- negateQuery = Not
-- matching -- matching things with queries
matchesCommodity :: Query -> CommoditySymbol -> Bool matchesCommodity :: Query -> CommoditySymbol -> Bool
matchesCommodity (Sym r) = regexMatchText r matchesCommodity (Sym r) = regexMatchText r