diff options
author | John Wiegley <johnw@newartisans.com> | 2010-12-22 15:34:06 -0500 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2010-12-22 15:34:06 -0500 |
commit | 958a61ede5916f7c71245ab3f7c1c96bc1f6abe0 (patch) | |
tree | 532a60ef9734970016a13ba97d90a402c2b7b0de | |
parent | dafe7c891af6e6c65a96c17ffe078adf124cc895 (diff) | |
download | fork-ledger-958a61ede5916f7c71245ab3f7c1c96bc1f6abe0.tar.gz fork-ledger-958a61ede5916f7c71245ab3f7c1c96bc1f6abe0.tar.bz2 fork-ledger-958a61ede5916f7c71245ab3f7c1c96bc1f6abe0.zip |
New command: org, for displaying Org-mode tables
-rw-r--r-- | src/org.cc | 200 | ||||
-rw-r--r-- | src/org.h | 94 | ||||
-rw-r--r-- | src/report.cc | 10 | ||||
-rw-r--r-- | tools/Makefile.am | 2 |
4 files changed, 306 insertions, 0 deletions
diff --git a/src/org.cc b/src/org.cc new file mode 100644 index 00000000..7c8e8c0d --- /dev/null +++ b/src/org.cc @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of New Artisans LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <system.hh> + +#include "org.h" +#include "xact.h" +#include "post.h" +#include "account.h" +#include "journal.h" +#include "pool.h" +#include "report.h" + +namespace ledger { + +posts_to_org_table::posts_to_org_table(report_t& _report, + const optional<string>& _prepend_format) + : report(_report), last_xact(NULL), last_post(NULL) +{ + TRACE_CTOR(posts_to_org_table, "report&, optional<string>"); + + first_line_format.parse_format + ("|%(format_date(date))" + "|%(code)" + "|%(payee)" + "|%(cleared ? \"*\" : (pending ? \"!\" : \"\"))" + "|%(display_account)" + "|%(scrub(top_amount(display_amount)))" + "|%(scrub(top_amount(display_total)))" + "|%(join(note | xact.note))\n"); + + next_lines_format.parse_format + ("|" + "|" + "|%(has_tag(\"Payee\") ? payee : \"\")" + "|%(cleared ? \"*\" : (pending ? \"!\" : \"\"))" + "|%(display_account)" + "|%(scrub(top_amount(display_amount)))" + "|%(scrub(top_amount(display_total)))" + "|%(join(note | xact.note))\n"); + + amount_lines_format.parse_format + ("|" + "|" + "|" + "|" + "|" + "|%(scrub(next_amount))" + "|%(scrub(next_total))" + "|\n"); + + if (_prepend_format) + prepend_format.parse_format(*_prepend_format); +} + +void posts_to_org_table::flush() +{ + report.output_stream.flush(); +} + +void posts_to_org_table::operator()(post_t& post) +{ + 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 (! header_printed) { + out << "|Date|Code|Payee|X|Account|Amount|Total|Note|\n" + << "|-|\n" + << "|||<20>|||<r>|<r>|<20>|\n"; + header_printed = true; + } + + if (! report_title.empty()) { + if (first_report_title) + first_report_title = false; + else + out << '\n'; + + value_scope_t val_scope(bound_scope, string_value(report_title)); + format_t group_title_format(report.HANDLER(group_title_format_).str()); + + out << "|-|\n"; + out << '|' << group_title_format(val_scope); + out << "|-|\n"; + + report_title = ""; + } + + if (prepend_format) + out << '|' << prepend_format(bound_scope); + + if (last_xact != post.xact) { + out << first_line_format(bound_scope); + last_xact = post.xact; + } + else if (last_post && last_post->date() != post.date()) { + out << first_line_format(bound_scope); + } + else { + out << next_lines_format(bound_scope); + } + + value_t amt = expr_t("display_amount").calc(bound_scope).simplified(); + value_t tot = expr_t("display_total").calc(bound_scope).simplified(); + + if (amt.type() == value_t::BALANCE || tot.type() == value_t::BALANCE) { + balance_t amt_bal(amt.to_balance()); + balance_t tot_bal(tot.to_balance()); + balance_t::amounts_map::const_iterator i = amt_bal.amounts.begin(); + balance_t::amounts_map::const_iterator j = tot_bal.amounts.begin(); + bool first = true; + while (i != amt_bal.amounts.end() || j != tot_bal.amounts.end()) { + if (first) { + first = false; + if (i != amt_bal.amounts.end()) ++i; + if (j != tot_bal.amounts.end()) ++j; + } else { + symbol_scope_t call_scope(bound_scope); + bool assigned = false; + + if (i != amt_bal.amounts.end()) { + if ((*i).second) { + DEBUG("org.next_amount", "next_amount = " << (*i).second); + call_scope.define(symbol_t::FUNCTION, "next_amount", + expr_t::op_t::wrap_value((*i++).second)); + assigned = true; + } else { + call_scope.define(symbol_t::FUNCTION, "next_amount", + expr_t::op_t::wrap_value(string_value(""))); + ++i; + } + } else { + call_scope.define(symbol_t::FUNCTION, "next_amount", + expr_t::op_t::wrap_value(string_value(""))); + } + + if (j != tot_bal.amounts.end()) { + if ((*j).second) { + DEBUG("org.next_total", "next_total = " << (*j).second); + call_scope.define(symbol_t::FUNCTION, "next_total", + expr_t::op_t::wrap_value((*j++).second)); + DEBUG("org.next_total", "2.next_total = " << + call_scope.lookup(symbol_t::FUNCTION, + "next_total")->as_value()); + assigned = true; + } else { + call_scope.define(symbol_t::FUNCTION, "next_total", + expr_t::op_t::wrap_value(string_value(""))); + ++j; + } + } else { + call_scope.define(symbol_t::FUNCTION, "next_total", + expr_t::op_t::wrap_value(string_value(""))); + } + + if (assigned) { + amount_lines_format.mark_uncompiled(); + out << amount_lines_format(call_scope); + } + } + } + } + + post.xdata().add_flags(POST_EXT_DISPLAYED); + last_post = &post; + } +} + +} // namespace ledger diff --git a/src/org.h b/src/org.h new file mode 100644 index 00000000..ed023be2 --- /dev/null +++ b/src/org.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2003-2010, John Wiegley. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of New Artisans LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @addtogroup data + */ + +/** + * @file org.h + * @author John Wiegley + * + * @ingroup data + */ +#ifndef _ORG_H +#define _ORG_H + +#include "chain.h" +#include "format.h" + +namespace ledger { + +class xact_t; +class post_t; +class report_t; + +class posts_to_org_table : public item_handler<post_t> +{ +protected: + typedef std::list<xact_t *> xacts_list; + typedef std::map<xact_t *, bool> xacts_present_map; + + report_t& report; + format_t first_line_format; + format_t next_lines_format; + format_t amount_lines_format; + format_t prepend_format; + xact_t * last_xact; + post_t * last_post; + bool header_printed; + bool first_report_title; + string report_title; + +public: + posts_to_org_table(report_t& _report, + const optional<string>& _prepend_format = none); + virtual ~posts_to_org_table() { + TRACE_DTOR(posts_to_org_table); + } + + virtual void flush(); + virtual void operator()(post_t& post); + + virtual void clear() { + last_xact = NULL; + last_post = NULL; + header_printed = false; + first_report_title = true; + report_title = ""; + + item_handler<post_t>::clear(); + } +}; + +} // namespace ledger + +#endif // _ORG_H diff --git a/src/report.cc b/src/report.cc index 8af1a459..e98596a3 100644 --- a/src/report.cc +++ b/src/report.cc @@ -47,6 +47,7 @@ #include "convert.h" #include "xml.h" #include "emacs.h" +#include "org.h" namespace ledger { @@ -1430,6 +1431,15 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, } break; + case 'o': + if (is_eq(p, "org")) { + return WRAP_FUNCTOR + (reporter<> + (new posts_to_org_table(*this, maybe_format(HANDLER(prepend_format_))), + *this, "#org")); + } + break; + case 'p': if (*(p + 1) == '\0' || is_eq(p, "print")) { return WRAP_FUNCTOR diff --git a/tools/Makefile.am b/tools/Makefile.am index ad096896..712b0f30 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -77,6 +77,7 @@ libledger_report_la_SOURCES = \ src/convert.cc \ src/draft.cc \ src/emacs.cc \ + src/org.cc \ src/xml.cc \ src/print.cc \ src/output.cc \ @@ -145,6 +146,7 @@ pkginclude_HEADERS = \ src/output.h \ src/xml.h \ src/emacs.h \ + src/org.h \ \ src/global.h \ \ |