summaryrefslogtreecommitdiff
path: root/src/output.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2010-05-30 02:28:58 -0600
committerJohn Wiegley <johnw@newartisans.com>2010-05-30 02:47:40 -0600
commit647d4aac2fa474085d01f7ea1cebdc34fafd64a6 (patch)
treec17157d73c3a9d5dd182a4b7b0896e4f31e318be /src/output.cc
parenta41d33fba37460587f59ea0349ac4947a4de9f3c (diff)
downloadfork-ledger-647d4aac2fa474085d01f7ea1cebdc34fafd64a6.tar.gz
fork-ledger-647d4aac2fa474085d01f7ea1cebdc34fafd64a6.tar.bz2
fork-ledger-647d4aac2fa474085d01f7ea1cebdc34fafd64a6.zip
New: --group-by=EXPR and --group-title-format=FMT
The --group-by option allows for most reports to be split up into sections based on the varying value of EXPR. For example, to see register subtotals by payee, use: ledger reg --group-by=payee -s This works for separated balances too: ledger bal --group-by=payee Another interesting possibility is seeing a register of all the accounts affected by a related account: ledger reg -r --group-by=payee The option --group-title-format can be used to add a separator bar to the group titles. The option --no-titles can be used to drop titles altogether.
Diffstat (limited to 'src/output.cc')
-rw-r--r--src/output.cc55
1 files changed, 46 insertions, 9 deletions
diff --git a/src/output.cc b/src/output.cc
index 183d80b3..f697dee4 100644
--- a/src/output.cc
+++ b/src/output.cc
@@ -45,7 +45,7 @@ format_posts::format_posts(report_t& _report,
const optional<string>& _prepend_format,
std::size_t _prepend_width)
: report(_report), prepend_width(_prepend_width),
- last_xact(NULL), last_post(NULL)
+ last_xact(NULL), last_post(NULL), first_report_title(true)
{
TRACE_CTOR(format_posts, "report&, const string&, bool");
@@ -78,12 +78,30 @@ void format_posts::flush()
void format_posts::operator()(post_t& post)
{
- std::ostream& out(report.output_stream);
-
if (! post.has_xdata() ||
! post.xdata().has_flags(POST_EXT_DISPLAYED)) {
+ std::ostream& out(report.output_stream);
+
bind_scope_t bound_scope(report, post);
+ if (! report_title.empty()) {
+ if (first_report_title)
+ first_report_title = false;
+ else
+ out << '\n';
+
+ value_scope_t val_scope(string_value(report_title));
+ bind_scope_t inner_scope(bound_scope, val_scope);
+
+ format_t group_title_format;
+ group_title_format
+ .parse_format(report.HANDLER(group_title_format_).str());
+
+ out << group_title_format(inner_scope);
+
+ report_title = "";
+ }
+
if (prepend_format) {
out.width(prepend_width);
out << prepend_format(bound_scope);
@@ -113,7 +131,8 @@ format_accounts::format_accounts(report_t& _report,
const string& format,
const optional<string>& _prepend_format,
std::size_t _prepend_width)
- : report(_report), prepend_width(_prepend_width), disp_pred()
+ : report(_report), prepend_width(_prepend_width), disp_pred(),
+ first_report_title(true)
{
TRACE_CTOR(format_accounts, "report&, const string&");
@@ -144,19 +163,37 @@ std::size_t format_accounts::post_account(account_t& account, const bool flat)
if (account.xdata().has_flags(ACCOUNT_EXT_TO_DISPLAY) &&
! account.xdata().has_flags(ACCOUNT_EXT_DISPLAYED)) {
+ std::ostream& out(report.output_stream);
+
DEBUG("account.display", "Displaying account: " << account.fullname());
account.xdata().add_flags(ACCOUNT_EXT_DISPLAYED);
bind_scope_t bound_scope(report, account);
+ if (! report_title.empty()) {
+ if (first_report_title)
+ first_report_title = false;
+ else
+ out << '\n';
+
+ value_scope_t val_scope(string_value(report_title));
+ bind_scope_t inner_scope(bound_scope, val_scope);
+
+ format_t group_title_format;
+ group_title_format
+ .parse_format(report.HANDLER(group_title_format_).str());
+
+ out << group_title_format(inner_scope);
+
+ report_title = "";
+ }
+
if (prepend_format) {
- static_cast<std::ostream&>(report.output_stream).width(prepend_width);
- static_cast<std::ostream&>(report.output_stream)
- << prepend_format(bound_scope);
+ out.width(prepend_width);
+ out << prepend_format(bound_scope);
}
- static_cast<std::ostream&>(report.output_stream)
- << account_line_format(bound_scope);
+ out << account_line_format(bound_scope);
return 1;
}