Rewrote the balance report again, to fix --depth

This commit is contained in:
John Wiegley 2009-03-08 04:15:48 -04:00
parent dd6c0ae80d
commit 77faaa926f
7 changed files with 199 additions and 59 deletions

View file

@ -136,7 +136,7 @@ string account_t::partial_name(bool flat) const
acct && acct->parent; acct && acct->parent;
acct = acct->parent) { acct = acct->parent) {
if (! flat) { if (! flat) {
std::size_t count = acct->children_with_flags(ACCOUNT_EXT_MATCHING); std::size_t count = acct->children_with_flags(ACCOUNT_EXT_TO_DISPLAY);
assert(count > 0); assert(count > 0);
if (count > 1) if (count > 1)
break; break;
@ -198,7 +198,7 @@ namespace {
for (const account_t * acct = account.parent; for (const account_t * acct = account.parent;
acct && acct->parent; acct && acct->parent;
acct = acct->parent) { acct = acct->parent) {
std::size_t count = acct->children_with_flags(ACCOUNT_EXT_MATCHING); std::size_t count = acct->children_with_flags(ACCOUNT_EXT_TO_DISPLAY);
assert(count > 0); assert(count > 0);
if (count > 1) if (count > 1)
depth++; depth++;

View file

@ -134,7 +134,8 @@ class account_t : public scope_t
#define ACCOUNT_EXT_AUTO_VIRTUALIZE 0x08 #define ACCOUNT_EXT_AUTO_VIRTUALIZE 0x08
#define ACCOUNT_EXT_VISITED 0x10 #define ACCOUNT_EXT_VISITED 0x10
#define ACCOUNT_EXT_MATCHING 0x20 #define ACCOUNT_EXT_MATCHING 0x20
#define ACCOUNT_EXT_DISPLAYED 0x40 #define ACCOUNT_EXT_TO_DISPLAY 0x40
#define ACCOUNT_EXT_DISPLAYED 0x80
struct details_t struct details_t
{ {

View file

@ -117,12 +117,6 @@ format_accounts::format_accounts(report_t& _report,
{ {
TRACE_CTOR(format_accounts, "report&, const string&"); TRACE_CTOR(format_accounts, "report&, const string&");
if (report.HANDLED(display_)) {
DEBUG("account.display",
"Account display predicate: " << report.HANDLER(display_).str());
disp_pred.predicate.parse(report.HANDLER(display_).str());
}
const char * f = format.c_str(); const char * f = format.c_str();
if (const char * p = std::strstr(f, "%/")) { if (const char * p = std::strstr(f, "%/")) {
@ -142,48 +136,62 @@ format_accounts::format_accounts(report_t& _report,
void format_accounts::post_account(account_t& account) void format_accounts::post_account(account_t& account)
{ {
bind_scope_t bound_scope(report, account); if (account.xdata().has_flags(ACCOUNT_EXT_TO_DISPLAY)) {
bool format_account = false;
DEBUG("account.display", "Should we display " << account.fullname());
if (account.has_flags(ACCOUNT_EXT_MATCHING) ||
(! report.HANDLED(flat) &&
account.children_with_flags(ACCOUNT_EXT_MATCHING) > 1)) {
DEBUG("account.display", " Yes, because it matched");
format_account = true;
}
else if (! report.HANDLED(flat) &&
account.children_with_flags(ACCOUNT_EXT_VISITED) &&
! account.children_with_flags(ACCOUNT_EXT_MATCHING)) {
DEBUG("account.display",
" Maybe, because it has visited, but no matching, children");
if (disp_pred(bound_scope)) {
DEBUG("account.display",
" And yes, because it matches the display predicate");
format_account = true;
} else {
DEBUG("account.display",
" And no, because it didn't match the display predicate");
}
}
else {
DEBUG("account.display",
" No, neither it nor its children were eligible for display");
}
if (format_account) {
account.xdata().add_flags(ACCOUNT_EXT_DISPLAYED); account.xdata().add_flags(ACCOUNT_EXT_DISPLAYED);
bind_scope_t bound_scope(report, account);
account_line_format.format(report.output_stream, bound_scope); account_line_format.format(report.output_stream, bound_scope);
} }
} }
std::pair<std::size_t, std::size_t>
format_accounts::mark_accounts(account_t& account, const bool flat)
{
std::size_t visited = 0;
std::size_t to_display = 0;
foreach (accounts_map::value_type& pair, account.accounts) {
std::pair<std::size_t, std::size_t> i = mark_accounts(*pair.second, flat);
visited += i.first;
to_display += i.second;
}
#if defined(DEBUG_ON)
DEBUG("account.display", "Considering account: " << account.fullname());
if (account.has_flags(ACCOUNT_EXT_VISITED))
DEBUG("account.display", " it was visited itself");
DEBUG("account.display", " it has " << visited << " visited children");
DEBUG("account.display",
" it has " << to_display << " children to display");
#endif
if (account.has_flags(ACCOUNT_EXT_VISITED) || (! flat && visited > 0)) {
bind_scope_t bound_scope(report, account);
if (disp_pred(bound_scope) && (flat || to_display != 1)) {
account.xdata().add_flags(ACCOUNT_EXT_TO_DISPLAY);
DEBUG("account.display", "Marking account as TO_DISPLAY");
to_display = 1;
}
visited = 1;
}
return std::pair<std::size_t, std::size_t>(visited, to_display);
}
void format_accounts::flush() void format_accounts::flush()
{ {
std::ostream& out(report.output_stream); std::ostream& out(report.output_stream);
if (report.HANDLED(display_)) {
DEBUG("account.display",
"Account display predicate: " << report.HANDLER(display_).str());
disp_pred.predicate.parse(report.HANDLER(display_).str());
}
std::size_t top_displayed = 0; std::size_t top_displayed = 0;
mark_accounts(*report.session.master, report.HANDLED(flat));
foreach (account_t * account, posted_accounts) { foreach (account_t * account, posted_accounts) {
post_account(*account); post_account(*account);
@ -194,8 +202,9 @@ void format_accounts::flush()
if (! report.HANDLED(flat)) { if (! report.HANDLED(flat)) {
foreach (accounts_map::value_type pair, report.session.master->accounts) { foreach (accounts_map::value_type pair, report.session.master->accounts) {
if (pair.second->has_flags(ACCOUNT_EXT_DISPLAYED) || if (pair.second->has_flags(ACCOUNT_EXT_DISPLAYED) ||
pair.second->children_with_flags(ACCOUNT_EXT_DISPLAYED)) pair.second->children_with_flags(ACCOUNT_EXT_DISPLAYED)) {
top_displayed++; top_displayed++;
}
} }
} }
@ -211,22 +220,6 @@ void format_accounts::flush()
void format_accounts::operator()(account_t& account) void format_accounts::operator()(account_t& account)
{ {
DEBUG("account.display",
"Proposing to format account: " << account.fullname());
if (account.has_flags(ACCOUNT_EXT_VISITED)) {
DEBUG("account.display", " Account or its children was visited");
bind_scope_t bound_scope(report, account);
if (disp_pred(bound_scope)) {
DEBUG("account.display",
" And the account matched the display predicate");
account.xdata().add_flags(ACCOUNT_EXT_MATCHING);
} else {
DEBUG("account.display",
" But it did not match the display predicate");
}
}
posted_accounts.push_back(&account); posted_accounts.push_back(&account);
} }

View file

@ -49,12 +49,12 @@
#include "chain.h" #include "chain.h"
#include "predicate.h" #include "predicate.h"
#include "format.h" #include "format.h"
#include "account.h"
namespace ledger { namespace ledger {
class xact_t; class xact_t;
class post_t; class post_t;
class account_t;
class report_t; class report_t;
/** /**
@ -106,6 +106,9 @@ public:
TRACE_DTOR(format_accounts); TRACE_DTOR(format_accounts);
} }
std::pair<std::size_t, std::size_t>
mark_accounts(account_t& account, const bool flat);
virtual void post_account(account_t& account); virtual void post_account(account_t& account);
virtual void flush(); virtual void flush();

View file

@ -304,7 +304,7 @@ public:
OPTION_(report_t, depth_, DO_(scope) { OPTION_(report_t, depth_, DO_(scope) {
interactive_t args(scope, "l"); interactive_t args(scope, "l");
parent->HANDLER(limit_).on(string("depth<=") + args.get<string>(0)); parent->HANDLER(display_).on(string("depth<=") + args.get<string>(0));
}); });
OPTION_(report_t, deviation, DO() { // -D OPTION_(report_t, deviation, DO() { // -D

View file

@ -0,0 +1,83 @@
bal --depth 1
<<<
2008/01/01 January
Expenses:Books $10.00
Assets:Cash
2008/01/01 January
Expenses:One:Books $10.00
Expenses:One:Two:Books $10.00
Expenses:One:Two:Three:Books $10.00
Assets:Cash
2008/01/01 January
Assets:Cash 0
Income:Books
2008/01/01 January
Assets:Cash
Income:One:Books $-10.00
Income:One:Two:Books $-10.00
Income:One:Two:Three:Books $-10.00
>>>1
$-10.00 Assets
$40.00 Expenses
$-30.00 Income
>>>2
=== 0
bal --depth 2
>>>1
$-10.00 Assets:Cash
$40.00 Expenses
$10.00 Books
$30.00 One
$-30.00 Income:One
>>>2
=== 0
bal --depth 3
>>>1
$-10.00 Assets:Cash
$40.00 Expenses
$10.00 Books
$30.00 One
$10.00 Books
$20.00 Two
$-30.00 Income:One
$-10.00 Books
$-20.00 Two
>>>2
=== 0
bal --depth 4
>>>1
$-10.00 Assets:Cash
$40.00 Expenses
$10.00 Books
$30.00 One
$10.00 Books
$20.00 Two
$10.00 Books
$10.00 Three
$-30.00 Income:One
$-10.00 Books
$-20.00 Two
$-10.00 Books
$-10.00 Three
>>>2
=== 0
bal --depth 5
>>>1
$-10.00 Assets:Cash
$40.00 Expenses
$10.00 Books
$30.00 One
$10.00 Books
$20.00 Two
$10.00 Books
$10.00 Three:Books
$-30.00 Income:One
$-10.00 Books
$-20.00 Two
$-10.00 Books
$-10.00 Three:Books
>>>2
=== 0

View file

@ -0,0 +1,60 @@
bal --depth 1 --flat
<<<
2008/01/01 January
Expenses:Books $10.00
Assets:Cash
2008/01/01 January
Expenses:One:Books $10.00
Expenses:One:Two:Books $10.00
Expenses:One:Two:Three:Books $10.00
Assets:Cash
2008/01/01 January
Assets:Cash 0
Income:Books
2008/01/01 January
Assets:Cash
Income:One:Books $-10.00
Income:One:Two:Books $-10.00
Income:One:Two:Three:Books $-10.00
>>>1
>>>2
=== 0
bal --depth 2 --flat
>>>1
$-10.00 Assets:Cash
$10.00 Expenses:Books
>>>2
=== 0
bal --depth 3 --flat
>>>1
$-10.00 Assets:Cash
$10.00 Expenses:Books
$10.00 Expenses:One:Books
$-10.00 Income:One:Books
>>>2
=== 0
bal --depth 4 --flat
>>>1
$-10.00 Assets:Cash
$10.00 Expenses:Books
$10.00 Expenses:One:Books
$10.00 Expenses:One:Two:Books
$-10.00 Income:One:Books
$-10.00 Income:One:Two:Books
>>>2
=== 0
bal --depth 5 --flat
>>>1
$-10.00 Assets:Cash
$10.00 Expenses:Books
$10.00 Expenses:One:Books
$10.00 Expenses:One:Two:Books
$10.00 Expenses:One:Two:Three:Books
$-10.00 Income:One:Books
$-10.00 Income:One:Two:Books
$-10.00 Income:One:Two:Three:Books
>>>2
=== 0