summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/format.cc124
-rw-r--r--src/report.cc4
-rw-r--r--src/report.h26
3 files changed, 122 insertions, 32 deletions
diff --git a/src/format.cc b/src/format.cc
index 0fcbbdfd..4a48808a 100644
--- a/src/format.cc
+++ b/src/format.cc
@@ -59,6 +59,32 @@ void format_t::element_t::dump(std::ostream& out) const
}
}
+namespace {
+ expr_t parse_single_expression(const char *& p, bool single_expr = true)
+ {
+ string temp(p);
+ ptristream str(const_cast<char *&>(p));
+ expr_t expr;
+ expr.parse(str, single_expr ? expr_t::PARSE_SINGLE : expr_t::PARSE_PARTIAL,
+ &temp);
+ if (str.eof()) {
+ expr.set_text(p);
+ p += std::strlen(p);
+ } else {
+ assert(str.good());
+ istream_pos_type pos = str.tellg();
+ expr.set_text(string(p, p + long(pos)));
+ p += long(pos) - 1;
+
+ // Don't gobble up any whitespace
+ const char * base = p;
+ while (p >= base && std::isspace(*p))
+ p--;
+ }
+ return expr;
+ }
+}
+
format_t::element_t * format_t::parse_elements(const string& fmt)
{
std::auto_ptr<element_t> result;
@@ -171,24 +197,88 @@ format_t::element_t * format_t::parse_elements(const string& fmt)
break;
case '(':
- case '[': {
- std::istringstream str(p);
+ case '{': {
+ bool format_amount = *p == '{';
+ if (format_amount) p++;
+
current->type = element_t::EXPR;
- string temp(p);
- current->expr.parse(str, expr_t::PARSE_SINGLE, &temp);
- if (str.eof()) {
- current->expr.set_text(p);
- p += std::strlen(p);
- } else {
- assert(str.good());
- istream_pos_type pos = str.tellg();
- current->expr.set_text(string(p, p + long(pos)));
- p += long(pos) - 1;
-
- // Don't gobble up any whitespace
- const char * base = p;
- while (p >= base && std::isspace(*p))
- p--;
+ current->expr = parse_single_expression(p, ! format_amount);
+
+ // Wrap the subexpression in calls to justify and scrub
+ if (format_amount) {
+ if (! *p || *(p + 1) != '}')
+ throw_(format_error, _("Expected closing brace"));
+ else
+ p++;
+
+ expr_t::ptr_op_t op = current->expr.get_op();
+
+ expr_t::ptr_op_t amount_op;
+ expr_t::ptr_op_t colorize_op;
+ if (op->kind == expr_t::op_t::O_CONS) {
+ amount_op = op->left();
+ colorize_op = op->right();
+ } else {
+ amount_op = op;
+ }
+
+ expr_t::ptr_op_t scrub_node(new expr_t::op_t(expr_t::op_t::IDENT));
+ scrub_node->set_ident("scrub");
+
+ expr_t::ptr_op_t call1_node(new expr_t::op_t(expr_t::op_t::O_CALL));
+ call1_node->set_left(scrub_node);
+ call1_node->set_right(amount_op);
+
+ expr_t::ptr_op_t arg1_node(new expr_t::op_t(expr_t::op_t::VALUE));
+ expr_t::ptr_op_t arg2_node(new expr_t::op_t(expr_t::op_t::VALUE));
+ expr_t::ptr_op_t arg3_node(new expr_t::op_t(expr_t::op_t::VALUE));
+
+ arg1_node->set_value(current->min_width > 0 ? long(current->min_width) : -1);
+ arg2_node->set_value(current->max_width > 0 ? long(current->max_width) : -1);
+ arg3_node->set_value(! current->has_flags(ELEMENT_ALIGN_LEFT));
+
+ current->min_width = 0;
+ current->max_width = 0;
+
+ expr_t::ptr_op_t args1_node(new expr_t::op_t(expr_t::op_t::O_CONS));
+ args1_node->set_left(arg2_node);
+ args1_node->set_right(arg3_node);
+
+ expr_t::ptr_op_t args2_node(new expr_t::op_t(expr_t::op_t::O_CONS));
+ args2_node->set_left(arg1_node);
+ args2_node->set_right(args1_node);
+
+ expr_t::ptr_op_t args3_node(new expr_t::op_t(expr_t::op_t::O_CONS));
+ args3_node->set_left(call1_node);
+ args3_node->set_right(args2_node);
+
+ expr_t::ptr_op_t justify_node(new expr_t::op_t(expr_t::op_t::IDENT));
+ justify_node->set_ident("justify");
+
+ expr_t::ptr_op_t call2_node(new expr_t::op_t(expr_t::op_t::O_CALL));
+ call2_node->set_left(justify_node);
+ call2_node->set_right(args3_node);
+
+ string prev_expr = current->expr.text();
+
+ if (colorize_op) {
+ expr_t::ptr_op_t ansify_if_node(new expr_t::op_t(expr_t::op_t::IDENT));
+ ansify_if_node->set_ident("ansify_if");
+
+ expr_t::ptr_op_t args4_node(new expr_t::op_t(expr_t::op_t::O_CONS));
+ args4_node->set_left(call2_node);
+ args4_node->set_right(colorize_op);
+
+ expr_t::ptr_op_t call3_node(new expr_t::op_t(expr_t::op_t::O_CALL));
+ call3_node->set_left(ansify_if_node);
+ call3_node->set_right(args4_node);
+
+ current->expr = expr_t(call3_node);
+ } else {
+ current->expr = expr_t(call2_node);
+ }
+
+ current->expr.set_text(prev_expr);
}
break;
}
diff --git a/src/report.cc b/src/report.cc
index e1127339..2c145dc7 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -280,9 +280,9 @@ value_t report_t::fn_format_date(call_scope_t& args)
value_t report_t::fn_ansify_if(call_scope_t& scope)
{
- interactive_t args(scope, "vsb");
+ interactive_t args(scope, "v&s");
- if (args.get<bool>(2)) {
+ if (args.has(1)) {
string color = args.get<string>(1);
std::ostringstream buf;
if (color == "black") buf << "\e[30m";
diff --git a/src/report.h b/src/report.h
index 72f0af57..7bca98b8 100644
--- a/src/report.h
+++ b/src/report.h
@@ -237,12 +237,12 @@ public:
});
OPTION__(report_t, balance_format_, CTOR(report_t, balance_format_) {
- on("%(ansify_if(justify(scrub(display_total), 20, -1, true), \"red\", "
- " color & scrub(display_total) < 0))"
+ on("%(ansify_if(justify(scrub(display_total), 20, -1, true), "
+ " red if color & scrub(display_total) < 0))"
" %(!options.flat ? depth_spacer : \"\")"
- "%-(ansify_if(partial_account(options.flat), \"blue\", color))\n%/"
- "%(ansify_if(justify(scrub(display_total), 20, -1, true), \"red\", "
- " color & scrub(display_total) < 0))\n%/"
+ "%-(ansify_if(partial_account(options.flat), blue if color))\n%/"
+ "%(ansify_if(justify(scrub(display_total), 20, -1, true), "
+ " red if color & scrub(display_total) < 0))\n%/"
"--------------------\n");
});
@@ -551,26 +551,26 @@ public:
});
OPTION__(report_t, register_format_, CTOR(report_t, register_format_) {
- on("%(ansify_if(justify(date, date_width), \"green\", color & date > today))"
+ on("%(ansify_if(justify(date, date_width), green if color & date > today))"
" %(ansify_if(justify(truncated(payee, payee_width), payee_width), "
- " \"bold\", color & !cleared))"
+ " bold if color & !cleared))"
" %(ansify_if(justify(truncated(account, account_width, abbrev_len), "
- " account_width), \"blue\", color))"
+ " account_width), blue if color))"
" %(ansify_if(justify(scrub(display_amount), amount_width, "
" 3 + date_width + payee_width + account_width + amount_width, true), "
- " \"red\", color & scrub(display_amount) < 0))"
+ " red if color & scrub(display_amount) < 0))"
" %(ansify_if(justify(scrub(display_total), total_width, "
" 4 + date_width + payee_width + account_width + amount_width "
- " + total_width, true), \"red\", color & scrub(display_amount) < 0))\n%/"
+ " + total_width, true), red if color & scrub(display_amount) < 0))\n%/"
"%(justify(\" \", 2 + date_width + payee_width))"
"%(ansify_if(justify(truncated(account, account_width, abbrev_len), "
- " account_width), \"blue\", color))"
+ " account_width), blue if color))"
" %(ansify_if(justify(scrub(display_amount), amount_width, "
" 3 + date_width + payee_width + account_width + amount_width, true), "
- " \"red\", color & scrub(display_amount) < 0))"
+ " red if color & scrub(display_amount) < 0))"
" %(ansify_if(justify(scrub(display_total), total_width, "
" 4 + date_width + payee_width + account_width + amount_width "
- " + total_width, true), \"red\", color & scrub(display_amount) < 0))\n");
+ " + total_width, true), red if color & scrub(display_amount) < 0))\n");
});
OPTION(report_t, related); // -r