removed constraints_t entirely
This commit is contained in:
parent
89c9bd2239
commit
c06fad4291
7 changed files with 256 additions and 315 deletions
157
constraint.h
157
constraint.h
|
|
@ -1,157 +0,0 @@
|
||||||
#ifndef _CONSTRAINT_H
|
|
||||||
#define _CONSTRAINT_H
|
|
||||||
|
|
||||||
#include "ledger.h"
|
|
||||||
#include "expr.h"
|
|
||||||
#include "item.h"
|
|
||||||
|
|
||||||
template <typename ForwardIterator, typename ValueType, typename Constraint>
|
|
||||||
class constrained_iterator
|
|
||||||
{
|
|
||||||
ForwardIterator iter, end;
|
|
||||||
const Constraint& constraint;
|
|
||||||
|
|
||||||
constrained_iterator& operator=(const constrained_iterator&);
|
|
||||||
|
|
||||||
public:
|
|
||||||
constrained_iterator(ForwardIterator begin, ForwardIterator _end,
|
|
||||||
const Constraint& _constraint)
|
|
||||||
: iter(begin), end(_end), constraint(_constraint) {
|
|
||||||
skip_nonmatching();
|
|
||||||
}
|
|
||||||
|
|
||||||
constrained_iterator(const constrained_iterator& other)
|
|
||||||
: iter(other.iter), end(other.end), constraint(other.constraint) {}
|
|
||||||
|
|
||||||
constrained_iterator operator++() const {
|
|
||||||
ForwardIterator temp = iter;
|
|
||||||
temp++;
|
|
||||||
return constrained_iterator(temp, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
constrained_iterator& operator++(int) {
|
|
||||||
iter++;
|
|
||||||
skip_nonmatching();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(ForwardIterator other) const {
|
|
||||||
return iter == other;
|
|
||||||
}
|
|
||||||
bool operator!=(ForwardIterator other) const {
|
|
||||||
return ! (*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueType operator*() const {
|
|
||||||
return *iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
void skip_nonmatching() {
|
|
||||||
bool failed;
|
|
||||||
do {
|
|
||||||
if (iter == end) return;
|
|
||||||
failed = false;
|
|
||||||
if (! constraint(*iter)) {
|
|
||||||
failed = true;
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
} while (failed);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace ledger {
|
|
||||||
|
|
||||||
class constraints_t
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool show_expanded;
|
|
||||||
bool show_related;
|
|
||||||
bool show_inverted;
|
|
||||||
bool show_subtotals;
|
|
||||||
bool show_empty;
|
|
||||||
|
|
||||||
node_t * predicate;
|
|
||||||
|
|
||||||
explicit constraints_t() {
|
|
||||||
show_expanded = false;
|
|
||||||
show_related = false;
|
|
||||||
show_inverted = false;
|
|
||||||
show_subtotals = true;
|
|
||||||
show_empty = false;
|
|
||||||
|
|
||||||
predicate = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
~constraints_t() {
|
|
||||||
if (predicate) delete predicate;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator ()(const transaction_t * xact) const {
|
|
||||||
if (! predicate) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
item_t temp;
|
|
||||||
temp.date = xact->entry->date;
|
|
||||||
temp.payee = xact->entry->payee;
|
|
||||||
temp.account = xact->account;
|
|
||||||
return predicate->compute(&temp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator ()(const entry_t * entry) const {
|
|
||||||
if (! predicate) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
item_t temp;
|
|
||||||
temp.date = entry->date;
|
|
||||||
temp.payee = entry->payee;
|
|
||||||
|
|
||||||
// Although there may be conflicting account masks for the whole
|
|
||||||
// set of transactions -- for example, /rent/&!/expenses/, which
|
|
||||||
// might match one by not another transactions -- we let the
|
|
||||||
// entry through if at least one of the transactions meets the
|
|
||||||
// criterion
|
|
||||||
|
|
||||||
for (transactions_list::const_iterator i = entry->transactions.begin();
|
|
||||||
i != entry->transactions.end();
|
|
||||||
i++) {
|
|
||||||
temp.account = (*i)->account;
|
|
||||||
if (predicate->compute(&temp))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator ()(const item_t * item) const {
|
|
||||||
return ! predicate || predicate->compute(item);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef constrained_iterator<transactions_list::const_iterator, transaction_t *,
|
|
||||||
constraints_t>
|
|
||||||
constrained_transactions_list_const_iterator;
|
|
||||||
|
|
||||||
typedef constrained_iterator<transactions_list::iterator, transaction_t *,
|
|
||||||
constraints_t>
|
|
||||||
constrained_transactions_list_iterator;
|
|
||||||
|
|
||||||
typedef constrained_iterator<entries_list::const_iterator, entry_t *,
|
|
||||||
constraints_t>
|
|
||||||
constrained_entries_list_const_iterator;
|
|
||||||
|
|
||||||
typedef constrained_iterator<entries_list::iterator, entry_t *,
|
|
||||||
constraints_t>
|
|
||||||
constrained_entries_list_iterator;
|
|
||||||
|
|
||||||
typedef constrained_iterator<items_deque::const_iterator, item_t *,
|
|
||||||
constraints_t>
|
|
||||||
constrained_items_deque_const_iterator;
|
|
||||||
|
|
||||||
typedef constrained_iterator<items_deque::iterator, item_t *,
|
|
||||||
constraints_t>
|
|
||||||
constrained_items_deque_iterator;
|
|
||||||
|
|
||||||
} // namespace ledger
|
|
||||||
|
|
||||||
#endif // _CONSTRAINT_H
|
|
||||||
50
expr.h
50
expr.h
|
|
@ -122,6 +122,56 @@ inline node_t * find_node(node_t * node, node_t::kind_t type) {
|
||||||
|
|
||||||
void dump_tree(std::ostream& out, node_t * node);
|
void dump_tree(std::ostream& out, node_t * node);
|
||||||
|
|
||||||
|
class value_predicate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const node_t * predicate;
|
||||||
|
|
||||||
|
explicit value_predicate(const node_t * _predicate)
|
||||||
|
: predicate(_predicate) {}
|
||||||
|
|
||||||
|
bool operator ()(const transaction_t * xact) const {
|
||||||
|
if (! predicate) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
item_t temp;
|
||||||
|
temp.date = xact->entry->date;
|
||||||
|
temp.payee = xact->entry->payee;
|
||||||
|
temp.account = xact->account;
|
||||||
|
return predicate->compute(&temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator ()(const entry_t * entry) const {
|
||||||
|
if (! predicate) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
item_t temp;
|
||||||
|
temp.date = entry->date;
|
||||||
|
temp.payee = entry->payee;
|
||||||
|
|
||||||
|
// Although there may be conflicting account masks for the whole
|
||||||
|
// set of transactions -- for example, /rent/&!/expenses/, which
|
||||||
|
// might match one by not another transactions -- we let the
|
||||||
|
// entry through if at least one of the transactions meets the
|
||||||
|
// criterion
|
||||||
|
|
||||||
|
for (transactions_list::const_iterator i = entry->transactions.begin();
|
||||||
|
i != entry->transactions.end();
|
||||||
|
i++) {
|
||||||
|
temp.account = (*i)->account;
|
||||||
|
if (predicate->compute(&temp))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator ()(const item_t * item) const {
|
||||||
|
return ! predicate || predicate->compute(item);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace report
|
} // namespace report
|
||||||
|
|
||||||
#endif // _REPORT_H
|
#endif // _REPORT_H
|
||||||
|
|
|
||||||
1
format.h
1
format.h
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include "ledger.h"
|
#include "ledger.h"
|
||||||
#include "balance.h"
|
#include "balance.h"
|
||||||
#include "constraint.h"
|
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
|
||||||
87
item.cc
87
item.cc
|
|
@ -1,5 +1,4 @@
|
||||||
#include "item.h"
|
#include "item.h"
|
||||||
#include "constraint.h"
|
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
@ -7,73 +6,84 @@ namespace ledger {
|
||||||
// jww (2004-07-21): If format.show_empty is set, then include all
|
// jww (2004-07-21): If format.show_empty is set, then include all
|
||||||
// subaccounts, empty, balanced or no
|
// subaccounts, empty, balanced or no
|
||||||
|
|
||||||
item_t * walk_accounts(const account_t * account,
|
item_t * walk_accounts(const account_t * account,
|
||||||
const constraints_t& constraints)
|
const node_t * predicate,
|
||||||
|
const bool show_subtotals)
|
||||||
{
|
{
|
||||||
item_t * item = new item_t;
|
item_t * item = new item_t;
|
||||||
item->account = account;
|
item->account = account;
|
||||||
|
|
||||||
for (constrained_transactions_list_const_iterator
|
std::time_t latest = 0;
|
||||||
i(account->transactions.begin(),
|
for (transactions_list::const_iterator i
|
||||||
account->transactions.end(), constraints);
|
= std::find_if(account->transactions.begin(),
|
||||||
|
account->transactions.end(),
|
||||||
|
value_predicate(predicate));
|
||||||
i != account->transactions.end();
|
i != account->transactions.end();
|
||||||
i++) {
|
i = std::find_if(++i, account->transactions.end(),
|
||||||
item->value += *(*i);
|
value_predicate(predicate))) {
|
||||||
|
if (std::difftime(latest, (*i)->entry->date) < 0)
|
||||||
|
latest = (*i)->entry->date;
|
||||||
|
|
||||||
if (constraints.show_subtotals)
|
item->value += *(*i);
|
||||||
|
if (show_subtotals)
|
||||||
item->total += *(*i);
|
item->total += *(*i);
|
||||||
}
|
}
|
||||||
|
item->date = latest;
|
||||||
|
|
||||||
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++) {
|
||||||
item_t * subitem = walk_accounts((*i).second, constraints);
|
item_t * subitem = walk_accounts((*i).second, predicate, show_subtotals);
|
||||||
subitem->parent = item;
|
subitem->parent = item;
|
||||||
|
|
||||||
if (constraints.show_subtotals)
|
if (std::difftime(item->date, subitem->date) < 0)
|
||||||
item->total += subitem->total;
|
item->date = subitem->date;
|
||||||
|
|
||||||
if (constraints.show_subtotals ? subitem->total : subitem->value)
|
if (show_subtotals)
|
||||||
|
item->total += subitem->total;
|
||||||
|
if (show_subtotals ? subitem->total : subitem->value)
|
||||||
item->subitems.push_back(subitem);
|
item->subitems.push_back(subitem);
|
||||||
}
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void sum_items(const item_t * top,
|
static inline void sum_items(const item_t * top,
|
||||||
const constraints_t& constraints,
|
const bool show_subtotals,
|
||||||
item_t * item)
|
item_t * item)
|
||||||
{
|
{
|
||||||
if (top->account == item->account) {
|
if (top->account == item->account) {
|
||||||
item->value += top->value;
|
item->value += top->value;
|
||||||
if (constraints.show_subtotals)
|
if (show_subtotals)
|
||||||
item->total += top->value;
|
item->total += top->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (items_deque::const_iterator i = top->subitems.begin();
|
for (items_deque::const_iterator i = top->subitems.begin();
|
||||||
i != top->subitems.end();
|
i != top->subitems.end();
|
||||||
i++)
|
i++)
|
||||||
sum_items(*i, constraints, item);
|
sum_items(*i, show_subtotals, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
item_t * walk_items(const item_t * top, const account_t * account,
|
item_t * walk_items(const item_t * top,
|
||||||
const constraints_t& constraints)
|
const account_t * account,
|
||||||
|
const node_t * predicate,
|
||||||
|
const bool show_subtotals)
|
||||||
{
|
{
|
||||||
item_t * item = new item_t;
|
item_t * item = new item_t;
|
||||||
item->account = account;
|
item->account = account;
|
||||||
|
|
||||||
sum_items(top, constraints, item);
|
sum_items(top, show_subtotals, item);
|
||||||
|
|
||||||
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++) {
|
||||||
item_t * subitem = walk_items(top, (*i).second, constraints);
|
item_t * subitem = walk_items(top, (*i).second, predicate, show_subtotals);
|
||||||
subitem->parent = item;
|
subitem->parent = item;
|
||||||
|
|
||||||
if (constraints.show_subtotals)
|
if (show_subtotals)
|
||||||
item->total += subitem->total;
|
item->total += subitem->total;
|
||||||
|
|
||||||
if (constraints.show_subtotals ? subitem->total : subitem->value)
|
if (show_subtotals ? subitem->total : subitem->value)
|
||||||
item->subitems.push_back(subitem);
|
item->subitems.push_back(subitem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,21 +92,26 @@ item_t * walk_items(const item_t * top, const account_t * account,
|
||||||
|
|
||||||
item_t * walk_entries(entries_list::const_iterator begin,
|
item_t * walk_entries(entries_list::const_iterator begin,
|
||||||
entries_list::const_iterator end,
|
entries_list::const_iterator end,
|
||||||
const constraints_t& constraints)
|
const node_t * predicate,
|
||||||
|
const bool show_related,
|
||||||
|
const bool show_inverted)
|
||||||
{
|
{
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
item_t * result = NULL;
|
item_t * result = NULL;
|
||||||
|
value_predicate pred_obj(predicate);
|
||||||
|
|
||||||
for (constrained_entries_list_const_iterator i(begin, end, constraints);
|
for (entries_list::const_iterator i = std::find_if(begin, end, pred_obj);
|
||||||
i != end;
|
i != end;
|
||||||
i++) {
|
i = std::find_if(++i, end, pred_obj)) {
|
||||||
item_t * item = NULL;
|
item_t * item = NULL;
|
||||||
|
|
||||||
for (constrained_transactions_list_const_iterator
|
for (transactions_list::const_iterator j
|
||||||
j((*i)->transactions.begin(), (*i)->transactions.end(),
|
= std::find_if((*i)->transactions.begin(),
|
||||||
constraints);
|
(*i)->transactions.end(), pred_obj);
|
||||||
j != (*i)->transactions.end();
|
j != (*i)->transactions.end();
|
||||||
j++) {
|
j = std::find_if(++j,
|
||||||
|
transactions_list::const_iterator((*i)->transactions.end()),
|
||||||
|
pred_obj)) {
|
||||||
assert(*i == (*j)->entry);
|
assert(*i == (*j)->entry);
|
||||||
|
|
||||||
if (! item) {
|
if (! item) {
|
||||||
|
|
@ -107,7 +122,7 @@ item_t * walk_entries(entries_list::const_iterator begin,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If show_inverted is true, it implies show_related.
|
// If show_inverted is true, it implies show_related.
|
||||||
if (! constraints.show_inverted) {
|
if (! show_inverted) {
|
||||||
item_t * subitem = new item_t;
|
item_t * subitem = new item_t;
|
||||||
subitem->parent = item;
|
subitem->parent = item;
|
||||||
subitem->date = item->date;
|
subitem->date = item->date;
|
||||||
|
|
@ -117,7 +132,7 @@ item_t * walk_entries(entries_list::const_iterator begin,
|
||||||
item->subitems.push_back(subitem);
|
item->subitems.push_back(subitem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (constraints.show_related)
|
if (show_related)
|
||||||
for (transactions_list::iterator k = (*i)->transactions.begin();
|
for (transactions_list::iterator k = (*i)->transactions.begin();
|
||||||
k != (*i)->transactions.end();
|
k != (*i)->transactions.end();
|
||||||
k++)
|
k++)
|
||||||
|
|
@ -128,7 +143,7 @@ item_t * walk_entries(entries_list::const_iterator begin,
|
||||||
subitem->payee = item->payee;
|
subitem->payee = item->payee;
|
||||||
subitem->account = (*k)->account;
|
subitem->account = (*k)->account;
|
||||||
subitem->value = *(*k);
|
subitem->value = *(*k);
|
||||||
if (constraints.show_inverted)
|
if (show_inverted)
|
||||||
subitem->value.negate();
|
subitem->value.negate();
|
||||||
item->subitems.push_back(subitem);
|
item->subitems.push_back(subitem);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
15
item.h
15
item.h
|
|
@ -36,17 +36,22 @@ struct item_t
|
||||||
void sort(const node_t * sort_order);
|
void sort(const node_t * sort_order);
|
||||||
};
|
};
|
||||||
|
|
||||||
class constraints_t;
|
struct node_t;
|
||||||
|
|
||||||
item_t * walk_accounts(const account_t * account,
|
item_t * walk_accounts(const account_t * account,
|
||||||
const constraints_t& constraints);
|
const node_t * predicate,
|
||||||
|
const bool show_subtotals);
|
||||||
|
|
||||||
item_t * walk_items(const item_t * top, const account_t * account,
|
item_t * walk_items(const item_t * top,
|
||||||
const constraints_t& constraints);
|
const account_t * account,
|
||||||
|
const node_t * predicate,
|
||||||
|
const bool show_subtotals);
|
||||||
|
|
||||||
item_t * walk_entries(entries_list::const_iterator begin,
|
item_t * walk_entries(entries_list::const_iterator begin,
|
||||||
entries_list::const_iterator end,
|
entries_list::const_iterator end,
|
||||||
const constraints_t& constraints);
|
const node_t * predicate,
|
||||||
|
const bool show_related,
|
||||||
|
const bool show_inverted);
|
||||||
|
|
||||||
} // namespace report
|
} // namespace report
|
||||||
|
|
||||||
|
|
|
||||||
259
main.cc
259
main.cc
|
|
@ -3,7 +3,6 @@
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "textual.h"
|
#include "textual.h"
|
||||||
#include "binary.h"
|
#include "binary.h"
|
||||||
#include "constraint.h"
|
|
||||||
#include "item.h"
|
#include "item.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
|
|
@ -23,21 +22,23 @@ namespace ledger {
|
||||||
|
|
||||||
static const std::string bal_fmt = "%20T%2_%-n\n";
|
static const std::string bal_fmt = "%20T%2_%-n\n";
|
||||||
|
|
||||||
unsigned int show_balances(std::ostream& out,
|
unsigned int show_balances(std::ostream& out,
|
||||||
items_deque& items,
|
items_deque& items,
|
||||||
const constraints_t& constraints,
|
const node_t * predicate,
|
||||||
const node_t * sort_order,
|
const node_t * sort_order,
|
||||||
const format_t& format,
|
const format_t& format,
|
||||||
const item_t * displayed_parent)
|
const bool show_expanded,
|
||||||
|
const item_t * displayed_parent)
|
||||||
{
|
{
|
||||||
unsigned int headlines = 0;
|
unsigned int headlines = 0;
|
||||||
|
value_predicate pred_obj(predicate);
|
||||||
|
|
||||||
for (items_deque::const_iterator i = items.begin();
|
for (items_deque::const_iterator i = items.begin();
|
||||||
i != items.end();
|
i != items.end();
|
||||||
i++) {
|
i++) {
|
||||||
const item_t * parent = displayed_parent;
|
const item_t * parent = displayed_parent;
|
||||||
|
|
||||||
if (constraints(*i) &&
|
if (pred_obj(*i) &&
|
||||||
((*i)->subitems.size() != 1 ||
|
((*i)->subitems.size() != 1 ||
|
||||||
(*i)->total != (*i)->subitems[0]->total)) {
|
(*i)->total != (*i)->subitems[0]->total)) {
|
||||||
format.format_elements(out, *i, parent);
|
format.format_elements(out, *i, parent);
|
||||||
|
|
@ -50,9 +51,9 @@ unsigned int show_balances(std::ostream& out,
|
||||||
if (sort_order)
|
if (sort_order)
|
||||||
(*i)->sort(sort_order);
|
(*i)->sort(sort_order);
|
||||||
|
|
||||||
if (constraints.show_expanded)
|
if (show_expanded)
|
||||||
headlines += show_balances(out, (*i)->subitems, constraints,
|
headlines += show_balances(out, (*i)->subitems, predicate,
|
||||||
sort_order, format, parent);
|
sort_order, format, true, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return headlines;
|
return headlines;
|
||||||
|
|
@ -60,17 +61,20 @@ unsigned int show_balances(std::ostream& out,
|
||||||
|
|
||||||
void balance_report(std::ostream& out,
|
void balance_report(std::ostream& out,
|
||||||
item_t * top,
|
item_t * top,
|
||||||
const constraints_t& constraints,
|
const node_t * predicate,
|
||||||
const node_t * sort_order,
|
const node_t * sort_order,
|
||||||
const format_t& format)
|
const format_t& format,
|
||||||
|
const bool show_expanded,
|
||||||
|
const bool show_subtotals)
|
||||||
{
|
{
|
||||||
if (sort_order)
|
if (sort_order)
|
||||||
top->sort(sort_order);
|
top->sort(sort_order);
|
||||||
|
|
||||||
unsigned int headlines = show_balances(out, top->subitems, constraints,
|
unsigned int headlines = show_balances(out, top->subitems, predicate,
|
||||||
sort_order, format, top);
|
sort_order, format, show_expanded,
|
||||||
|
top);
|
||||||
|
|
||||||
if (constraints.show_subtotals && headlines > 1 && top->total) {
|
if (show_subtotals && headlines > 1 && top->total) {
|
||||||
std::cout << "--------------------\n";
|
std::cout << "--------------------\n";
|
||||||
format.format_elements(std::cout, top);
|
format.format_elements(std::cout, top);
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +96,7 @@ static void report_value_change(std::ostream& out,
|
||||||
const std::time_t date,
|
const std::time_t date,
|
||||||
const balance_pair_t& balance,
|
const balance_pair_t& balance,
|
||||||
const balance_pair_t& prev_balance,
|
const balance_pair_t& prev_balance,
|
||||||
const constraints_t& constraints,
|
const node_t * predicate,
|
||||||
const format_t& first_line_format,
|
const format_t& first_line_format,
|
||||||
const format_t& next_lines_format)
|
const format_t& next_lines_format)
|
||||||
{
|
{
|
||||||
|
|
@ -116,7 +120,7 @@ static void report_value_change(std::ostream& out,
|
||||||
temp.total = balance;
|
temp.total = balance;
|
||||||
temp.payee = "Commodities revalued";
|
temp.payee = "Commodities revalued";
|
||||||
|
|
||||||
if (constraints(&temp)) {
|
if (value_predicate(predicate)(&temp)) {
|
||||||
first_line_format.format_elements(out, &temp);
|
first_line_format.format_elements(out, &temp);
|
||||||
next_lines_format.format_elements(out, &temp);
|
next_lines_format.format_elements(out, &temp);
|
||||||
}
|
}
|
||||||
|
|
@ -125,26 +129,28 @@ static void report_value_change(std::ostream& out,
|
||||||
prev_date = date;
|
prev_date = date;
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_report(std::ostream& out,
|
void register_report(std::ostream& out,
|
||||||
item_t * top,
|
item_t * top,
|
||||||
const constraints_t& constraints,
|
const node_t * predicate,
|
||||||
const node_t * sort_order,
|
const node_t * sort_order,
|
||||||
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 show_expanded)
|
||||||
{
|
{
|
||||||
if (sort_order)
|
if (sort_order)
|
||||||
top->sort(sort_order);
|
top->sort(sort_order);
|
||||||
|
|
||||||
balance_pair_t balance;
|
balance_pair_t balance;
|
||||||
balance_pair_t last_reported;
|
balance_pair_t last_reported;
|
||||||
account_t splits(NULL, "<Total>");
|
account_t splits(NULL, "<Total>");
|
||||||
|
value_predicate pred_obj(predicate);
|
||||||
|
|
||||||
for (items_deque::const_iterator i = top->subitems.begin();
|
for (items_deque::const_iterator i = top->subitems.begin();
|
||||||
i != top->subitems.end();
|
i != top->subitems.end();
|
||||||
i++) {
|
i++) {
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
if ((*i)->subitems.size() > 1 && ! constraints.show_expanded) {
|
if ((*i)->subitems.size() > 1 && ! show_expanded) {
|
||||||
item_t summary;
|
item_t summary;
|
||||||
summary.date = (*i)->date;
|
summary.date = (*i)->date;
|
||||||
summary.parent = *i;
|
summary.parent = *i;
|
||||||
|
|
@ -156,10 +162,10 @@ void register_report(std::ostream& out,
|
||||||
summary.value += (*j)->value;
|
summary.value += (*j)->value;
|
||||||
summary.total = balance + summary.value;
|
summary.total = balance + summary.value;
|
||||||
|
|
||||||
bool show = constraints(&summary);
|
bool show = pred_obj(&summary);
|
||||||
if (show && show_commodities_revalued)
|
if (show && show_commodities_revalued)
|
||||||
report_value_change(out, summary.date, balance, last_reported,
|
report_value_change(out, summary.date, balance, last_reported,
|
||||||
constraints, first_line_format, next_lines_format);
|
predicate, first_line_format, next_lines_format);
|
||||||
|
|
||||||
balance += summary.value;
|
balance += summary.value;
|
||||||
|
|
||||||
|
|
@ -176,11 +182,10 @@ void register_report(std::ostream& out,
|
||||||
j++) {
|
j++) {
|
||||||
(*j)->total = balance + (*j)->value;
|
(*j)->total = balance + (*j)->value;
|
||||||
|
|
||||||
bool show = constraints(*j);
|
bool show = pred_obj(*j);
|
||||||
if (show && first && show_commodities_revalued) {
|
if (show && first && show_commodities_revalued) {
|
||||||
report_value_change(out, (*i)->date, balance, last_reported,
|
report_value_change(out, (*i)->date, balance, last_reported,
|
||||||
constraints, first_line_format,
|
predicate, first_line_format, next_lines_format);
|
||||||
next_lines_format);
|
|
||||||
if (show_commodities_revalued_only)
|
if (show_commodities_revalued_only)
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
@ -205,7 +210,7 @@ void register_report(std::ostream& out,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_commodities_revalued)
|
if (show_commodities_revalued)
|
||||||
report_value_change(out, -1, balance, last_reported, constraints,
|
report_value_change(out, -1, balance, last_reported, predicate,
|
||||||
first_line_format, next_lines_format);
|
first_line_format, next_lines_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -471,14 +476,20 @@ static void show_help(std::ostream& out)
|
||||||
int main(int argc, char * argv[])
|
int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
std::list<std::string> files;
|
std::list<std::string> files;
|
||||||
ledger::ledger_t * journal = new ledger::ledger_t;
|
|
||||||
ledger::constraints_t constraints;
|
std::string predicate_string;
|
||||||
std::string predicate;
|
ledger::node_t * predicate = NULL;
|
||||||
std::string format_string;
|
std::string format_string;
|
||||||
std::string sort_str;
|
std::string sort_string;
|
||||||
ledger::node_t * sort_order = NULL;
|
ledger::node_t * sort_order = NULL;
|
||||||
std::string value_expr = "a";
|
std::string value_expr = "a";
|
||||||
std::string total_expr = "T";
|
std::string total_expr = "T";
|
||||||
|
ledger::ledger_t * journal = new ledger::ledger_t;
|
||||||
|
|
||||||
|
bool show_subtotals = true;
|
||||||
|
bool show_expanded = false;
|
||||||
|
bool show_related = false;
|
||||||
|
bool show_inverted = false;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
bool debug = false;
|
bool debug = false;
|
||||||
|
|
@ -562,48 +573,48 @@ int main(int argc, char * argv[])
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'b':
|
case 'b':
|
||||||
if (! predicate.empty())
|
if (! predicate_string.empty())
|
||||||
predicate += "&";
|
predicate_string += "&";
|
||||||
predicate += "(d>=[";
|
predicate_string += "(d>=[";
|
||||||
predicate += optarg;
|
predicate_string += optarg;
|
||||||
predicate += "])";
|
predicate_string += "])";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'e':
|
case 'e':
|
||||||
if (! predicate.empty())
|
if (! predicate_string.empty())
|
||||||
predicate += "&";
|
predicate_string += "&";
|
||||||
predicate += "(d<[";
|
predicate_string += "(d<[";
|
||||||
predicate += optarg;
|
predicate_string += optarg;
|
||||||
predicate += "])";
|
predicate_string += "])";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c': {
|
case 'c': {
|
||||||
if (! predicate.empty())
|
if (! predicate_string.empty())
|
||||||
predicate += "&";
|
predicate_string += "&";
|
||||||
predicate += "(d<";
|
predicate_string += "(d<";
|
||||||
std::ostringstream now;
|
std::ostringstream now;
|
||||||
now << std::time(NULL);
|
now << std::time(NULL);
|
||||||
predicate += now.str();
|
predicate_string += now.str();
|
||||||
predicate += ")";
|
predicate_string += ")";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'C':
|
case 'C':
|
||||||
if (! predicate.empty())
|
if (! predicate_string.empty())
|
||||||
predicate += "&";
|
predicate_string += "&";
|
||||||
predicate += "X";
|
predicate_string += "X";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'U':
|
case 'U':
|
||||||
if (! predicate.empty())
|
if (! predicate_string.empty())
|
||||||
predicate += "&";
|
predicate_string += "&";
|
||||||
predicate += "!X";
|
predicate_string += "!X";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'R':
|
case 'R':
|
||||||
if (! predicate.empty())
|
if (! predicate_string.empty())
|
||||||
predicate += "&";
|
predicate_string += "&";
|
||||||
predicate += "R";
|
predicate_string += "R";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Customizing output
|
// Customizing output
|
||||||
|
|
@ -611,32 +622,34 @@ int main(int argc, char * argv[])
|
||||||
format_string = optarg;
|
format_string = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if 0
|
||||||
case 'E':
|
case 'E':
|
||||||
constraints.show_empty = true;
|
show_empty = true;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case 'n':
|
case 'n':
|
||||||
constraints.show_subtotals = false;
|
show_subtotals = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
constraints.show_expanded = true;
|
show_expanded = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'S':
|
case 'S':
|
||||||
sort_str = optarg;
|
sort_string = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'o':
|
case 'o':
|
||||||
constraints.show_related = true;
|
show_related = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
if (! predicate.empty())
|
if (! predicate_string.empty())
|
||||||
predicate += "&";
|
predicate_string += "&";
|
||||||
predicate += "(";
|
predicate_string += "(";
|
||||||
predicate += optarg;
|
predicate_string += optarg;
|
||||||
predicate += ")";
|
predicate_string += ")";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Commodity reporting
|
// Commodity reporting
|
||||||
|
|
@ -700,6 +713,7 @@ int main(int argc, char * argv[])
|
||||||
total_expr = "MDMT";
|
total_expr = "MDMT";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if 0
|
||||||
case 'W':
|
case 'W':
|
||||||
value_expr = "a";
|
value_expr = "a";
|
||||||
total_expr = "MD(MT*(d-b/e-b))";
|
total_expr = "MD(MT*(d-b/e-b))";
|
||||||
|
|
@ -709,6 +723,11 @@ int main(int argc, char * argv[])
|
||||||
value_expr = "a";
|
value_expr = "a";
|
||||||
total_expr = "a+MD(MT*(d-b/e-b))";
|
total_expr = "a+MD(MT*(d-b/e-b))";
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -778,50 +797,51 @@ int main(int argc, char * argv[])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
constraints.show_expanded = true;
|
show_expanded = true;
|
||||||
|
|
||||||
if (! predicate.empty())
|
if (! predicate_string.empty())
|
||||||
predicate += "&";
|
predicate_string += "&";
|
||||||
|
|
||||||
if (argv[index][0] == '-') {
|
if (argv[index][0] == '-') {
|
||||||
predicate += "(!/";
|
predicate_string += "(!/";
|
||||||
predicate += argv[index] + 1;
|
predicate_string += argv[index] + 1;
|
||||||
} else {
|
} else {
|
||||||
predicate += "(/";
|
predicate_string += "(/";
|
||||||
predicate += argv[index];
|
predicate_string += argv[index];
|
||||||
}
|
}
|
||||||
predicate += "/)";
|
predicate_string += "/)";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; index < argc; index++) {
|
for (; index < argc; index++) {
|
||||||
constraints.show_expanded = true;
|
show_expanded = true;
|
||||||
|
|
||||||
if (! predicate.empty())
|
if (! predicate_string.empty())
|
||||||
predicate += "&";
|
predicate_string += "&";
|
||||||
|
|
||||||
if (argv[index][0] == '-') {
|
if (argv[index][0] == '-') {
|
||||||
predicate += "(!//";
|
predicate_string += "(!//";
|
||||||
predicate += argv[index] + 1;
|
predicate_string += argv[index] + 1;
|
||||||
} else {
|
} else {
|
||||||
predicate += "(//";
|
predicate_string += "(//";
|
||||||
predicate += argv[index];
|
predicate_string += argv[index];
|
||||||
}
|
}
|
||||||
predicate += "/)";
|
predicate_string += "/)";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the constraints to the format object, and compile the value
|
// Compile the predicate
|
||||||
// and total style strings
|
|
||||||
|
|
||||||
if (! predicate.empty()) {
|
if (! predicate_string.empty()) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (debug)
|
if (debug)
|
||||||
std::cerr << "predicate = " << predicate << std::endl;
|
std::cerr << "predicate = " << predicate_string << std::endl;
|
||||||
#endif
|
#endif
|
||||||
constraints.predicate = ledger::parse_expr(predicate);
|
predicate = ledger::parse_expr(predicate_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! sort_str.empty())
|
// Compile the sorting string
|
||||||
sort_order = ledger::parse_expr(sort_str);
|
|
||||||
|
if (! sort_string.empty())
|
||||||
|
sort_order = ledger::parse_expr(sort_string);
|
||||||
|
|
||||||
// Setup the meaning of %t and %T encountered in format strings
|
// Setup the meaning of %t and %T encountered in format strings
|
||||||
|
|
||||||
|
|
@ -834,7 +854,8 @@ int main(int argc, char * argv[])
|
||||||
#if 0
|
#if 0
|
||||||
if (ledger::item_t * top
|
if (ledger::item_t * top
|
||||||
= ledger::walk_entries(journal->entries.begin(),
|
= ledger::walk_entries(journal->entries.begin(),
|
||||||
journal->entries.end(), constraints)) {
|
journal->entries.end(), predicate,
|
||||||
|
show_related, show_inverted)) {
|
||||||
ledger::format_t * format = new ledger::format_t(format_string);
|
ledger::format_t * format = new ledger::format_t(format_string);
|
||||||
ledger::entry_report(std::cout, top, *format);
|
ledger::entry_report(std::cout, top, *format);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
@ -847,9 +868,9 @@ int main(int argc, char * argv[])
|
||||||
else if (command == "equity") {
|
else if (command == "equity") {
|
||||||
#if 0
|
#if 0
|
||||||
if (ledger::item_t * top
|
if (ledger::item_t * top
|
||||||
= ledger::walk_accounts(journal->master, constraints)) {
|
= ledger::walk_accounts(journal->master, predicate, show_subtotals)) {
|
||||||
ledger::format_t * format = new ledger::format_t(format_string);
|
ledger::format_t * format = new ledger::format_t(format_string);
|
||||||
ledger::entry_report(std::cout, top, constraints, *format);
|
ledger::entry_report(std::cout, top, predicate, *format);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
delete top;
|
delete top;
|
||||||
delete format;
|
delete format;
|
||||||
|
|
@ -857,14 +878,15 @@ int main(int argc, char * argv[])
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (! sort_order && ! constraints.show_related &&
|
else if (! sort_order && ! show_related &&
|
||||||
(command == "balance" || command == "bal")) {
|
(command == "balance" || command == "bal")) {
|
||||||
if (ledger::item_t * top
|
if (ledger::item_t * top
|
||||||
= ledger::walk_accounts(journal->master, constraints)) {
|
= ledger::walk_accounts(journal->master, predicate, show_subtotals)) {
|
||||||
ledger::format_t * format
|
ledger::format_t * format
|
||||||
= new ledger::format_t(format_string.empty() ?
|
= new ledger::format_t(format_string.empty() ?
|
||||||
ledger::bal_fmt : format_string);
|
ledger::bal_fmt : format_string);
|
||||||
ledger::balance_report(std::cout, top, constraints, sort_order, *format);
|
ledger::balance_report(std::cout, top, predicate, sort_order, *format,
|
||||||
|
show_expanded, show_subtotals);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
delete format;
|
delete format;
|
||||||
delete top;
|
delete top;
|
||||||
|
|
@ -874,14 +896,16 @@ int main(int argc, char * argv[])
|
||||||
else if (command == "balance" || command == "bal") {
|
else if (command == "balance" || command == "bal") {
|
||||||
if (ledger::item_t * list
|
if (ledger::item_t * list
|
||||||
= ledger::walk_entries(journal->entries.begin(),
|
= ledger::walk_entries(journal->entries.begin(),
|
||||||
journal->entries.end(), constraints))
|
journal->entries.end(), predicate,
|
||||||
|
show_related, show_inverted))
|
||||||
if (ledger::item_t * top
|
if (ledger::item_t * top
|
||||||
= ledger::walk_items(list, journal->master, constraints)) {
|
= ledger::walk_items(list, journal->master, predicate,
|
||||||
|
show_subtotals)) {
|
||||||
ledger::format_t * format
|
ledger::format_t * format
|
||||||
= new ledger::format_t(format_string.empty() ?
|
= new ledger::format_t(format_string.empty() ?
|
||||||
ledger::bal_fmt : format_string);
|
ledger::bal_fmt : format_string);
|
||||||
ledger::balance_report(std::cout, top, constraints, sort_order,
|
ledger::balance_report(std::cout, top, predicate, sort_order, *format,
|
||||||
*format);
|
show_expanded, show_subtotals);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
delete format;
|
delete format;
|
||||||
delete top;
|
delete top;
|
||||||
|
|
@ -890,12 +914,13 @@ int main(int argc, char * argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (command == "register" || command == "reg") {
|
else if (command == "register" || command == "reg") {
|
||||||
if (constraints.show_related)
|
if (show_related)
|
||||||
constraints.show_inverted = true;
|
show_inverted = true;
|
||||||
|
|
||||||
if (ledger::item_t * top
|
if (ledger::item_t * top
|
||||||
= ledger::walk_entries(journal->entries.begin(),
|
= ledger::walk_entries(journal->entries.begin(),
|
||||||
journal->entries.end(), constraints)) {
|
journal->entries.end(), predicate,
|
||||||
|
show_related, show_inverted)) {
|
||||||
std::string first_line_format;
|
std::string first_line_format;
|
||||||
std::string next_lines_format;
|
std::string next_lines_format;
|
||||||
|
|
||||||
|
|
@ -911,9 +936,11 @@ int main(int argc, char * argv[])
|
||||||
|
|
||||||
ledger::format_t * format = new ledger::format_t(first_line_format);
|
ledger::format_t * format = new ledger::format_t(first_line_format);
|
||||||
ledger::format_t * nformat = new ledger::format_t(next_lines_format);
|
ledger::format_t * nformat = new ledger::format_t(next_lines_format);
|
||||||
ledger::register_report(std::cout, top, constraints, sort_order,
|
|
||||||
*format, *nformat);
|
ledger::register_report(std::cout, top, predicate, sort_order,
|
||||||
|
*format, *nformat, show_expanded);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
delete nformat;
|
||||||
delete format;
|
delete format;
|
||||||
delete top;
|
delete top;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -937,6 +964,8 @@ int main(int argc, char * argv[])
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
delete journal;
|
delete journal;
|
||||||
|
|
||||||
|
if (predicate)
|
||||||
|
delete predicate;
|
||||||
if (sort_order)
|
if (sort_order)
|
||||||
delete sort_order;
|
delete sort_order;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include "textual.h"
|
#include "textual.h"
|
||||||
#include "constraint.h"
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "expr.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue