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

View File

@ -3,10 +3,16 @@ Show account names.
_FLAGS _FLAGS
This command lists account names, either declared with account directives This command lists account names.
(--declared), posted to (--used), or both (the default). 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. 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 It shows a flat list by default. With `--tree`, it uses indentation to
show the account hierarchy. 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 With `--directives`, it adds the `account` keyword, showing
valid account directives which can be pasted into a journal file. 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: Examples:
@ -36,3 +48,7 @@ income:gifts
income:salary income:salary
liabilities:debts 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." [] -> error' $ help <> ".\nPlease provide an account name or a (case-insensitive, infix, regexp) pattern."
(a:as) -> return (a, map T.pack as) (a:as) -> return (a, map T.pack as)
let let
-- keep synced with accounts --find
acct = fromMaybe (error' $ help <> ",\nbut " ++ show apat++" did not match any account.") -- PARTIAL: acct = fromMaybe (error' $ help <> ",\nbut " ++ show apat++" did not match any account.") -- PARTIAL:
. firstMatch $ journalAccountNamesDeclaredOrImplied j . firstMatch $ journalAccountNamesDeclaredOrImplied j
firstMatch = case toRegexCI $ T.pack apat of firstMatch = case toRegexCI $ T.pack apat of