fixed the "-o bal rent" report again
This commit is contained in:
parent
50f75e0a5c
commit
ef2e0beb64
3 changed files with 98 additions and 156 deletions
10
format.h
10
format.h
|
|
@ -54,13 +54,19 @@ struct format_t
|
||||||
static std::auto_ptr<node_t> value_expr;
|
static std::auto_ptr<node_t> value_expr;
|
||||||
static std::auto_ptr<node_t> total_expr;
|
static std::auto_ptr<node_t> total_expr;
|
||||||
|
|
||||||
format_t(const std::string& _format) {
|
format_t(const std::string& _format) : elements(NULL) {
|
||||||
elements = parse_elements(_format);
|
reset(_format);
|
||||||
}
|
}
|
||||||
~format_t() {
|
~format_t() {
|
||||||
if (elements) delete elements;
|
if (elements) delete elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reset(const std::string& _format) {
|
||||||
|
if (elements)
|
||||||
|
delete elements;
|
||||||
|
elements = parse_elements(_format);
|
||||||
|
}
|
||||||
|
|
||||||
static element_t * parse_elements(const std::string& fmt);
|
static element_t * parse_elements(const std::string& fmt);
|
||||||
|
|
||||||
void format_elements(std::ostream& out, const details_t& details) const;
|
void format_elements(std::ostream& out, const details_t& details) const;
|
||||||
|
|
|
||||||
87
main.cc
87
main.cc
|
|
@ -19,68 +19,6 @@ namespace ledger {
|
||||||
|
|
||||||
static const std::string bal_fmt = "%20T %2_%-n\n";
|
static const std::string bal_fmt = "%20T %2_%-n\n";
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
unsigned int show_balances(std::ostream& out,
|
|
||||||
items_deque& items,
|
|
||||||
const node_t * predicate,
|
|
||||||
const node_t * sort_order,
|
|
||||||
const format_t& format,
|
|
||||||
const bool show_expanded,
|
|
||||||
const item_t * displayed_parent)
|
|
||||||
{
|
|
||||||
unsigned int headlines = 0;
|
|
||||||
value_predicate pred_obj(predicate);
|
|
||||||
|
|
||||||
for (items_deque::const_iterator i = items.begin();
|
|
||||||
i != items.end();
|
|
||||||
i++) {
|
|
||||||
const item_t * parent = displayed_parent;
|
|
||||||
|
|
||||||
if (pred_obj(*i) &&
|
|
||||||
((*i)->subitems.size() != 1 ||
|
|
||||||
(*i)->total != (*i)->subitems[0]->total)) {
|
|
||||||
format.format_elements(out, *i, parent);
|
|
||||||
parent = *i;
|
|
||||||
|
|
||||||
if (! displayed_parent->parent)
|
|
||||||
headlines++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sort_order)
|
|
||||||
(*i)->sort(sort_order);
|
|
||||||
|
|
||||||
if (show_expanded)
|
|
||||||
headlines += show_balances(out, (*i)->subitems, predicate,
|
|
||||||
sort_order, format, true, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
return headlines;
|
|
||||||
}
|
|
||||||
|
|
||||||
void balance_report(std::ostream& out,
|
|
||||||
item_t * top,
|
|
||||||
const node_t * predicate,
|
|
||||||
const node_t * sort_order,
|
|
||||||
const format_t& format,
|
|
||||||
const bool show_expanded,
|
|
||||||
const bool show_subtotals)
|
|
||||||
{
|
|
||||||
if (sort_order)
|
|
||||||
top->sort(sort_order);
|
|
||||||
|
|
||||||
unsigned int headlines = show_balances(out, top->subitems, predicate,
|
|
||||||
sort_order, format, show_expanded,
|
|
||||||
top);
|
|
||||||
|
|
||||||
if (show_subtotals && headlines > 1 && top->total) {
|
|
||||||
std::cout << "--------------------\n";
|
|
||||||
format.format_elements(std::cout, top);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// The command-line register and print report
|
// The command-line register and print report
|
||||||
|
|
@ -797,16 +735,21 @@ int main(int argc, char * argv[])
|
||||||
|
|
||||||
// Now handle the command that was identified above.
|
// Now handle the command that was identified above.
|
||||||
|
|
||||||
|
unsigned int xact_display_flags = MATCHING_TRANSACTIONS;
|
||||||
|
|
||||||
if (command == "p" || command == "e") {
|
if (command == "p" || command == "e") {
|
||||||
show_related = true;
|
|
||||||
show_expanded = true;
|
show_expanded = true;
|
||||||
}
|
}
|
||||||
else if (command == "E") {
|
else if (command == "E") {
|
||||||
show_expanded = true;
|
show_expanded = true;
|
||||||
}
|
}
|
||||||
else if (show_related && command == "r") {
|
else if (show_related && command == "r") {
|
||||||
|
xact_display_flags = OTHER_TRANSACTIONS;
|
||||||
show_inverted = true;
|
show_inverted = true;
|
||||||
}
|
}
|
||||||
|
else if (show_related) {
|
||||||
|
xact_display_flags |= OTHER_TRANSACTIONS;
|
||||||
|
}
|
||||||
|
|
||||||
const char * f;
|
const char * f;
|
||||||
if (! format_string.empty())
|
if (! format_string.empty())
|
||||||
|
|
@ -821,14 +764,13 @@ int main(int argc, char * argv[])
|
||||||
if (command == "b") {
|
if (command == "b") {
|
||||||
format_t format(f);
|
format_t format(f);
|
||||||
walk_accounts(journal->master, format_account(std::cout, format),
|
walk_accounts(journal->master, format_account(std::cout, format),
|
||||||
predicate.get(), show_related, show_inverted,
|
predicate.get(), xact_display_flags, show_subtotals,
|
||||||
show_subtotals, display_predicate.get(), sort_order.get());
|
display_predicate.get(), sort_order.get());
|
||||||
|
|
||||||
if (! display_predicate.get() ||
|
if (! display_predicate.get() ||
|
||||||
item_predicate(display_predicate.get())(journal->master)) {
|
item_predicate<account_t>(display_predicate.get())(journal->master)) {
|
||||||
std::string end_format = "--------------------\n";
|
std::string end_format = "--------------------\n";
|
||||||
end_format += f;
|
format.reset(end_format + f);
|
||||||
format.elements = format_t::parse_elements(end_format);
|
|
||||||
format_account(std::cout, format)(journal->master, true);
|
format_account(std::cout, format)(journal->master, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -844,22 +786,21 @@ int main(int argc, char * argv[])
|
||||||
|
|
||||||
format_t format(first_line_format);
|
format_t format(first_line_format);
|
||||||
format_t nformat(next_lines_format);
|
format_t nformat(next_lines_format);
|
||||||
format_transaction formatter(std::cout, format, nformat);
|
format_transaction formatter(std::cout, format, nformat, show_inverted);
|
||||||
|
|
||||||
if (! sort_order.get()) {
|
if (! sort_order.get()) {
|
||||||
walk_entries(journal->entries.begin(), journal->entries.end(),
|
walk_entries(journal->entries.begin(), journal->entries.end(),
|
||||||
formatter, predicate.get(), show_related, show_inverted,
|
formatter, predicate.get(), xact_display_flags,
|
||||||
display_predicate.get());
|
display_predicate.get());
|
||||||
} else {
|
} else {
|
||||||
transactions_deque transactions_pool;
|
transactions_deque transactions_pool;
|
||||||
walk_entries(journal->entries.begin(), journal->entries.end(),
|
walk_entries(journal->entries.begin(), journal->entries.end(),
|
||||||
collect_transactions(transactions_pool), predicate.get(),
|
collect_transactions(transactions_pool), predicate.get(),
|
||||||
show_related, show_inverted, display_predicate.get());
|
xact_display_flags, display_predicate.get());
|
||||||
std::stable_sort(transactions_pool.begin(), transactions_pool.end(),
|
std::stable_sort(transactions_pool.begin(), transactions_pool.end(),
|
||||||
compare_items<transaction_t>(sort_order.get()));
|
compare_items<transaction_t>(sort_order.get()));
|
||||||
walk_transactions(transactions_pool.begin(), transactions_pool.end(),
|
walk_transactions(transactions_pool.begin(), transactions_pool.end(),
|
||||||
formatter, NULL, show_related, show_inverted,
|
formatter);
|
||||||
display_predicate.get());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
157
walk.h
157
walk.h
|
|
@ -11,37 +11,18 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
class item_predicate
|
class item_predicate
|
||||||
{
|
{
|
||||||
const node_t * predicate;
|
const node_t * predicate;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
item_predicate(const node_t * _predicate) : predicate(_predicate) {}
|
item_predicate(const node_t * _predicate) : predicate(_predicate) {}
|
||||||
|
|
||||||
bool operator()(const entry_t * entry) const {
|
bool operator()(const T * item) const {
|
||||||
if (predicate) {
|
if (predicate) {
|
||||||
balance_t result;
|
balance_t result;
|
||||||
predicate->compute(result, details_t(entry));
|
predicate->compute(result, details_t(item));
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(const transaction_t * xact) const {
|
|
||||||
if (predicate) {
|
|
||||||
balance_t result;
|
|
||||||
predicate->compute(result, details_t(xact));
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(const account_t * account) const {
|
|
||||||
if (predicate) {
|
|
||||||
balance_t result;
|
|
||||||
predicate->compute(result, details_t(account));
|
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -66,19 +47,21 @@ class format_transaction
|
||||||
std::ostream& output_stream;
|
std::ostream& output_stream;
|
||||||
const format_t& first_line_format;
|
const format_t& first_line_format;
|
||||||
const format_t& next_lines_format;
|
const format_t& next_lines_format;
|
||||||
|
const bool inverted;
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
entry_t * last_entry;
|
entry_t * last_entry;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
format_transaction(std::ostream& _output_stream,
|
format_transaction(std::ostream& _output_stream,
|
||||||
const format_t& _first_line_format,
|
const format_t& _first_line_format,
|
||||||
const format_t& _next_lines_format)
|
const format_t& _next_lines_format,
|
||||||
|
const bool _inverted)
|
||||||
: output_stream(_output_stream),
|
: output_stream(_output_stream),
|
||||||
first_line_format(_first_line_format),
|
first_line_format(_first_line_format),
|
||||||
next_lines_format(_next_lines_format),
|
next_lines_format(_next_lines_format),
|
||||||
index(0), last_entry(NULL) {}
|
inverted(_inverted), index(0), last_entry(NULL) {}
|
||||||
|
|
||||||
void operator()(transaction_t * xact, const bool inverted);
|
void operator()(transaction_t * xact);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
@ -111,7 +94,7 @@ class collect_transactions
|
||||||
collect_transactions(transactions_deque& _transactions)
|
collect_transactions(transactions_deque& _transactions)
|
||||||
: transactions(_transactions) {}
|
: transactions(_transactions) {}
|
||||||
|
|
||||||
void operator()(transaction_t * xact, const bool inverted) {
|
void operator()(transaction_t * xact) {
|
||||||
transactions.push_back(xact);
|
transactions.push_back(xact);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -126,26 +109,27 @@ inline void sort_transactions(transactions_deque& transactions,
|
||||||
class ignore_transaction
|
class ignore_transaction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void operator()(transaction_t * xact, const bool inverted) const {}
|
void operator()(transaction_t * xact) const {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MATCHING_TRANSACTIONS 0x01
|
||||||
|
#define OTHER_TRANSACTIONS 0x02
|
||||||
|
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
void handle_transaction(transaction_t * xact,
|
void handle_transaction(transaction_t * xact, Function functor,
|
||||||
Function functor,
|
item_predicate<transaction_t>& pred_functor,
|
||||||
item_predicate& pred_functor,
|
unsigned int flags)
|
||||||
const bool related,
|
|
||||||
const bool inverted)
|
|
||||||
{
|
{
|
||||||
// If inverted is true, it implies related.
|
if ((flags & MATCHING_TRANSACTIONS) &&
|
||||||
if (! inverted && ! (xact->flags & TRANSACTION_HANDLED)) {
|
! (xact->flags & TRANSACTION_HANDLED)) {
|
||||||
xact->flags |= TRANSACTION_HANDLED;
|
xact->flags |= TRANSACTION_HANDLED;
|
||||||
if (pred_functor(xact)) {
|
if (pred_functor(xact)) {
|
||||||
xact->flags |= TRANSACTION_DISPLAYED;
|
xact->flags |= TRANSACTION_DISPLAYED;
|
||||||
functor(xact, inverted);
|
functor(xact);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (related)
|
if (flags & OTHER_TRANSACTIONS)
|
||||||
for (transactions_list::iterator i = xact->entry->transactions.begin();
|
for (transactions_list::iterator i = xact->entry->transactions.begin();
|
||||||
i != xact->entry->transactions.end();
|
i != xact->entry->transactions.end();
|
||||||
i++) {
|
i++) {
|
||||||
|
|
@ -156,7 +140,7 @@ void handle_transaction(transaction_t * xact,
|
||||||
(*i)->flags |= TRANSACTION_HANDLED;
|
(*i)->flags |= TRANSACTION_HANDLED;
|
||||||
if (pred_functor(xact)) {
|
if (pred_functor(xact)) {
|
||||||
xact->flags |= TRANSACTION_DISPLAYED;
|
xact->flags |= TRANSACTION_DISPLAYED;
|
||||||
functor(*i, inverted);
|
functor(*i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -164,47 +148,36 @@ void handle_transaction(transaction_t * xact,
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
void walk_entries(entries_list::iterator begin,
|
void walk_entries(entries_list::iterator begin,
|
||||||
entries_list::iterator end,
|
entries_list::iterator end,
|
||||||
Function functor,
|
Function functor,
|
||||||
const node_t * predicate,
|
const node_t * predicate,
|
||||||
const bool related,
|
unsigned int flags,
|
||||||
const bool inverted,
|
const node_t * display_predicate = NULL)
|
||||||
const node_t * display_predicate = NULL)
|
|
||||||
{
|
{
|
||||||
item_predicate pred_functor(predicate);
|
item_predicate<transaction_t> pred_functor(predicate);
|
||||||
item_predicate disp_pred_functor(display_predicate);
|
item_predicate<transaction_t> disp_pred_functor(display_predicate);
|
||||||
|
|
||||||
for (entries_list::iterator i = begin; i != end; i++)
|
for (entries_list::iterator i = begin; i != end; i++)
|
||||||
for (transactions_list::iterator j = (*i)->transactions.begin();
|
for (transactions_list::iterator j = (*i)->transactions.begin();
|
||||||
j != (*i)->transactions.end();
|
j != (*i)->transactions.end();
|
||||||
j++)
|
j++)
|
||||||
if (pred_functor(*j))
|
if (pred_functor(*j))
|
||||||
handle_transaction(*j, functor, disp_pred_functor, related, inverted);
|
handle_transaction(*j, functor, disp_pred_functor, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
void walk_transactions(transactions_list::iterator begin,
|
void walk_transactions(transactions_list::iterator begin,
|
||||||
transactions_list::iterator end,
|
transactions_list::iterator end, Function functor)
|
||||||
Function functor,
|
|
||||||
const node_t * predicate,
|
|
||||||
const bool related,
|
|
||||||
const bool inverted,
|
|
||||||
const node_t * display_predicate = NULL)
|
|
||||||
{
|
{
|
||||||
for (transactions_list::iterator i = begin; i != end; i++)
|
for (transactions_list::iterator i = begin; i != end; i++)
|
||||||
functor(*i, inverted);
|
functor(*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
void walk_transactions(transactions_deque::iterator begin,
|
void walk_transactions(transactions_deque::iterator begin,
|
||||||
transactions_deque::iterator end,
|
transactions_deque::iterator end, Function functor)
|
||||||
Function functor,
|
|
||||||
const node_t * predicate,
|
|
||||||
const bool related,
|
|
||||||
const bool inverted,
|
|
||||||
const node_t * display_predicate = NULL)
|
|
||||||
{
|
{
|
||||||
for (transactions_deque::iterator i = begin; i != end; i++)
|
for (transactions_deque::iterator i = begin; i != end; i++)
|
||||||
functor(*i, inverted);
|
functor(*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
class format_account
|
class format_account
|
||||||
|
|
@ -236,26 +209,24 @@ inline void sort_accounts(account_t * account,
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
void walk__accounts(const account_t * account,
|
void walk__accounts(const account_t * account, Function functor,
|
||||||
Function functor,
|
item_predicate<account_t>& disp_pred_functor)
|
||||||
const node_t * display_predicate)
|
|
||||||
{
|
{
|
||||||
if (! display_predicate || item_predicate(display_predicate)(account))
|
if (disp_pred_functor(account))
|
||||||
functor(account);
|
functor(account);
|
||||||
|
|
||||||
for (accounts_map::const_iterator i = account->accounts.begin();
|
for (accounts_map::const_iterator i = account->accounts.begin();
|
||||||
i != account->accounts.end();
|
i != account->accounts.end();
|
||||||
i++)
|
i++)
|
||||||
walk__accounts((*i).second, functor, display_predicate);
|
walk__accounts((*i).second, functor, disp_pred_functor);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
void walk__accounts_sorted(const account_t * account,
|
void walk__accounts_sorted(const account_t * account, Function functor,
|
||||||
Function functor,
|
const node_t * sort_order,
|
||||||
const node_t * sort_order,
|
item_predicate<account_t>& disp_pred_functor)
|
||||||
const node_t * display_predicate)
|
|
||||||
{
|
{
|
||||||
if (! display_predicate || item_predicate(display_predicate)(account))
|
if (disp_pred_functor(account))
|
||||||
functor(account);
|
functor(account);
|
||||||
|
|
||||||
accounts_deque accounts;
|
accounts_deque accounts;
|
||||||
|
|
@ -271,32 +242,56 @@ void walk__accounts_sorted(const account_t * account,
|
||||||
for (accounts_deque::const_iterator i = accounts.begin();
|
for (accounts_deque::const_iterator i = accounts.begin();
|
||||||
i != accounts.end();
|
i != accounts.end();
|
||||||
i++)
|
i++)
|
||||||
walk__accounts_sorted(*i, functor, sort_order, display_predicate);
|
walk__accounts_sorted(*i, functor, sort_order, disp_pred_functor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void calc__accounts(account_t * account,
|
template <typename Function>
|
||||||
const node_t * predicate,
|
void for_each_account(account_t * account, Function functor)
|
||||||
const bool related,
|
{
|
||||||
const bool inverted,
|
functor(account);
|
||||||
const bool calc_subtotals);
|
|
||||||
|
for (accounts_map::iterator i = account->accounts.begin();
|
||||||
|
i != account->accounts.end();
|
||||||
|
i++)
|
||||||
|
walk__accounts((*i).second, functor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void calc__accounts(account_t * account,
|
||||||
|
item_predicate<transaction_t>& pred_functor,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
|
inline void sum__accounts(account_t * account)
|
||||||
|
{
|
||||||
|
for (accounts_map::iterator i = account->accounts.begin();
|
||||||
|
i != account->accounts.end();
|
||||||
|
i++) {
|
||||||
|
sum__accounts((*i).second);
|
||||||
|
account->total += (*i).second->total;
|
||||||
|
}
|
||||||
|
account->total += account->value;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
void walk_accounts(account_t * account,
|
void walk_accounts(account_t * account,
|
||||||
Function functor,
|
Function functor,
|
||||||
const node_t * predicate,
|
const node_t * predicate,
|
||||||
const bool related,
|
unsigned int flags,
|
||||||
const bool inverted,
|
|
||||||
const bool calc_subtotals,
|
const bool calc_subtotals,
|
||||||
const node_t * display_predicate = NULL,
|
const node_t * display_predicate = NULL,
|
||||||
const node_t * sort_order = NULL)
|
const node_t * sort_order = NULL)
|
||||||
{
|
{
|
||||||
calc__accounts(account, predicate, related, inverted, calc_subtotals);
|
item_predicate<transaction_t> pred_functor(predicate);
|
||||||
|
item_predicate<account_t> disp_pred_functor(display_predicate);
|
||||||
|
|
||||||
|
calc__accounts(account, pred_functor, flags);
|
||||||
|
if (calc_subtotals)
|
||||||
|
sum__accounts(account);
|
||||||
|
|
||||||
if (sort_order)
|
if (sort_order)
|
||||||
walk__accounts_sorted<Function>(account, functor, sort_order,
|
walk__accounts_sorted<Function>(account, functor, sort_order,
|
||||||
display_predicate);
|
disp_pred_functor);
|
||||||
else
|
else
|
||||||
walk__accounts<Function>(account, functor, display_predicate);
|
walk__accounts<Function>(account, functor, disp_pred_functor);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue