feat: accounts: add --undeclared and --find flags

This commit is contained in:
Simon Michael 2022-10-05 08:14:16 -10:00
parent 15b2e7d586
commit 3e42851958
3 changed files with 53 additions and 14 deletions

View File

@ -28,6 +28,8 @@ import System.Console.CmdArgs.Explicit as C
import Hledger
import Hledger.Cli.CliOptions
import Control.Monad (forM_)
import Data.Maybe (fromMaybe)
import Safe (headDef)
-- | Command line options for this command.
@ -35,11 +37,13 @@ accountsmode = hledgerCommandMode
$(embedFileRelative "Hledger/Cli/Commands/Accounts.txt")
(flattreeflags False ++
[flagReq ["drop"] (\s opts -> Right $ setopt "drop" s opts) "N" "flat mode: omit N leading account name parts"
,flagNone ["used"] (setboolopt "used") "show only accounts used by transactions"
,flagNone ["declared"] (setboolopt "declared") "show only accounts declared by account directive"
,flagNone ["used"] (setboolopt "used") "show only accounts referenced by transactions"
,flagNone ["types"] (setboolopt "types") "show accounts' types, when known"
,flagNone ["positions"] (setboolopt "positions") "show where accounts were declared"
,flagNone ["directives"] (setboolopt "directives") "show valid account directives usable in journals"
,flagNone ["undeclared"] (setboolopt "undeclared") "show accounts used but not declared"
,flagNone ["find"] (setboolopt "find") "find the first account matched by the first command argument (a case-insensitive infix regexp or account name)"
,flagNone ["types"] (setboolopt "types") "also show account types when known"
,flagNone ["positions"] (setboolopt "positions") "also show where accounts were declared"
,flagNone ["directives"] (setboolopt "directives") "show as account directives, for use in journals"
])
[generalflagsgroup1]
hiddenflags
@ -51,8 +55,10 @@ accounts CliOpts{rawopts_=rawopts, reportspec_=ReportSpec{_rsQuery=query,_rsRepo
-- 1. identify the accounts we'll show
let tree = tree_ ropts
decl = boolopt "declared" rawopts
used = boolopt "used" rawopts
decl = boolopt "declared" rawopts
undecl = boolopt "undeclared" rawopts
find_ = boolopt "find" rawopts
types = boolopt "types" rawopts
positions = boolopt "positions" rawopts
directives = boolopt "directives" rawopts
@ -63,13 +69,29 @@ accounts CliOpts{rawopts_=rawopts, reportspec_=ReportSpec{_rsQuery=query,_rsRepo
dep = dbg4 "depth" $ queryDepth $ filterQuery queryIsDepth query
matcheddeclaredaccts =
dbg4 "matcheddeclaredaccts" $
nub $
filter (matchesAccountExtra (journalAccountType j) (journalInheritedAccountTags j) nodepthq)
$ map fst $ jdeclaredaccounts j
matchedusedaccts = dbg5 "matchedusedaccts" $ map paccount $ journalPostings $ filterJournalPostings nodepthq j
accts = dbg5 "accts to show" $
if | decl && not used -> matcheddeclaredaccts
| not decl && used -> matchedusedaccts
| otherwise -> matcheddeclaredaccts ++ matchedusedaccts
matchedusedaccts = dbg5 "matchedusedaccts" $ nub $ map paccount $ journalPostings $ filterJournalPostings nodepthq j
matchedundeclaredaccts = dbg5 "matchedundeclaredaccts" $ nub $ matchedusedaccts \\ matcheddeclaredaccts
-- keep synced with aregister
matchedacct = dbg5 "matchedacct" $
fromMaybe (error' $ show apat ++ " did not match any account.") -- PARTIAL:
. firstMatch $ journalAccountNamesDeclaredOrImplied j
where
firstMatch = case toRegexCI $ T.pack apat of
Right re -> find (regexMatchText re)
Left _ -> const Nothing
apat = headDef
(error' "With --find, please provide an account name or\naccount pattern (case-insensitive, infix, regexp) as first command argument.")
$ listofstringopt "args" rawopts
accts = dbg5 "accts to show" $ if
| find_ -> [matchedacct]
| undecl -> matchedundeclaredaccts
| decl && not used -> matcheddeclaredaccts
| not decl && used -> matchedusedaccts
| otherwise -> matcheddeclaredaccts ++ matchedusedaccts
-- 2. sort them by declaration order (then undeclared accounts alphabetically)
-- within each group of siblings

View File

@ -3,10 +3,16 @@ Show account names.
_FLAGS
This command lists account names, either declared with account directives
(--declared), posted to (--used), or both (the default).
With query arguments, only matched account names and account names
referenced by matched postings are shown.
This command lists account names.
By default it shows all known accounts, either used in transactions or declared with account directives.
With query arguments, only matched account names and account names referenced by matched postings are shown.
Or it can show just
the used accounts (`--used`),
the declared accounts (`--declared`),
the accounts used but not declared (`--undeclared`),
or the first account matched by an account name pattern, if any (`--find`).
It shows a flat list by default. With `--tree`, it uses indentation to
show the account hierarchy.
@ -22,6 +28,12 @@ these may be useful when troubleshooting account display order.
With `--directives`, it adds the `account` keyword, showing
valid account directives which can be pasted into a journal file.
This is useful together with `--undeclared` to update your account declarations
when `check accounts` reports undeclared accounts.
The `--find` flag can be used to look up a single account name, in the same way
that the `aregister` command does. It returns the alphanumerically-first matched
account name, or if none can be found, it fails with a non-zero exit code.
Examples:
@ -36,3 +48,7 @@ income:gifts
income:salary
liabilities:debts
```
```shell
$ hledger accounts --undeclared --directives >> $LEDGER_FILE
$ hledger check accounts
```

View File

@ -75,6 +75,7 @@ aregister opts@CliOpts{rawopts_=rawopts,reportspec_=rspec} j = do
[] -> error' $ help <> ".\nPlease provide an account name or a (case-insensitive, infix, regexp) pattern."
(a:as) -> return (a, map T.pack as)
let
-- keep synced with accounts --find
acct = fromMaybe (error' $ help <> ",\nbut " ++ show apat++" did not match any account.") -- PARTIAL:
. firstMatch $ journalAccountNamesDeclaredOrImplied j
firstMatch = case toRegexCI $ T.pack apat of