summaryrefslogtreecommitdiff
path: root/format.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2008-08-03 23:44:18 -0400
committerJohn Wiegley <johnw@newartisans.com>2008-08-03 23:44:18 -0400
commitbcffbc96ba88bd19f5f8ac00015ff38131fd6466 (patch)
tree7f4a9646bb05f138b00cdc7127dd45cc05142cb5 /format.cc
parent8a21391d0a6d6187855b40530f25b1d8beb0d67a (diff)
downloadfork-ledger-bcffbc96ba88bd19f5f8ac00015ff38131fd6466.tar.gz
fork-ledger-bcffbc96ba88bd19f5f8ac00015ff38131fd6466.tar.bz2
fork-ledger-bcffbc96ba88bd19f5f8ac00015ff38131fd6466.zip
Regular expressions are working again, such that very basic register reports
are now possible.
Diffstat (limited to 'format.cc')
-rw-r--r--format.cc413
1 files changed, 8 insertions, 405 deletions
diff --git a/format.cc b/format.cc
index 035f9268..65dfce95 100644
--- a/format.cc
+++ b/format.cc
@@ -272,430 +272,33 @@ void format_t::format(std::ostream& out_str, scope_t& scope)
try {
elem->expr.compile(scope);
+ value_t value;
if (elem->expr.is_function()) {
call_scope_t args(scope);
args.push_back(long(elem->max_width));
- elem->expr.get_function()(args).dump(out, elem->min_width);
+ value = elem->expr.get_function()(args);
} else {
- elem->expr.calc(scope).dump(out, elem->min_width);
+ value = elem->expr.calc(scope);
}
+ value.strip_annotations().dump(out, elem->min_width);
}
catch (const calc_error&) {
out << (string("%") + elem->chars);
}
break;
-#if 0
- case element_t::ACCOUNT_FULLNAME:
- scope.resolve("account").dump(out, elem->min_width);
- break;
- case element_t::ACCOUNT_NAME:
- scope.resolve("account_base").dump(out, elem->min_width);
- break;
-
- case element_t::AMOUNT:
- out << "a";
- //out << scope.resolve("amount");
- break;
- case element_t::TOTAL:
- out << "T";
- //out << scope.resolve("total");
- break;
-
- case element_t::VALUE_EXPR: {
- expr_t * calc;
- switch (elem->type) {
- case element_t::AMOUNT:
- assert(value_expr::amount_expr.get());
- calc = value_expr::amount_expr.get();
- break;
- case element_t::TOTAL:
- assert(value_expr::total_expr.get());
- calc = value_expr::total_expr.get();
- break;
- case element_t::VALUE_EXPR:
- calc = const_cast<value_expr *>(&elem->val_expr);
- break;
- default:
- assert(false);
- break;
- }
- if (! calc)
- break;
-
- value_t value;
- const balance_t * bal = NULL;
-
- calc->compute(value, details);
-
- if (! amount_t::keep_price ||
- ! amount_t::keep_date ||
- ! amount_t::keep_tag) {
- switch (value.type()) {
- case value_t::AMOUNT:
- case value_t::BALANCE:
- case value_t::BALANCE_PAIR:
- value = value.strip_annotations();
- break;
- default:
- break;
- }
- }
-
- bool highlighted = false;
-
- switch (value.type()) {
- case value_t::BOOLEAN:
- out << (value.as_boolean() ? "true" : "false");
- break;
-
- case value_t::INTEGER:
- if (ansi_codes && elem->flags & ELEMENT_HIGHLIGHT) {
- if (ansi_invert) {
- if (value.as_long() > 0) {
- mark_red(out, elem);
- highlighted = true;
- }
- } else {
- if (value.as_long() < 0) {
- mark_red(out, elem);
- highlighted = true;
- }
- }
- }
- out << value.as_long();
- break;
-
- case value_t::DATETIME:
- out << value.as_datetime();
- break;
-
- case value_t::AMOUNT:
- if (ansi_codes && elem->flags & ELEMENT_HIGHLIGHT) {
- if (ansi_invert) {
- if (value.as_amount().sign() > 0) {
- mark_red(out, elem);
- highlighted = true;
- }
- } else {
- if (value.as_amount().sign() < 0) {
- mark_red(out, elem);
- highlighted = true;
- }
- }
- }
- out << value.as_amount();
- break;
-
- case value_t::BALANCE:
- bal = &(value.as_balance());
- // fall through...
-
- case value_t::BALANCE_PAIR:
- if (! bal)
- bal = &(value.as_balance_pair().quantity());
-
- if (ansi_codes && elem->flags & ELEMENT_HIGHLIGHT) {
- if (ansi_invert) {
- if (*bal > 0) {
- mark_red(out, elem);
- highlighted = true;
- }
- } else {
- if (*bal < 0) {
- mark_red(out, elem);
- highlighted = true;
- }
- }
- }
- bal->print(out, elem->min_width,
- (elem->max_width > 0 ?
- elem->max_width : elem->min_width));
-
- ignore_max_width = true;
- break;
- default:
- assert(false);
- break;
- }
-
- if (highlighted)
- mark_plain(out);
- break;
- }
-
- case element_t::OPT_AMOUNT:
- if (details.xact) {
- string disp;
- bool use_disp = false;
-
- if (details.xact->cost && details.xact->amount) {
- std::ostringstream stream;
- if (! details.xact->amount_expr.expr_str.empty())
- stream << details.xact->amount_expr.expr_str;
- else
- stream << details.xact->amount.strip_annotations();
-
- if (details.xact->cost_expr)
- stream << details.xact->cost_expr->expr_str;
- else
- stream << " @ " << amount_t(*details.xact->cost /
- details.xact->amount).unround();
- disp = stream.str();
- use_disp = true;
- }
- else if (details.entry) {
- unsigned int xacts_count = 0;
- xact_t * first = NULL;
- xact_t * last = NULL;
-
- foreach (const transaction_t * xact, details.entry->xacts) {
- if (xact_has_xdata(*xact) &&
- xact_xdata_(*xact).dflags & XACT_TO_DISPLAY) {
- xacts_count++;
- if (! first)
- first = xact;
- last = xact;
- }
- }
-
- use_disp = (xacts_count == 2 && details.xact == last &&
- first->amount == - last->amount);
- }
-
- if (! use_disp) {
- if (! details.xact->amount_expr.expr_str.empty())
- out << details.xact->amount_expr.expr_str;
- else
- out << details.xact->amount.strip_annotations();
- } else {
- out << disp;
- }
- }
- break;
-
- case element_t::SOURCE:
- if (details.entry && details.entry->journal) {
- int idx = details.entry->src_idx;
- foreach (const path& path, details.entry->journal->sources)
- if (! idx--) {
- out << path;
- break;
- }
- }
- break;
-
- case element_t::ENTRY_BEG_POS:
- if (details.entry)
- out << (unsigned long)details.entry->beg_pos;
- break;
-
- case element_t::ENTRY_BEG_LINE:
- if (details.entry)
- out << details.entry->beg_line;
- break;
-
- case element_t::ENTRY_END_POS:
- if (details.entry)
- out << (unsigned long)details.entry->end_pos;
- break;
-
- case element_t::ENTRY_END_LINE:
- if (details.entry)
- out << details.entry->end_line;
- break;
-
- case element_t::XACT_BEG_POS:
- if (details.xact)
- out << (unsigned long)details.xact->beg_pos;
- break;
-
- case element_t::XACT_BEG_LINE:
- if (details.xact)
- out << details.xact->beg_line;
- break;
-
- case element_t::XACT_END_POS:
- if (details.xact)
- out << (unsigned long)details.xact->end_pos;
- break;
-
- case element_t::XACT_END_LINE:
- if (details.xact)
- out << details.xact->end_line;
- break;
-
- case element_t::DATE_STRING:
- out << format_date(scope.resolve("date").as_date());
- break;
-
- case element_t::COMPLETE_DATE_STRING: {
- date_t actual_date;
- date_t effective_date;
- if (details.xact) {
- actual_date = details.xact->actual_date();
- effective_date = details.xact->effective_date();
- }
- else if (details.entry) {
- actual_date = details.entry->actual_date();
- effective_date = details.entry->effective_date();
- }
-
- char abuf[256];
-#if 0
- // jww (2008-04-20): This needs to be rewritten
- std::strftime(abuf, 255, elem->chars.c_str(), actual_date.localtime());
-#else
- abuf[0] = '\0';
-#endif
-
- if (is_valid(effective_date) && effective_date != actual_date) {
- char buf[512];
- char ebuf[256];
-#if 0
- // jww (2008-04-20): This needs to be rewritten
- std::strftime(ebuf, 255, elem->chars.c_str(),
- effective_date.localtime());
-#else
- ebuf[0] = '\0';
-#endif
-
- std::strcpy(buf, abuf);
- std::strcat(buf, "=");
- std::strcat(buf, ebuf);
-
- out << (elem->max_width == 0 ? buf : truncate(buf, elem->max_width));
- } else {
- out << (elem->max_width == 0 ? abuf : truncate(abuf, elem->max_width));
- }
- break;
- }
-
- case element_t::CLEARED:
- if (details.xact) {
- switch (details.xact->state) {
- case xact_t::CLEARED:
- out << "* ";
- break;
- case xact_t::PENDING:
- out << "! ";
- break;
- case xact_t::UNCLEARED:
- break;
- }
- }
- break;
-
- case element_t::ENTRY_CLEARED:
- if (details.entry) {
- xact_t::state_t state;
- if (details.entry->get_state(&state))
- switch (state) {
- case xact_t::CLEARED:
- out << "* ";
- break;
- case xact_t::PENDING:
- out << "! ";
- break;
- case xact_t::UNCLEARED:
- break;
- }
- }
- break;
-
- case element_t::CODE: {
- string temp;
- if (details.entry && details.entry->code) {
- temp += "(";
- temp += *details.entry->code;
- temp += ") ";
- }
- out << temp;
- break;
- }
-
- case element_t::PAYEE:
- scope.resolve("payee").dump(out, elem->min_width);
- break;
-
- case element_t::OPT_NOTE:
- if (details.xact && details.xact->note)
- out << " ; ";
- // fall through...
-
- case element_t::NOTE:
- if (details.xact)
- out << (elem->max_width == 0 ?
- details.xact->note : truncate(*details.xact->note,
- elem->max_width));
- break;
-
- case element_t::OPT_ACCOUNT:
- if (details.entry && details.xact) {
- xact_t::state_t state;
- if (! details.entry->get_state(&state))
- switch (details.xact->state) {
- case xact_t::CLEARED:
- name = "* ";
- break;
- case xact_t::PENDING:
- name = "! ";
- break;
- case xact_t::UNCLEARED:
- break;
- }
- }
- // fall through...
-
- case element_t::ACCOUNT_NAME:
- case element_t::ACCOUNT_FULLNAME:
- if (details.account) {
- name += (elem->type == element_t::ACCOUNT_FULLNAME ?
- details.account->fullname() :
- partial_account_name(*details.account));
-
- if (details.xact && details.xact->has_flags(XACT_VIRTUAL)) {
- if (elem->max_width > 2)
- name = truncate(name, elem->max_width - 2, true);
-
- if (details.xact->has_flags(XACT_BALANCE))
- name = string("[") + name + "]";
- else
- name = string("(") + name + ")";
- }
- else if (elem->max_width > 0)
- name = truncate(name, elem->max_width, true);
-
- out << name;
- } else {
- out << " ";
- }
- break;
-
- case element_t::DEPTH_SPACER:
- for (const account_t * acct = details.account;
- acct;
- acct = acct->parent)
- if (account_has_xdata(*acct) &&
- account_xdata_(*acct).dflags & 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;
-#endif
-
default:
assert(false);
break;
}
string temp = out.str();
+
if (! ignore_max_width &&
elem->max_width > 0 && elem->max_width < temp.length())
- truncate(temp, elem->max_width);
- out_str << temp;
+ out_str << truncate(temp, elem->max_width);
+ else
+ out_str << temp;
}
}