summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--format.cc113
-rw-r--r--format.h92
-rw-r--r--ledger.h5
-rw-r--r--main.cc147
-rw-r--r--valexpr.cc16
-rw-r--r--valexpr.h16
-rw-r--r--walk.h4
7 files changed, 162 insertions, 231 deletions
diff --git a/format.cc b/format.cc
index a509c143..87fbcdd0 100644
--- a/format.cc
+++ b/format.cc
@@ -14,18 +14,22 @@ std::string truncated(const std::string& str, unsigned int width)
return buf;
}
-std::string partial_account_name(const account_t * account,
- const unsigned int start_depth)
+std::string partial_account_name(const account_t * account)
{
- std::string name = account->name;
- const account_t * acct = account->parent;
-
- for (int i = account->depth - start_depth - 1;
- --i >= 0 && acct->parent; ) {
- assert(acct);
- name = acct->name + ":" + name;
- acct = acct->parent;
+ std::string name;
+
+ for (const account_t * acct = account;
+ acct && acct->parent;
+ acct = acct->parent) {
+ if (acct->flags & ACCOUNT_DISPLAYED)
+ break;
+
+ if (name.empty())
+ name = acct->name;
+ else
+ name = acct->name + ":" + name;
}
+
return name;
}
@@ -206,8 +210,7 @@ void format_t::format_elements(std::ostream& out,
if (details.account) {
std::string name = (elem->type == element_t::ACCOUNT_FULLNAME ?
details.account->fullname() :
- partial_account_name(details.account,
- details.depth));
+ partial_account_name(details.account));
if (elem->max_width > 0)
name = truncated(name, elem->max_width);
@@ -278,12 +281,15 @@ void format_t::format_elements(std::ostream& out,
}
case element_t::SPACER:
- for (unsigned int i = 0; i < details.depth; i++) {
- if (elem->min_width > 0 || elem->max_width > 0)
- out.width(elem->min_width > elem->max_width ?
- elem->min_width : elem->max_width);
- out << " ";
- }
+ for (const account_t * acct = details.account;
+ acct;
+ acct = acct->parent)
+ if (acct->flags & ACCOUNT_DISPLAYED) {
+ if (elem->min_width > 0 || elem->max_width > 0)
+ out.width(elem->min_width > elem->max_width ?
+ elem->min_width : elem->max_width);
+ out << " ";
+ }
break;
default:
@@ -293,11 +299,12 @@ void format_t::format_elements(std::ostream& out,
}
}
+#ifdef COLLAPSED_REGISTER
+
void format_transaction::report_cumulative_subtotal() const
{
if (count == 1) {
- if (! intercept || ! intercept(last_xact))
- first_line_format.format_elements(output_stream, details_t(last_xact));
+ first_line_format.format_elements(output_stream, details_t(last_xact));
return;
}
@@ -321,9 +328,8 @@ void format_transaction::report_cumulative_subtotal() const
splits_total.cost = (*i).second;
splits_total.total += (*i).second;
if (first) {
- if (! intercept || ! intercept(&splits_total))
- first_line_format.format_elements(output_stream,
- details_t(&splits_total));
+ first_line_format.format_elements(output_stream,
+ details_t(&splits_total));
first = false;
} else {
next_lines_format.format_elements(output_stream,
@@ -332,10 +338,12 @@ void format_transaction::report_cumulative_subtotal() const
}
}
+#endif // COLLAPSED_REGISTER
+
void format_transaction::operator()(transaction_t * xact) const
{
if (last_xact)
- xact->total = last_xact->total;
+ xact->total += last_xact->total;
if (inverted) {
xact->amount.negate();
@@ -353,6 +361,7 @@ void format_transaction::operator()(transaction_t * xact) const
// This makes the assumption that transactions from a single entry
// are always grouped together.
+#ifdef COLLAPSED_REGISTER
if (collapsed) {
// If we've reached a new entry, report on the subtotal
// accumulated thus far.
@@ -365,10 +374,11 @@ void format_transaction::operator()(transaction_t * xact) const
subtotal += *xact;
count++;
- } else {
+ } else
+#endif
+ {
if (last_entry != xact->entry) {
- if (! intercept || ! intercept(xact))
- first_line_format.format_elements(output_stream, details_t(xact));
+ first_line_format.format_elements(output_stream, details_t(xact));
} else {
next_lines_format.format_elements(output_stream, details_t(xact));
}
@@ -383,38 +393,8 @@ void format_transaction::operator()(transaction_t * xact) const
last_xact = xact;
}
-#if 0
-
-bool report_changed_values(transaction_t * xact)
-{
- static transaction_t * last_xact = NULL;
- if (last_xact) {
- balance_t prev_bal, cur_bal;
- format_t::compute_total(prev_bal, details_t(last_xact));
- format_t::compute_total(cur_bal, details_t(xact));
-
- if (balance_t diff = cur_bal - prev_bal) {
- entry_t modified_entry;
- transaction_t new_xact(&modified_entry, NULL);
-
- modified_entry.date = xact ? xact->entry->date : std::time(NULL);
- modified_entry.payee = "Commodities revalued";
-
- new_xact.amount = diff.amount();
- format_t::compute_value(diff, details_t(xact));
- new_xact.total = cur_bal - diff;
-
- functor(&new_xact);
- }
- }
-
- last_xact = xact;
-}
-
-#endif
-
-void format_account::operator()(const account_t * account,
+void format_account::operator()(account_t * account,
const unsigned int max_depth,
const bool report_top) const
{
@@ -425,7 +405,8 @@ void format_account::operator()(const account_t * account,
// parent account and a lone displayed child, then don't display the
// parent."
- if (bool output = report_top || account->parent != NULL) {
+ if (bool output = ((report_top || account->parent != NULL) &&
+ disp_pred_functor(account))) {
int counted = 0;
bool display = false;
@@ -445,17 +426,9 @@ void format_account::operator()(const account_t * account,
if (counted == 1 && ! display)
output = false;
- if (output) {
- unsigned int depth = account->depth;
- if (max_depth == 0 || depth <= max_depth) {
- for (const account_t * acct = account;
- depth > 0 && acct && acct != last_account;
- acct = acct->parent)
- depth--;
-
- format.format_elements(output_stream, details_t(account, depth));
- last_account = account;
- }
+ if (output && (max_depth == 0 || account->depth <= max_depth)) {
+ format.format_elements(output_stream, details_t(account));
+ account->flags |= ACCOUNT_DISPLAYED;
}
}
}
diff --git a/format.h b/format.h
index a7c49301..649bb190 100644
--- a/format.h
+++ b/format.h
@@ -87,17 +87,17 @@ class format_transaction
std::ostream& output_stream;
const format_t& first_line_format;
const format_t& next_lines_format;
+#ifdef COLLAPSED_REGISTER
const bool collapsed;
+#endif
const bool inverted;
item_predicate<transaction_t> disp_pred_functor;
- typedef bool (*intercept_t)(transaction_t * xact);
-
- intercept_t intercept;
-
+#ifdef COLLAPSED_REGISTER
mutable balance_pair_t subtotal;
mutable unsigned int count;
+#endif
mutable entry_t * last_entry;
mutable transaction_t * last_xact;
@@ -106,29 +106,86 @@ class format_transaction
const format_t& _first_line_format,
const format_t& _next_lines_format,
const node_t * display_predicate,
+#ifdef COLLAPSED_REGISTER
const bool _collapsed = false,
- const bool _inverted = false,
- intercept_t _intercept = NULL)
+#endif
+ const bool _inverted = false)
: output_stream(_output_stream),
first_line_format(_first_line_format),
next_lines_format(_next_lines_format),
- collapsed(_collapsed), inverted(_inverted),
- disp_pred_functor(display_predicate),
- intercept(_intercept), count(0),
+#ifdef COLLAPSED_REGISTER
+ collapsed(_collapsed),
+#endif
+ inverted(_inverted), disp_pred_functor(display_predicate),
+#ifdef COLLAPSED_REGISTER
+ count(0),
+#endif
last_entry(NULL), last_xact(NULL) {}
- void start() const {}
- void finish() const {
+#ifdef COLLAPSED_REGISTER
+ ~format_transaction() {
if (subtotal)
report_cumulative_subtotal();
}
void report_cumulative_subtotal() const;
+#endif
+
void operator()(transaction_t * xact) const;
};
-// An intercept that can be used to report changes in commodity value
-bool report_changed_values(transaction_t * xact);
+
+template <typename Function>
+class changed_value_filter
+{
+ const Function& functor;
+
+ mutable entry_t modified_entry;
+ mutable transaction_t modified_xact;
+ mutable transaction_t * last_xact;
+
+ public:
+ changed_value_filter(const Function& _functor)
+ : functor(_functor), modified_xact(&modified_entry, NULL),
+ last_xact(NULL) {
+ modified_entry.payee = "Commodities revalued";
+ }
+
+ ~changed_value_filter() {
+ (*this)(NULL);
+ }
+
+ void operator()(transaction_t * xact) const {
+ if (last_xact) {
+ balance_t prev_bal, cur_bal;
+
+ format_t::compute_total(prev_bal, details_t(last_xact));
+
+ std::time_t current = xact ? xact->entry->date : std::time(NULL);
+ std::time_t prev_date = last_xact->entry->date;
+ last_xact->entry->date = current;
+ format_t::compute_total(cur_bal, details_t(last_xact));
+ last_xact->entry->date = prev_date;
+
+ if (balance_t diff = cur_bal - prev_bal) {
+ modified_entry.date = current;
+
+ // jww (2004-08-07): What if there are multiple commodities?
+ assert(diff.amounts.size() == 1);
+ modified_xact.amount = diff.amount();
+ modified_xact.total = diff;
+ modified_xact.total.negate();
+
+ functor(&modified_xact);
+ }
+ }
+
+ if (xact)
+ functor(xact);
+
+ last_xact = xact;
+ }
+};
class format_account
@@ -138,19 +195,14 @@ class format_account
item_predicate<account_t> disp_pred_functor;
- mutable const account_t * last_account;
-
public:
format_account(std::ostream& _output_stream,
const format_t& _format,
const node_t * display_predicate = NULL)
: output_stream(_output_stream), format(_format),
- disp_pred_functor(display_predicate), last_account(NULL) {}
-
- void start() const {}
- void finish() const {}
+ disp_pred_functor(display_predicate) {}
- void operator()(const account_t * account,
+ void operator()(account_t * account,
const unsigned int max_depth = 1,
const bool report_top = false) const;
};
diff --git a/ledger.h b/ledger.h
index 8fec0c17..94a7e08a 100644
--- a/ledger.h
+++ b/ledger.h
@@ -94,6 +94,8 @@ class entry_t
};
+#define ACCOUNT_DISPLAYED 0x1
+
typedef std::map<const std::string, account_t *> accounts_map;
typedef std::pair<const std::string, account_t *> accounts_pair;
@@ -109,6 +111,7 @@ class account_t
balance_pair_t value;
balance_pair_t total;
unsigned long ident;
+ unsigned long flags;
mutable std::string _fullname;
static unsigned long next_ident;
@@ -117,7 +120,7 @@ class account_t
const std::string& _name = "",
const std::string& _note = "")
: parent(_parent), name(_name), note(_note),
- depth(parent ? parent->depth + 1 : 0) {}
+ depth(parent ? parent->depth + 1 : 0), flags(0) {}
~account_t();
diff --git a/main.cc b/main.cc
index cab9abed..73248450 100644
--- a/main.cc
+++ b/main.cc
@@ -11,19 +11,8 @@
namespace ledger {
-
-//////////////////////////////////////////////////////////////////////
-//
-// The command-line balance report
-//
-
static const std::string bal_fmt = "%20T %2_%-n\n";
-//////////////////////////////////////////////////////////////////////
-//
-// The command-line register and print report
-//
-
static const std::string reg_fmt
= "%10d %-.20p %-.22N %12.66t %12.80T\n\
%/ %-.22N %12.66t %12.80T\n";
@@ -31,104 +20,6 @@ static const std::string reg_fmt
static const std::string print_fmt
= "\n%10d %X%C%p\n %-34N %12o\n%/ %-34N %12o\n";
-#if 0
-
-static void report_value_change(std::ostream& out,
- const std::time_t date,
- const balance_pair_t& balance,
- const balance_pair_t& prev_balance,
- const node_t * predicate,
- const format_t& first_line_format,
- const format_t& next_lines_format)
-{
-}
-
-void register_report(std::ostream& out,
- item_t * top,
- const node_t * predicate,
- const node_t * sort_order,
- const format_t& first_line_format,
- const format_t& next_lines_format,
- const bool show_expanded)
-{
- if (sort_order)
- top->sort(sort_order);
-
- balance_pair_t balance;
- balance_pair_t last_reported;
- account_t splits(NULL, "<Total>");
- value_predicate pred_obj(predicate);
-
- for (items_deque::const_iterator i = top->subitems.begin();
- i != top->subitems.end();
- i++) {
- bool first = true;
-
- if ((*i)->subitems.size() > 1 && ! show_expanded) {
- item_t summary(*i);
- summary.parent = *i;
- summary.account = &splits;
-
- summary.value = 0;
- for (items_deque::const_iterator j = (*i)->subitems.begin();
- j != (*i)->subitems.end();
- j++)
- summary.value += (*j)->value;
- summary.total = balance + summary.value;
-
- bool show = pred_obj(&summary);
- if (show && show_commodities_revalued)
- report_value_change(out, summary.date, balance, last_reported,
- predicate, first_line_format, next_lines_format);
-
- balance += summary.value;
-
- if (show) {
- if (! show_commodities_revalued_only)
- first_line_format.format_elements(out, &summary, top);
-
- if (show_commodities_revalued)
- last_reported = balance;
- }
- } else {
- for (items_deque::const_iterator j = (*i)->subitems.begin();
- j != (*i)->subitems.end();
- j++) {
- (*j)->total = balance + (*j)->value;
-
- bool show = pred_obj(*j);
- if (show && first && show_commodities_revalued) {
- report_value_change(out, (*i)->date, balance, last_reported,
- predicate, first_line_format, next_lines_format);
- if (show_commodities_revalued_only)
- first = false;
- }
-
- balance += (*j)->value;
-
- if (show) {
- if (! show_commodities_revalued_only) {
- if (first) {
- first = false;
- first_line_format.format_elements(out, *j, *i);
- } else {
- next_lines_format.format_elements(out, *j, *i);
- }
- }
-
- if (show_commodities_revalued)
- last_reported = balance;
- }
- }
- }
- }
-
- if (show_commodities_revalued)
- report_value_change(out, -1, balance, last_reported, predicate,
- first_line_format, next_lines_format);
-}
-
-#endif
void set_price_conversion(const std::string& setting)
{
@@ -710,18 +601,17 @@ int main(int argc, char * argv[])
unsigned int xact_display_flags = MATCHING_TRANSACTIONS;
- if (command == "p" || command == "e") {
- show_expanded = true;
- }
- else if (command == "E") {
+ if (command == "p" || command == "e" || command == "E") {
+ xact_display_flags |= OTHER_TRANSACTIONS;
show_expanded = true;
}
- else if (show_related && command == "r") {
- xact_display_flags = OTHER_TRANSACTIONS;
- show_inverted = true;
- }
else if (show_related) {
- xact_display_flags |= OTHER_TRANSACTIONS;
+ if (command == "r") {
+ xact_display_flags = OTHER_TRANSACTIONS;
+ show_inverted = true;
+ } else {
+ xact_display_flags |= OTHER_TRANSACTIONS;
+ }
}
const char * f;
@@ -737,11 +627,9 @@ int main(int argc, char * argv[])
if (command == "b") {
format_t format(f);
format_account formatter(std::cout, format, display_predicate.get());
- formatter.start();
walk_accounts(journal->master, formatter, predicate.get(),
xact_display_flags, show_subtotals, show_expanded ? 0 : 1,
sort_order.get());
- formatter.finish();
if (! display_predicate.get() ||
item_predicate<account_t>(display_predicate.get())(journal->master)) {
@@ -766,12 +654,20 @@ int main(int argc, char * argv[])
format_transaction formatter(std::cout, format, nformat,
display_predicate.get(),
- ! show_subtotals, show_inverted);
- formatter.start();
-
+#ifdef COLLAPSED_REGISTER
+ ! show_subtotals,
+#endif
+ show_inverted);
if (! sort_order.get()) {
- walk_entries(journal->entries.begin(), journal->entries.end(),
- formatter, predicate.get(), xact_display_flags);
+ if (show_commodities_revalued) {
+ changed_value_filter<format_transaction>
+ filtered_formatter(formatter);
+ walk_entries(journal->entries.begin(), journal->entries.end(),
+ filtered_formatter, predicate.get(), xact_display_flags);
+ } else {
+ walk_entries(journal->entries.begin(), journal->entries.end(),
+ formatter, predicate.get(), xact_display_flags);
+ }
} else {
transactions_deque transactions_pool;
walk_entries(journal->entries.begin(), journal->entries.end(),
@@ -782,7 +678,6 @@ int main(int argc, char * argv[])
walk_transactions(transactions_pool.begin(), transactions_pool.end(),
formatter);
}
- formatter.finish();
}
// Save the cache, if need be
diff --git a/valexpr.cc b/valexpr.cc
index b1b53974..2889c602 100644
--- a/valexpr.cc
+++ b/valexpr.cc
@@ -153,6 +153,8 @@ void node_t::compute(balance_t& result, const details_t& details) const
case DATE:
if (details.entry)
result = (unsigned int) details.entry->date;
+ else
+ result = (unsigned int) std::time(NULL);
break;
case CLEARED:
@@ -207,12 +209,20 @@ void node_t::compute(balance_t& result, const details_t& details) const
left->compute(result, details);
std::time_t moment = -1;
- if (right && details.entry) {
+ if (right) {
switch (right->type) {
- case DATE: moment = details.entry->date; break;
+ case DATE:
+ if (details.entry)
+ moment = details.entry->date;
+ else
+ moment = std::time(NULL);
+ break;
+
default:
- throw compute_error("Invalid date passed to P(v,d)");
+ throw compute_error("Invalid date passed to P(value,date)");
}
+ } else {
+ moment = std::time(NULL);
}
result = result.value(moment);
break;
diff --git a/valexpr.h b/valexpr.h
index aadbb03f..a774472f 100644
--- a/valexpr.h
+++ b/valexpr.h
@@ -30,20 +30,18 @@ bool matches(const masks_list& regexps, const std::string& str,
struct details_t
{
- const entry_t * entry;
- const transaction_t * xact;
- const account_t * account;
- const unsigned int depth;
+ const entry_t * entry;
+ const transaction_t * xact;
+ const account_t * account;
details_t(const entry_t * _entry)
- : entry(_entry), xact(NULL), account(NULL), depth(0) {}
+ : entry(_entry), xact(NULL), account(NULL) {}
details_t(const transaction_t * _xact)
- : entry(_xact->entry), xact(_xact), account(_xact->account), depth(0) {}
+ : entry(_xact->entry), xact(_xact), account(_xact->account) {}
- details_t(const account_t * _account,
- const unsigned int _depth = 0)
- : entry(NULL), xact(NULL), account(_account), depth(_depth) {}
+ details_t(const account_t * _account)
+ : entry(NULL), xact(NULL), account(_account) {}
};
struct node_t
diff --git a/walk.h b/walk.h
index 850eb228..160dcc6a 100644
--- a/walk.h
+++ b/walk.h
@@ -161,7 +161,7 @@ inline void sort_accounts(account_t * account,
}
template <typename Function>
-void walk__accounts(const account_t * account,
+void walk__accounts(account_t * account,
const Function& functor,
const unsigned int max_depth)
{
@@ -174,7 +174,7 @@ void walk__accounts(const account_t * account,
}
template <typename Function>
-void walk__accounts_sorted(const account_t * account,
+void walk__accounts_sorted(account_t * account,
const Function& functor,
const unsigned int max_depth,
const node_t * sort_order)