mirror of
https://github.com/simonmichael/hledger.git
synced 2024-12-29 13:22:27 +03:00
fix: tags: also match accounts declared but not used (#1857)
By default, all account declarations and all transactions are searched; but when there's a query involving transaction fields, account declarations unrelated to the matched transactions are not searched. added: queryIsCode queryIsTransactionRelated
This commit is contained in:
parent
4f26309328
commit
5af224d534
@ -29,20 +29,21 @@ module Hledger.Query (
|
|||||||
matchesQuery,
|
matchesQuery,
|
||||||
-- * predicates
|
-- * predicates
|
||||||
queryIsNull,
|
queryIsNull,
|
||||||
queryIsAcct,
|
|
||||||
queryIsAmt,
|
|
||||||
queryIsDepth,
|
|
||||||
queryIsDate,
|
queryIsDate,
|
||||||
queryIsDate2,
|
queryIsDate2,
|
||||||
queryIsDateOrDate2,
|
queryIsDateOrDate2,
|
||||||
queryIsStartDateOnly,
|
|
||||||
queryIsSym,
|
|
||||||
queryIsReal,
|
|
||||||
queryIsStatus,
|
queryIsStatus,
|
||||||
queryIsType,
|
queryIsCode,
|
||||||
|
queryIsDesc,
|
||||||
queryIsTag,
|
queryIsTag,
|
||||||
queryIsAccountRelated,
|
queryIsAcct,
|
||||||
queryIsTransactionOrPostingRelated,
|
queryIsType,
|
||||||
|
queryIsDepth,
|
||||||
|
queryIsReal,
|
||||||
|
queryIsAmt,
|
||||||
|
queryIsSym,
|
||||||
|
queryIsStartDateOnly,
|
||||||
|
queryIsTransactionRelated,
|
||||||
-- * accessors
|
-- * accessors
|
||||||
queryStartDate,
|
queryStartDate,
|
||||||
queryEndDate,
|
queryEndDate,
|
||||||
@ -478,13 +479,9 @@ queryIsNull (And []) = True
|
|||||||
queryIsNull (Not (Or [])) = True
|
queryIsNull (Not (Or [])) = True
|
||||||
queryIsNull _ = False
|
queryIsNull _ = False
|
||||||
|
|
||||||
-- | Is this a simple query of this type ("depth:D") ?
|
-- | Is this a simple query of this type (date:) ?
|
||||||
-- Note, does not match a compound query like "not:depth:D" or "depth:D acct:A".
|
-- Does not match a compound query involving and/or/not.
|
||||||
-- Likewise for the following functions.
|
-- Likewise for the following functions.
|
||||||
queryIsDepth :: Query -> Bool
|
|
||||||
queryIsDepth (Depth _) = True
|
|
||||||
queryIsDepth _ = False
|
|
||||||
|
|
||||||
queryIsDate :: Query -> Bool
|
queryIsDate :: Query -> Bool
|
||||||
queryIsDate (Date _) = True
|
queryIsDate (Date _) = True
|
||||||
queryIsDate _ = False
|
queryIsDate _ = False
|
||||||
@ -498,14 +495,38 @@ queryIsDateOrDate2 (Date _) = True
|
|||||||
queryIsDateOrDate2 (Date2 _) = True
|
queryIsDateOrDate2 (Date2 _) = True
|
||||||
queryIsDateOrDate2 _ = False
|
queryIsDateOrDate2 _ = False
|
||||||
|
|
||||||
|
queryIsStatus :: Query -> Bool
|
||||||
|
queryIsStatus (StatusQ _) = True
|
||||||
|
queryIsStatus _ = False
|
||||||
|
|
||||||
|
queryIsCode :: Query -> Bool
|
||||||
|
queryIsCode (Code _) = True
|
||||||
|
queryIsCode _ = False
|
||||||
|
|
||||||
queryIsDesc :: Query -> Bool
|
queryIsDesc :: Query -> Bool
|
||||||
queryIsDesc (Desc _) = True
|
queryIsDesc (Desc _) = True
|
||||||
queryIsDesc _ = False
|
queryIsDesc _ = False
|
||||||
|
|
||||||
|
queryIsTag :: Query -> Bool
|
||||||
|
queryIsTag (Tag _ _) = True
|
||||||
|
queryIsTag _ = False
|
||||||
|
|
||||||
queryIsAcct :: Query -> Bool
|
queryIsAcct :: Query -> Bool
|
||||||
queryIsAcct (Acct _) = True
|
queryIsAcct (Acct _) = True
|
||||||
queryIsAcct _ = False
|
queryIsAcct _ = False
|
||||||
|
|
||||||
|
queryIsType :: Query -> Bool
|
||||||
|
queryIsType (Type _) = True
|
||||||
|
queryIsType _ = False
|
||||||
|
|
||||||
|
queryIsDepth :: Query -> Bool
|
||||||
|
queryIsDepth (Depth _) = True
|
||||||
|
queryIsDepth _ = False
|
||||||
|
|
||||||
|
queryIsReal :: Query -> Bool
|
||||||
|
queryIsReal (Real _) = True
|
||||||
|
queryIsReal _ = False
|
||||||
|
|
||||||
queryIsAmt :: Query -> Bool
|
queryIsAmt :: Query -> Bool
|
||||||
queryIsAmt (Amt _ _) = True
|
queryIsAmt (Amt _ _) = True
|
||||||
queryIsAmt _ = False
|
queryIsAmt _ = False
|
||||||
@ -514,22 +535,6 @@ queryIsSym :: Query -> Bool
|
|||||||
queryIsSym (Sym _) = True
|
queryIsSym (Sym _) = True
|
||||||
queryIsSym _ = False
|
queryIsSym _ = False
|
||||||
|
|
||||||
queryIsReal :: Query -> Bool
|
|
||||||
queryIsReal (Real _) = True
|
|
||||||
queryIsReal _ = False
|
|
||||||
|
|
||||||
queryIsStatus :: Query -> Bool
|
|
||||||
queryIsStatus (StatusQ _) = True
|
|
||||||
queryIsStatus _ = False
|
|
||||||
|
|
||||||
queryIsType :: Query -> Bool
|
|
||||||
queryIsType (Type _) = True
|
|
||||||
queryIsType _ = False
|
|
||||||
|
|
||||||
queryIsTag :: Query -> Bool
|
|
||||||
queryIsTag (Tag _ _) = True
|
|
||||||
queryIsTag _ = False
|
|
||||||
|
|
||||||
-- | Does this query specify a start date and nothing else (that would
|
-- | Does this query specify a start date and nothing else (that would
|
||||||
-- filter postings prior to the date) ?
|
-- filter postings prior to the date) ?
|
||||||
-- When the flag is true, look for a starting secondary date instead.
|
-- When the flag is true, look for a starting secondary date instead.
|
||||||
@ -542,29 +547,18 @@ 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,
|
-- | Does this query involve a property of transactions (or their postings),
|
||||||
-- making it inappropriate for matching other things ?
|
-- making it inapplicable to account declarations ?
|
||||||
queryIsAccountRelated :: Query -> Bool
|
queryIsTransactionRelated :: Query -> Bool
|
||||||
queryIsAccountRelated = matchesQuery (
|
queryIsTransactionRelated = matchesQuery (
|
||||||
queryIsAcct
|
queryIsDate
|
||||||
||| 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
|
||| queryIsDate2
|
||||||
-- ||| queryIsNote
|
|
||||||
-- ||| queryIsPayee
|
|
||||||
||| queryIsReal
|
|
||||||
||| queryIsStatus
|
||| queryIsStatus
|
||||||
|
||| queryIsCode
|
||||||
|
||| queryIsDesc
|
||||||
|
||| queryIsReal
|
||||||
|
||| queryIsAmt
|
||||||
|
||| queryIsSym
|
||||||
)
|
)
|
||||||
|
|
||||||
(|||) :: (a->Bool) -> (a->Bool) -> (a->Bool)
|
(|||) :: (a->Bool) -> (a->Bool) -> (a->Bool)
|
||||||
|
@ -29,21 +29,28 @@ tags :: CliOpts -> Journal -> IO ()
|
|||||||
tags CliOpts{rawopts_=rawopts,reportspec_=rspec} j = do
|
tags CliOpts{rawopts_=rawopts,reportspec_=rspec} j = do
|
||||||
let today = _rsDay rspec
|
let today = _rsDay rspec
|
||||||
args = listofstringopt "args" rawopts
|
args = listofstringopt "args" rawopts
|
||||||
|
-- first argument is a tag name pattern, others are a hledger query: hledger tags [TAGREGEX [QUERYARGS..]]
|
||||||
mtagpat <- mapM (either Fail.fail pure . toRegexCI . T.pack) $ headMay args
|
mtagpat <- mapM (either Fail.fail pure . toRegexCI . T.pack) $ headMay args
|
||||||
let
|
let
|
||||||
querystring = map T.pack $ drop 1 args
|
querystr = map T.pack $ drop 1 args
|
||||||
values = boolopt "values" rawopts
|
values = boolopt "values" rawopts
|
||||||
parsed = boolopt "parsed" rawopts
|
parsed = boolopt "parsed" rawopts
|
||||||
empty = empty_ $ _rsReportOpts rspec
|
empty = empty_ $ _rsReportOpts rspec
|
||||||
|
query <- either usageError (return . fst) $ parseQueryList today querystr
|
||||||
argsquery <- either usageError (return . fst) $ parseQueryList today querystring
|
|
||||||
let
|
let
|
||||||
q = simplifyQuery $ And [queryFromFlags $ _rsReportOpts rspec, argsquery]
|
q = simplifyQuery $ And [queryFromFlags $ _rsReportOpts rspec, query]
|
||||||
txns = filter (q `matchesTransaction`) $ jtxns $ journalApplyValuationFromOpts rspec j
|
matchedtxns = filter (q `matchesTransaction`) $ jtxns $ journalApplyValuationFromOpts rspec j
|
||||||
|
-- also list tags from matched account declarations, but not if there is
|
||||||
|
-- a query for something transaction-related, like date: or amt:.
|
||||||
|
matchedaccts = dbg4 "accts" $
|
||||||
|
if dbg4 "queryIsTransactionRelated" $ queryIsTransactionRelated $ dbg4 "q" q
|
||||||
|
then []
|
||||||
|
else filter (matchesAccountExtra (journalAccountType j) (journalInheritedAccountTags j) q) $
|
||||||
|
map fst $ jdeclaredaccounts j
|
||||||
tagsorvalues =
|
tagsorvalues =
|
||||||
(if parsed then id else nubSort)
|
(if parsed then id else nubSort)
|
||||||
[ r
|
[ r
|
||||||
| (t,v) <- concatMap transactionAllTags txns
|
| (t,v) <- concatMap (journalAccountTags j) matchedaccts ++ concatMap transactionAllTags matchedtxns
|
||||||
, maybe True (`regexMatchText` t) mtagpat
|
, maybe True (`regexMatchText` t) mtagpat
|
||||||
, let r = if values then v else t
|
, let r = if values then v else t
|
||||||
, not (values && T.null v && not empty)
|
, not (values && T.null v && not empty)
|
||||||
|
@ -1,14 +1,23 @@
|
|||||||
tags\
|
tags\
|
||||||
List the unique tag names used in the journal. With a TAGREGEX argument,
|
List the unique tag names used in the journal, whether on transactions, postings,
|
||||||
only tag names matching the regular expression (case insensitive) are shown.
|
or account declarations.
|
||||||
With QUERY arguments, only transactions matching the query are considered.
|
|
||||||
|
|
||||||
With the --values flag, the tags' unique values are listed instead.
|
With a TAGREGEX argument, only tag names matching this regular expression
|
||||||
|
(case insensitive, infix matched) are shown.
|
||||||
|
|
||||||
With --parsed flag, all tags or values are shown in the order they
|
With QUERY arguments, only transactions and accounts matching this query are considered.
|
||||||
are parsed from the input data, including duplicates.
|
If the query involves transaction fields (date:, desc:, amt:, ...),
|
||||||
|
the search is restricted to the matched transactions and their accounts.
|
||||||
|
|
||||||
With -E/--empty, any blank/empty values will also be shown, otherwise
|
With the --values flag, the tags' unique non-empty values are listed instead.
|
||||||
they are omitted.
|
With -E/--empty, blank/empty values are also shown.
|
||||||
|
|
||||||
|
With --parsed, tags or values are shown in the order they were parsed, with duplicates included.
|
||||||
|
(Except, tags from account declarations are always shown first.)
|
||||||
|
|
||||||
_FLAGS
|
_FLAGS
|
||||||
|
|
||||||
|
Tip: remember,
|
||||||
|
accounts also acquire tags from their parents,
|
||||||
|
postings also acquire tags from their account and transaction,
|
||||||
|
transactions also acquire tags from their postings.
|
||||||
|
@ -1,32 +1,56 @@
|
|||||||
# tags command
|
# tags command
|
||||||
|
|
||||||
account a ; t1:v1
|
account a ; t1:v1, an account tag
|
||||||
|
account b:bb ; t2:v2, an unused account, depth 2
|
||||||
|
|
||||||
2000/1/1 ; t2:v2
|
2000/1/1 ; t3:v3, a transaction tag
|
||||||
(b) 1 ; t3:v3
|
(a:aa) 1 ; t4:v4, a posting tag
|
||||||
|
|
||||||
2000/1/2 ; t4:v4
|
2000/1/2 ; t5:v4, a reused value
|
||||||
(b) 1 ; t5:v5
|
(c) 1 ; t6:v6, an undeclared account
|
||||||
|
|
||||||
# 1. list all tags
|
# 1. show all tags
|
||||||
$ hledger -f - tags
|
$ hledger -f- tags
|
||||||
|
t1
|
||||||
t2
|
t2
|
||||||
t3
|
t3
|
||||||
t4
|
t4
|
||||||
t5
|
t5
|
||||||
|
t6
|
||||||
|
|
||||||
# 2. list tag names matching a regex
|
# 2. show all tag values
|
||||||
$ hledger -f - tags '[24]'
|
$ hledger -f- tags --values
|
||||||
t2
|
v1
|
||||||
t4
|
|
||||||
|
|
||||||
# 3. list tag values
|
|
||||||
$ hledger -f - tags --values
|
|
||||||
v2
|
v2
|
||||||
v3
|
v3
|
||||||
v4
|
v4
|
||||||
v5
|
v6
|
||||||
|
|
||||||
# 4. list values of tags matching a regex from transactions matching a query
|
# 3. show tags matching a regex
|
||||||
$ hledger -f - tags t3 date:2000/1/1 --values
|
$ hledger -f- tags '[1-4]'
|
||||||
v3
|
t1
|
||||||
|
t2
|
||||||
|
t3
|
||||||
|
t4
|
||||||
|
|
||||||
|
# 4. show tags matching (a regex and) a hledger query.
|
||||||
|
# If the query is applicable to both transactions and account declarations,
|
||||||
|
# both are searched for tags.
|
||||||
|
$ hledger -f- tags . b c
|
||||||
|
t2
|
||||||
|
t5
|
||||||
|
t6
|
||||||
|
|
||||||
|
# 5. If the query involves transaction attributes,
|
||||||
|
# only accounts used by the matched transactions will contribute tags.
|
||||||
|
$ hledger -f- tags . date:2000/1/1
|
||||||
|
t1
|
||||||
|
t3
|
||||||
|
t4
|
||||||
|
|
||||||
|
# 6. show account tags even when there are no transactions (#1857)
|
||||||
|
<
|
||||||
|
account a ; t1:
|
||||||
|
|
||||||
|
$ hledger -f- tags
|
||||||
|
t1
|
||||||
|
Loading…
Reference in New Issue
Block a user